From 661e5de43bea5199f8e7a9f5acb85eae1daaf9ea Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 6 Nov 2007 22:51:08 +0000 Subject: 2007-11-03 Ray Xu * cpu.c, cpu_asm.S, score/cpu.h : add support for ARM<->THUMB veneer thumb new dir to controll CPSR/SPRS in thumb mode 2007-05-09 Ray Xu * cpu.c: move do_data_abort() to libbsp/arm/shared/abort/ implement a compact do_data_abort() in simple_abort.c --- cpukit/score/cpu/arm/ChangeLog | 10 +++++ cpukit/score/cpu/arm/Makefile.am | 4 +- cpukit/score/cpu/arm/cpu.c | 45 +++++++++++++++++++- cpukit/score/cpu/arm/cpu_asm.S | 75 ++++++++++++++++++++++++++++------ cpukit/score/cpu/arm/rtems/asm.h | 13 ++++++ cpukit/score/cpu/arm/rtems/score/cpu.h | 20 +++++++++ 6 files changed, 150 insertions(+), 17 deletions(-) (limited to 'cpukit/score/cpu') diff --git a/cpukit/score/cpu/arm/ChangeLog b/cpukit/score/cpu/arm/ChangeLog index 3dfb7934b5..780fd18bb8 100644 --- a/cpukit/score/cpu/arm/ChangeLog +++ b/cpukit/score/cpu/arm/ChangeLog @@ -1,3 +1,13 @@ +2007-11-03 Ray Xu + + * cpu.c, cpu_asm.S, score/cpu.h : add support for ARM<->THUMB veneer + thumb new dir to controll CPSR/SPRS in thumb mode + +2007-05-09 Ray Xu + + * cpu.c: move do_data_abort() to libbsp/arm/shared/abort/ + implement a compact do_data_abort() in simple_abort.c + 2007-05-09 Ray Xu * cpu.c: move do_data_abort() to libbsp/arm/shared/abort/ diff --git a/cpukit/score/cpu/arm/Makefile.am b/cpukit/score/cpu/arm/Makefile.am index 2290aa4123..f02efb599a 100644 --- a/cpukit/score/cpu/arm/Makefile.am +++ b/cpukit/score/cpu/arm/Makefile.am @@ -1,9 +1,7 @@ ## ## $Id$ ## - include $(top_srcdir)/automake/compile.am - include_rtemsdir = $(includedir)/rtems include_rtems_HEADERS = rtems/asm.h @@ -14,6 +12,8 @@ include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/cpu_asm.h \ noinst_LIBRARIES = libscorecpu.a libscorecpu_a_SOURCES = cpu.c cpu_asm.S libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) +SUBDIRS = thumb +libscorecpu_a_LIBADD = ./thumb/libthumbisr_a-thumb_isr.o include $(srcdir)/preinstall.am include $(top_srcdir)/automake/local.am diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c index 6c942fe49e..87593aa019 100644 --- a/cpukit/score/cpu/arm/cpu.c +++ b/cpukit/score/cpu/arm/cpu.c @@ -43,18 +43,56 @@ void _CPU_Initialize( * * _CPU_ISR_Get_level - returns the current interrupt level */ +#define str(x) #x +#define xstr(x) str(x) +#define L(x) #x "_" xstr(__LINE__) + +#define TO_ARM_MODE(x) \ + asm volatile ( \ + ".code 16 \n" \ + L(x) "_thumb: \n" \ + ".align 2 \n" \ + "push {lr} \n" \ + "adr %0, "L(x) "_arm \n" \ + "bl " L(x)" \n" \ + "pop {pc} \n" \ + ".balign 4 \n" \ + L(x) ": \n" \ + "bx %0 \n" \ + "nop \n" \ + ".pool \n" \ + ".code 32 \n" \ + L(x) "_arm: \n" \ + :"=&r" (reg)) + +/* + * Switch to Thumb mode Veneer,ugly but safe + */ + +#define TO_THUMB_MODE(x) \ + asm volatile ( \ + ".code 32 \n"\ + "adr %0, "L(x) "_thumb +1 \n"\ + "bx %0 \n"\ + ".pool \n"\ + ".thumb_func \n"\ + L(x) "_thumb: \n"\ + : "=&r" (reg)) + +#if (!defined(__THUMB_INTERWORK__) && !defined(__thumb__)) uint32_t _CPU_ISR_Get_level( void ) { uint32_t reg = 0; /* to avoid warning */ - asm volatile ("mrs %0, cpsr \n" \ "and %0, %0, #0xc0 \n" \ : "=r" (reg) \ : "0" (reg) ); - return reg; } +#endif + + /* * _CPU_ISR_install_vector @@ -162,6 +200,9 @@ cpuExcHandlerType _currentExcHandler = _defaultExcHandler; extern void _Exception_Handler_Undef_Swi(); extern void _Exception_Handler_Abort(); extern void _exc_data_abort(); + + + /* FIXME: put comments here */ void rtems_exception_init_mngt() { diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S index 7abc881e45..5001d9bebb 100644 --- a/cpukit/score/cpu/arm/cpu_asm.S +++ b/cpukit/score/cpu/arm/cpu_asm.S @@ -19,6 +19,25 @@ #include #include +/* + * function declaration macro (start body in ARM mode) + */ +#ifdef __thumb__ + #define FUNC_START_ARM(_name_) \ + .code 16 ;\ + .thumb_func ;\ + .globl _name_ ;\ +_name_: ;\ + bx pc ;\ + .code 32 ;\ +_name_ ## _ARM: +#else + #define FUNC_START_ARM(_name_) \ + .globl _name_; \ +_name_: +#endif + + .text /* * void _CPU_Context_switch( run_context, heir_context ) @@ -35,8 +54,8 @@ * a 16 bit data bus. * */ - .globl _CPU_Context_switch -_CPU_Context_switch: + +FUNC_START_ARM(_CPU_Context_switch) /* Start saving context */ mrs r2, cpsr stmia r0, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14} @@ -46,8 +65,12 @@ _CPU_Context_switch: _restore: ldmia r1, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14} msr cpsr, r2 +#ifdef __thumb__ + bx lr + nop +#else mov pc, lr - +#endif /* * void _CPU_Context_restore( new_context ) * @@ -55,16 +78,14 @@ _restore: * It must match _CPU_Context_switch() * */ - .globl _CPU_Context_restore -_CPU_Context_restore: +FUNC_START_ARM(_CPU_Context_restore) mov r1, r0 b _restore /* FIXME: _Exception_Handler_Undef_Swi is untested */ - .globl _Exception_Handler_Undef_Swi -_Exception_Handler_Undef_Swi: +FUNC_START_ARM(_Exception_Handler_Undef_Swi) /* FIXME: This should use load and store multiple instructions */ sub r13,r13,#SIZE_REGS str r4, [r13, #REG_R4] @@ -100,8 +121,7 @@ _go_back_1: movs pc,r14 /* return */ /* FIXME: _Exception_Handler_Abort is untested */ - .globl _Exception_Handler_Abort -_Exception_Handler_Abort: +FUNC_START_ARM(_Exception_Handler_Abort) /* FIXME: This should use load and store multiple instructions */ sub r13,r13,#SIZE_REGS str r4, [r13, #REG_R4] @@ -133,13 +153,18 @@ _go_back_2: ldr lr, [r13, #REG_SP] ldr lr, [r13, #REG_LR] add r13,r13,#SIZE_REGS +#ifdef __thumb__ + subs r11, r14,#4 + bx r11 + nop +#else subs pc,r14,#4 /* return */ +#endif #define ABORT_REGS_OFFS 32-REG_R4 #define ABORT_SIZE_REGS SIZE_REGS+ABORT_REGS_OFFS - .globl _exc_data_abort -_exc_data_abort: +FUNC_START_ARM(_exc_data_abort) sub sp, sp, #ABORT_SIZE_REGS /* reserve register frame */ stmia sp, {r0-r11} add sp, sp, #ABORT_REGS_OFFS /* the Context_Control structure starts by CPSR, R4, ... */ @@ -151,7 +176,26 @@ _exc_data_abort: ldr r0, [r1, #-8] /* r0 = bad instruction */ mrs r1, spsr /* r1 = spsr */ mov r2, r13 /* r2 = exception frame of Context_Control type */ +#if defined(__thumb__) + .code 32 + /*arm to thumb*/ + adr r5, to_thumb + 1 + bx r5 + .code 16 +to_thumb: +#endif bl do_data_abort +#if defined(__thumb__) +/*back to arm*/ + .code 16 +thumb_to_arm: + .align 2 + adr r5, arm_code + bx r5 + nop + .code 32 +arm_code: +#endif ldr lr, [sp, #REG_LR] ldr ip, [sp, #REG_PC] /* restore R12 (ip) */ @@ -159,6 +203,11 @@ _exc_data_abort: sub sp, sp, #ABORT_REGS_OFFS ldmia sp, {r0-r11} add sp, sp, #ABORT_SIZE_REGS - - subs pc, r14, #4 /* return to the instruction */ +#ifdef __thumb__ + subs r11, r14, #4 /* return to the instruction */ + bx r11 + nop +#else + subs pc, r14, #4 +#endif /* _AFTER_ the aborted one */ diff --git a/cpukit/score/cpu/arm/rtems/asm.h b/cpukit/score/cpu/arm/rtems/asm.h index 5c33a2565a..bbb9760156 100644 --- a/cpukit/score/cpu/arm/rtems/asm.h +++ b/cpukit/score/cpu/arm/rtems/asm.h @@ -94,6 +94,19 @@ #define SPSR REG(SPSR) +#define NUM_IRQ_VECTOR 6 // IRQ number +#define NUM_FIQ_VECTOR 7 // IRQ number + // // +#define CPSR_IRQ_DISABLE 0x80 // FIQ disabled when =1 +#define CPSR_FIQ_DISABLE 0x40 // FIQ disabled when =1 +#define CPSR_THUMB_ENABLE 0x20 // Thumb mode when =1 +#define CPSR_FIQ_MODE 0x11 +#define CPSR_IRQ_MODE 0x12 +#define CPSR_SUPERVISOR_MODE 0x13 +#define CPSR_UNDEF_MODE 0x1B + +#define CPSR_MODE_BITS 0x1F + /* * Define macros to handle section beginning and ends. */ diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h index f03ff2baab..cf99701e9c 100644 --- a/cpukit/score/cpu/arm/rtems/score/cpu.h +++ b/cpukit/score/cpu/arm/rtems/score/cpu.h @@ -512,7 +512,26 @@ SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context; * Disable all interrupts for an RTEMS critical section. The previous * level is returned in _level. */ +#if (defined(__THUMB_INTERWORK__) || defined(__thumb__)) +extern unsigned int _CPU_ISR_Disable_Thumb(void) __attribute__ ((naked)); +extern void _CPU_ISR_Enable_Thumb( int ) __attribute__ ((naked)); +extern void _CPU_ISR_Flash_Thumb(int) __attribute__ ((naked)); +extern void _CPU_ISR_Set_level_Thumb(int ) __attribute__ ((naked)); +extern uint32_t _CPU_ISR_Get_level_Thumb(void ) __attribute__ ((naked)); + +#define _CPU_ISR_Disable(_level) \ + (_level) = _CPU_ISR_Disable_Thumb() + +#define _CPU_ISR_Enable(a) _CPU_ISR_Enable_Thumb(a) + +#define _CPU_ISR_Flash(a) _CPU_ISR_Flash_Thumb(a) + +#define _CPU_ISR_Set_level(a) _CPU_ISR_Set_level_Thumb(a) + +#define _CPU_ISR_Get_level(a) _CPU_ISR_Get_level_Thumb(a) + +#else /*For ARM mode*/ #define _CPU_ISR_Disable( _level ) \ { \ int reg; \ @@ -575,6 +594,7 @@ SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context; : "0" (reg), "r" (new_level)); \ } +#endif /*(defined(__THUMB_INTERWORK__) || defined(__thumb__))*/ uint32_t _CPU_ISR_Get_level( void ); -- cgit v1.2.3