summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-11-06 22:51:08 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-11-06 22:51:08 +0000
commit661e5de43bea5199f8e7a9f5acb85eae1daaf9ea (patch)
tree514f1503907df66655d574d3547fe5c5b8951f84 /cpukit/score/cpu
parent2007-11-03 Ray Xu <rayx.cn@gmail.com> (diff)
downloadrtems-661e5de43bea5199f8e7a9f5acb85eae1daaf9ea.tar.bz2
2007-11-03 Ray Xu <rayx.cn@gmail.com>
* 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 <rayx.cn@gmail.com> * cpu.c: move do_data_abort() to libbsp/arm/shared/abort/ implement a compact do_data_abort() in simple_abort.c
Diffstat (limited to 'cpukit/score/cpu')
-rw-r--r--cpukit/score/cpu/arm/ChangeLog10
-rw-r--r--cpukit/score/cpu/arm/Makefile.am4
-rw-r--r--cpukit/score/cpu/arm/cpu.c45
-rw-r--r--cpukit/score/cpu/arm/cpu_asm.S75
-rw-r--r--cpukit/score/cpu/arm/rtems/asm.h13
-rw-r--r--cpukit/score/cpu/arm/rtems/score/cpu.h20
6 files changed, 150 insertions, 17 deletions
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 <rayx.cn@gmail.com>
+
+ * 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 <rayx.cn@gmail.com>
+
+ * 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 <rayx@gmail.com>
* 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 <rtems/asm.h>
#include <rtems/score/cpu_asm.h>
+/*
+ * 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 );