From 50cf94da7e57a9e83d7c0753dd55eae5fd55455a Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 20 Mar 1998 17:16:31 +0000 Subject: SH port submitted from Ralf Corsepius . --- c/src/lib/libcpu/sh/sh7032/score/cpu_asm.c | 311 +++++++++++++++++++++++++++ c/src/lib/libcpu/sh/sh7032/score/ispsh7032.c | 252 ++++++++++++++++++++++ 2 files changed, 563 insertions(+) create mode 100644 c/src/lib/libcpu/sh/sh7032/score/cpu_asm.c create mode 100644 c/src/lib/libcpu/sh/sh7032/score/ispsh7032.c (limited to 'c/src/lib/libcpu/sh/sh7032') diff --git a/c/src/lib/libcpu/sh/sh7032/score/cpu_asm.c b/c/src/lib/libcpu/sh/sh7032/score/cpu_asm.c new file mode 100644 index 0000000000..42764f6eb1 --- /dev/null +++ b/c/src/lib/libcpu/sh/sh7032/score/cpu_asm.c @@ -0,0 +1,311 @@ +/* + * This file contains the basic algorithms for all assembly code used + * in an specific CPU port of RTEMS. These algorithms must be implemented + * in assembly language + * + * NOTE: This port uses a C file with inline assembler instructions + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * + * COPYRIGHT (c) 1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + */ + +/* + * This is supposed to be an assembly file. This means that system.h + * and cpu.h should not be included in a "real" cpu_asm file. An + * implementation in assembly should include "cpu_asm.h" + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* from cpu_isps.c */ +extern proc_ptr _Hardware_isr_Table[]; + +#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + unsigned long *_old_stack_ptr; +#endif + +register unsigned long *stack_ptr asm("r15"); + +/* + * sh_set_irq_priority + * + * this function sets the interrupt level of the specified interrupt + * + * parameters: + * - irq : interrupt number + * - prio: priority to set for this interrupt number + * + * returns: 0 if ok + * -1 on error + */ + +unsigned int sh_set_irq_priority( + unsigned int irq, + unsigned int prio ) +{ + unsigned32 shiftcount; + unsigned32 prioreg; + unsigned16 temp16; + unsigned32 level; + + /* + * first check for valid interrupt + */ + if(( irq > 113) || (_Hardware_isr_Table[irq] == _dummy_isp)) + return -1; + /* + * check for valid irq priority + */ + if( prio > 15 ) + return -1; + + /* + * look up appropriate interrupt priority register + */ + if( irq > 71) + { + irq = irq - 72; + shiftcount = 12 - ((irq & ~0x03) % 16); + + switch( irq / 16) + { + case 0: { prioreg = INTC_IPRC; break;} + case 1: { prioreg = INTC_IPRD; break;} + case 2: { prioreg = INTC_IPRE; break;} + default: return -1; + } + } + else + { + shiftcount = 12 - 4 * ( irq % 4); + if( irq > 67) + prioreg = INTC_IPRB; + else + prioreg = INTC_IPRA; + } + + /* + * Set the interrupt priority register + */ + _CPU_ISR_Disable( level ); + + temp16 = read16( prioreg); + temp16 &= ~( 15 << shiftcount); + temp16 |= prio << shiftcount; + write16( temp16, prioreg); + + _CPU_ISR_Enable( level ); + + return 0; +} + +/* + * _CPU_Context_save_fp_context + * + * This routine is responsible for saving the FP context + * at *fp_context_ptr. If the point to load the FP context + * from is changed then the pointer is modified by this routine. + * + * Sometimes a macro implementation of this is in cpu.h which dereferences + * the ** and a similarly named routine in this file is passed something + * like a (Context_Control_fp *). The general rule on making this decision + * is to avoid writing assembly language. + */ + +void _CPU_Context_save_fp( + void **fp_context_ptr +) +{ +} + +/* + * _CPU_Context_restore_fp_context + * + * This routine is responsible for restoring the FP context + * at *fp_context_ptr. If the point to load the FP context + * from is changed then the pointer is modified by this routine. + * + * Sometimes a macro implementation of this is in cpu.h which dereferences + * the ** and a similarly named routine in this file is passed something + * like a (Context_Control_fp *). The general rule on making this decision + * is to avoid writing assembly language. + */ + +void _CPU_Context_restore_fp( + void **fp_context_ptr +) +{ +} + +/* _CPU_Context_switch + * + * This routine performs a normal non-FP context switch. + */ + +/* within __CPU_Context_switch: + * _CPU_Context_switch + * _CPU_Context_restore + * + * This routine is generally used only to restart self in an + * efficient manner. It may simply be a label in _CPU_Context_switch. + * + * NOTE: It should be safe not to store r4, r5 + * + * NOTE: It is doubtful if r0 is really needed to be stored + * + * NOTE: gbr is added, but should not be necessary, as it is + * only used globally in this port. + */ + +/* + * FIXME: This is an ugly hack, but we wanted to avoid recalculating + * the offset each time Context_Control is changed + */ +void __CPU_Context_switch( + Context_Control *run, /* r4 */ + Context_Control *heir /* r5 */ +) +{ + +asm volatile(" + .global __CPU_Context_switch +__CPU_Context_switch: + + add %0,r4 + + stc.l sr,@-r4 + stc.l gbr,@-r4 + mov.l r0,@-r4 + mov.l r1,@-r4 + mov.l r2,@-r4 + mov.l r3,@-r4 + + mov.l r6,@-r4 + mov.l r7,@-r4 + mov.l r8,@-r4 + mov.l r9,@-r4 + mov.l r10,@-r4 + mov.l r11,@-r4 + mov.l r12,@-r4 + mov.l r13,@-r4 + mov.l r14,@-r4 + sts.l pr,@-r4 + sts.l mach,@-r4 + sts.l macl,@-r4 + mov.l r15,@-r4 + + mov r5, r4" + :: "I" (sizeof(Context_Control)) + ); + + asm volatile(" + .global __CPU_Context_restore +__CPU_Context_restore: + mov.l @r4+,r15 + lds.l @r4+,macl + lds.l @r4+,mach + lds.l @r4+,pr + mov.l @r4+,r14 + mov.l @r4+,r13 + mov.l @r4+,r12 + mov.l @r4+,r11 + mov.l @r4+,r10 + mov.l @r4+,r9 + mov.l @r4+,r8 + mov.l @r4+,r7 + mov.l @r4+,r6 + + mov.l @r4+,r3 + mov.l @r4+,r2 + mov.l @r4+,r1 + mov.l @r4+,r0 + ldc.l @r4+,gbr + ldc.l @r4+,sr + + rts + nop" ); +} + +/* + * This routine provides the RTEMS interrupt management. + */ + +void __ISR_Handler( unsigned32 vector) +{ + register unsigned32 level; + + _CPU_ISR_Disable( level ); + + _Thread_Dispatch_disable_level++; + +#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + if( _ISR_Nest_level == 0 ) + { + /* Install irq stack */ + _old_stack_ptr = stack_ptr; + stack_ptr = _CPU_Interrupt_stack_high; + } + +#endif + + _ISR_Nest_level++; + + _CPU_ISR_Enable( level ); + + /* call isp */ + if( _ISR_Vector_table[ vector]) + (*_ISR_Vector_table[ vector ])( vector ); + + _CPU_ISR_Disable( level ); + + _ISR_Nest_level--; + +#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + + if( _ISR_Nest_level == 0 ) + /* restore old stack pointer */ + stack_ptr = _old_stack_ptr; +#endif + + _Thread_Dispatch_disable_level--; + + _CPU_ISR_Enable( level ); + + if ( _Thread_Dispatch_disable_level == 0 ) + { + if(( _Context_Switch_necessary) || (! _ISR_Signals_to_thread_executing)) + { + _ISR_Signals_to_thread_executing = FALSE; + _Thread_Dispatch(); + } + } +} diff --git a/c/src/lib/libcpu/sh/sh7032/score/ispsh7032.c b/c/src/lib/libcpu/sh/sh7032/score/ispsh7032.c new file mode 100644 index 0000000000..1643785810 --- /dev/null +++ b/c/src/lib/libcpu/sh/sh7032/score/ispsh7032.c @@ -0,0 +1,252 @@ +/* + * This file contains the isp frames for the user interrupts. + * From these procedures __ISR_Handler is called with the vector number + * as argument. + * + * __ISR_Handler is kept in a separate file (cpu_asm.c), because a bug in + * some releases of gcc doesn't properly handle #pragma interrupt, if a + * file contains both isrs and normal functions. + * + * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and + * Bernd Becker (becker@faw.uni-ulm.de) + * + * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE + * + * + * COPYRIGHT (c) 1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include +#include + +/* + * This is a exception vector table + * + * It has the same structure like the actual vector table (vectab) + */ +proc_ptr _Hardware_isr_Table[256]={ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, +_nmi_isp, _usb_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, +/* trapa 0 -31 */ +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +_dummy_isp, _dummy_isp, _dummy_isp, _dummy_isp, +/* irq 64 ... */ +_irq0_isp, _irq1_isp, _irq2_isp, _irq3_isp, +_irq4_isp, _irq5_isp, _irq6_isp, _irq7_isp, +_dma0_isp, _dummy_isp, _dma1_isp, _dummy_isp, +_dma2_isp, _dummy_isp, _dma3_isp, _dummy_isp, +_imia0_isp, _imib0_isp, _ovi0_isp, _dummy_isp, +_imia1_isp, _imib1_isp, _ovi1_isp, _dummy_isp, +_imia2_isp, _imib2_isp, _ovi2_isp, _dummy_isp, +_imia3_isp, _imib3_isp, _ovi3_isp, _dummy_isp, +_imia4_isp, _imib4_isp, _ovi4_isp, _dummy_isp, +_eri0_isp, _rxi0_isp, _txi0_isp, _tei0_isp, +_eri1_isp, _rxi1_isp, _txi1_isp, _tei1_isp, +_prt_isp, _adu_isp, _dummy_isp, _dummy_isp, +_wdt_isp, +/* 113 */ _dref_isp +}; + +#define Str(a)#a + +/* + * Some versions of gcc and all version of egcs at least until egcs-1.0.2 + * are not able to handle #praga interrupt correctly if more than 1 isr is + * contained in a file and when optimizing. + * We try to work around this problem by using the macro below. + */ +#define isp( name, number, func)\ +asm (".global _"Str(name)"\n\t" \ + "_"Str(name)": \n\t" \ + " mov.l r0,@-r15 \n\t" \ + " mov.l r1,@-r15 \n\t" \ + " mov.l r2,@-r15 \n\t" \ + " mov.l r3,@-r15 \n\t" \ + " mov.l r4,@-r15 \n\t" \ + " mov.l r5,@-r15 \n\t" \ + " mov.l r6,@-r15 \n\t" \ + " mov.l r7,@-r15 \n\t" \ + " mov.l r14,@-r15 \n\t" \ + " sts.l pr,@-r15 \n\t" \ + " sts.l mach,@-r15 \n\t" \ + " sts.l macl,@-r15 \n\t" \ + " mov r15,r14 \n\t" \ + " mov.l "Str(name)"_k, r1\n\t" \ + " jsr @r1 \n\t" \ + " mov #"Str(number)", r4\n\t" \ + " mov r14,r15 \n\t" \ + " lds.l @r15+,macl \n\t" \ + " lds.l @r15+,mach \n\t" \ + " lds.l @r15+,pr \n\t" \ + " mov.l @r15+,r14 \n\t" \ + " mov.l @r15+,r7 \n\t" \ + " mov.l @r15+,r6 \n\t" \ + " mov.l @r15+,r5 \n\t" \ + " mov.l @r15+,r4 \n\t" \ + " mov.l @r15+,r3 \n\t" \ + " mov.l @r15+,r2 \n\t" \ + " mov.l @r15+,r1 \n\t" \ + " mov.l @r15+,r0 \n\t" \ + " rte \n\t" \ + " nop \n\t" \ + " .align 2 \n\t" \ + #name"_k: \n\t" \ + ".long "Str(func)); + +/************************************************ + * Dummy interrupt service procedure for + * interrupts being not allowed --> Trap 34 + ************************************************/ +asm(" .section .text +.global __dummy_isp +__dummy_isp: + mov.l r14,@-r15 + mov r15, r14 + trapa #34 + mov.l @r15+,r14 + rte + nop"); + +/***************************** + * Non maskable interrupt + *****************************/ +isp( _nmi_isp, NMI_ISP_V, ___ISR_Handler); + +/***************************** + * User break controller + *****************************/ +isp( _usb_isp, USB_ISP_V, ___ISR_Handler); + +/***************************** + * External interrupts 0-7 + *****************************/ +isp( _irq0_isp, IRQ0_ISP_V, ___ISR_Handler); +isp( _irq1_isp, IRQ1_ISP_V, ___ISR_Handler); +isp( _irq2_isp, IRQ2_ISP_V, ___ISR_Handler); +isp( _irq3_isp, IRQ3_ISP_V, ___ISR_Handler); +isp( _irq4_isp, IRQ4_ISP_V, ___ISR_Handler); +isp( _irq5_isp, IRQ5_ISP_V, ___ISR_Handler); +isp( _irq6_isp, IRQ6_ISP_V, ___ISR_Handler); +isp( _irq7_isp, IRQ7_ISP_V, ___ISR_Handler); + +/***************************** + * DMA - controller + *****************************/ +isp( _dma0_isp, DMA0_ISP_V, ___ISR_Handler); +isp( _dma1_isp, DMA1_ISP_V, ___ISR_Handler); +isp( _dma2_isp, DMA2_ISP_V, ___ISR_Handler); +isp( _dma3_isp, DMA3_ISP_V, ___ISR_Handler); + + +/***************************** + * Interrupt timer unit + *****************************/ + +/***************************** + * Timer 0 + *****************************/ +isp( _imia0_isp, IMIA0_ISP_V, ___ISR_Handler); +isp( _imib0_isp, IMIB0_ISP_V, ___ISR_Handler); +isp( _ovi0_isp, OVI0_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 1 + *****************************/ +isp( _imia1_isp, IMIA1_ISP_V, ___ISR_Handler); +isp( _imib1_isp, IMIB1_ISP_V, ___ISR_Handler); +isp( _ovi1_isp, OVI1_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 2 + *****************************/ +isp( _imia2_isp, IMIA2_ISP_V, ___ISR_Handler); +isp( _imib2_isp, IMIB2_ISP_V, ___ISR_Handler); +isp( _ovi2_isp, OVI2_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 3 + *****************************/ +isp( _imia3_isp, IMIA3_ISP_V, ___ISR_Handler); +isp( _imib3_isp, IMIB3_ISP_V, ___ISR_Handler); +isp( _ovi3_isp, OVI3_ISP_V, ___ISR_Handler); + +/***************************** + * Timer 4 + *****************************/ +isp( _imia4_isp, IMIA4_ISP_V, ___ISR_Handler); +isp( _imib4_isp, IMIB4_ISP_V, ___ISR_Handler); +isp( _ovi4_isp, OVI4_ISP_V, ___ISR_Handler); + + +/***************************** + * Serial interfaces + *****************************/ + +/***************************** + * Serial interface 0 + *****************************/ +isp( _eri0_isp, ERI0_ISP_V, ___ISR_Handler); +isp( _rxi0_isp, RXI0_ISP_V, ___ISR_Handler); +isp( _txi0_isp, TXI0_ISP_V, ___ISR_Handler); +isp( _tei0_isp, TEI0_ISP_V, ___ISR_Handler); + +/***************************** + * Serial interface 1 + *****************************/ +isp( _eri1_isp, ERI1_ISP_V, ___ISR_Handler); +isp( _rxi1_isp, RXI1_ISP_V, ___ISR_Handler); +isp( _txi1_isp, TXI1_ISP_V, ___ISR_Handler); +isp( _tei1_isp, TEI1_ISP_V, ___ISR_Handler); + + +/***************************** + * Parity control unit of + * the bus state controller + *****************************/ +isp( _prt_isp, PRT_ISP_V, ___ISR_Handler); + + +/****************************** + * Analog digital converter + * ADC + ******************************/ +isp( _adu_isp, ADU_ISP_V, ___ISR_Handler); + + +/****************************** + * Watchdog timer + ******************************/ +isp( _wdt_isp, WDT_ISP_V, ___ISR_Handler); + + +/****************************** + * DRAM refresh control unit + * of bus state controller + ******************************/ +isp( _dref_isp, DREF_ISP_V, ___ISR_Handler); -- cgit v1.2.3