summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/arm/cpu_asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/cpu/arm/cpu_asm.S')
-rw-r--r--cpukit/score/cpu/arm/cpu_asm.S119
1 files changed, 71 insertions, 48 deletions
diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S
index dfe6212923..60c638d80a 100644
--- a/cpukit/score/cpu/arm/cpu_asm.S
+++ b/cpukit/score/cpu/arm/cpu_asm.S
@@ -1,8 +1,12 @@
-/* cpu_asm.s
+/*
+ * $Id$
*
* This file contains all assembly code for the ARM implementation
* of RTEMS.
*
+ * Copyright (c) 2002 by Advent Networks, Inc.
+ * Jay Monkman <jmonkman@adventnetworks.com>
+ *
* COPYRIGHT (c) 2000 Canon Research Centre France SA.
* Emmanuel Raguet, mailto:raguet@crf.canon.fr
*
@@ -13,41 +17,33 @@
*/
#include <asm.h>
+#include <rtems/score/cpu_asm.h>
-/*
- * Format of ARM Register structure
- */
-
-.set REG_R0, 0
-.set REG_R1, 4
-.set REG_R2, 8
-.set REG_R3, 12
-.set REG_R4, 16
-.set REG_R5, 20
-.set REG_R6, 24
-.set REG_R7, 28
-.set REG_R8, 32
-.set REG_R9, 36
-.set REG_R10, 40
-.set REG_FP, 44
-.set REG_IP, 48
-.set REG_SP, 52
-.set REG_LR, 56
-.set REG_PC, 60
-.set SIZE_REGS, REG_PC + 4
/*
* void _CPU_Context_switch( run_context, heir_context )
+ * void _CPU_Context_restore( run_context, heir_context )
*
* This routine performs a normal non-FP context.
*
- * R0 = run_context R1 = heir_context
- *
+ * R0 = run_context R1 = heir_context
+ *
+ * This function copies the current registers to where r0 points, then
+ * restores the ones from where r1 points.
+ *
+ *
+ * NOTE: The function should be able to only save/restore the registers
+ * that would be saved by a C function since the others have already
+ * been saved.
+ *
+ * It should also be able to use the stm/ldm instructions.
+ *
*/
.globl _CPU_Context_switch
-
_CPU_Context_switch:
+/* FIXME: This should use load and store multiple instructions */
+/* Start saving context */
str r2, [r0, #REG_R2]
str r3, [r0, #REG_R3]
str r4, [r0, #REG_R4]
@@ -57,9 +53,21 @@ _CPU_Context_switch:
str r8, [r0, #REG_R8]
str r9, [r0, #REG_R9]
str r10, [r0, #REG_R10]
+
+ str r11, [r0, #REG_R11]
+ str r12, [r0, #REG_R12]
+
str sp, [r0, #REG_SP]
- str lr, [r0, #REG_PC]
+ str lr, [r0, #REG_PC] /* save LR at PC's location */
+ mrs r2, cpsr
+ str r2, [r0, #REG_CPSR]
+
+/* Start restoring context */
+
+ ldr r2, [r1, #REG_CPSR]
+ msr cpsr, r2
+
ldr r2, [r1, #REG_R2]
ldr r3, [r1, #REG_R3]
ldr r4, [r1, #REG_R4]
@@ -68,25 +76,34 @@ _CPU_Context_switch:
ldr r7, [r1, #REG_R7]
ldr r8, [r1, #REG_R8]
ldr r9, [r1, #REG_R9]
- ldr r10, [r1, #REG_R10]
+ ldr r10, [r1, #REG_R10]
+ ldr r11, [r1, #REG_R11]
+ ldr r12, [r1, #REG_R12]
+
ldr sp, [r1, #REG_SP]
- ldr lr, [r1, #REG_PC]
+ ldr lr, [r1, #REG_PC]
mov pc, lr
/*
- * NOTE: May be unnecessary to reload some registers.
- */
-
-/*
* void _CPU_Context_restore( new_context )
*
- * This routine performs a normal non-FP context.
+ * This function copies the restores the registers from where r0 points.
+ * It must match _CPU_Context_switch()
+ *
+ * NOTE: The function should be able to only save/restore the registers
+ * that would be saved by a C function since the others have already
+ * been saved.
+ *
+ * It should also be able to use the stm/ldm instructions.
+ *
*/
.globl _CPU_Context_restore
-
_CPU_Context_restore:
+/* FIXME: This should use load and store multiple instructions */
+ ldr r2, [r0, #REG_CPSR]
+ msr cpsr, r2
- ldr r2, [r0, #REG_R2]
+ ldr r2, [r0, #REG_R2]
ldr r3, [r0, #REG_R3]
ldr r4, [r0, #REG_R4]
ldr r5, [r0, #REG_R5]
@@ -94,14 +111,19 @@ _CPU_Context_restore:
ldr r7, [r0, #REG_R7]
ldr r8, [r0, #REG_R8]
ldr r9, [r0, #REG_R9]
- ldr r10, [r0, #REG_R10]
+ ldr r10, [r0, #REG_R10]
+ ldr r11, [r1, #REG_R11]
+ ldr r12, [r1, #REG_R12]
+
ldr sp, [r0, #REG_SP]
ldr lr, [r0, #REG_PC]
mov pc, lr
+/* FIXME: _Exception_Handler_Undef_Swi is untested */
.globl _Exception_Handler_Undef_Swi
_Exception_Handler_Undef_Swi:
+/* FIXME: This should use load and store multiple instructions */
sub r13,r13,#SIZE_REGS
str r0, [r13, #REG_R0]
str r1, [r13, #REG_R1]
@@ -114,8 +136,8 @@ _Exception_Handler_Undef_Swi:
str r8, [r13, #REG_R8]
str r9, [r13, #REG_R9]
str r10, [r13, #REG_R10]
- str fp, [r13, #REG_FP]
- str ip, [r13, #REG_IP]
+ str r11, [r13, #REG_R11]
+ str r12, [r13, #REG_R12]
str sp, [r13, #REG_SP]
str lr, [r13, #REG_LR]
mrs r0, cpsr /* read the status */
@@ -123,7 +145,7 @@ _Exception_Handler_Undef_Swi:
str r0, [r13, #REG_PC] /* we store it in a free place */
mov r0, r13 /* put frame address in r0 (C arg 1) */
- ldr r1, =_currentExcHandler
+ ldr r1, =SWI_Handler
ldr lr, =_go_back_1
ldr pc,[r1] /* call handler */
_go_back_1:
@@ -138,15 +160,17 @@ _go_back_1:
ldr r8, [r13, #REG_R8]
ldr r9, [r13, #REG_R9]
ldr r10, [r13, #REG_R10]
- ldr fp, [r13, #REG_FP]
- ldr ip, [r13, #REG_IP]
+ ldr r11, [r13, #REG_R11]
+ ldr r12, [r13, #REG_R12]
ldr sp, [r13, #REG_SP]
ldr lr, [r13, #REG_LR]
add r13,r13,#SIZE_REGS
- movs pc,r14 /* return */
-
+ movs pc,r14 /* return */
+
+/* FIXME: _Exception_Handler_Abort is untested */
.globl _Exception_Handler_Abort
_Exception_Handler_Abort:
+/* FIXME: This should use load and store multiple instructions */
sub r13,r13,#SIZE_REGS
str r0, [r13, #REG_R0]
str r1, [r13, #REG_R1]
@@ -159,8 +183,8 @@ _Exception_Handler_Abort:
str r8, [r13, #REG_R8]
str r9, [r13, #REG_R9]
str r10, [r13, #REG_R10]
- str sp, [r13, #REG_FP]
- str lr, [r13, #REG_IP]
+ str sp, [r13, #REG_R11]
+ str lr, [r13, #REG_R12]
str lr, [r13, #REG_SP]
str lr, [r13, #REG_LR]
mrs r0, cpsr /* read the status */
@@ -183,11 +207,10 @@ _go_back_2:
ldr r8, [r13, #REG_R8]
ldr r9, [r13, #REG_R9]
ldr r10, [r13, #REG_R10]
- ldr sp, [r13, #REG_FP]
- ldr lr, [r13, #REG_IP]
+ ldr sp, [r13, #REG_R11]
+ ldr lr, [r13, #REG_R12]
ldr lr, [r13, #REG_SP]
ldr lr, [r13, #REG_LR]
add r13,r13,#SIZE_REGS
subs pc,r14,#4 /* return */
-