1 | /** |
---|
2 | * @file |
---|
3 | * |
---|
4 | * @ingroup ScoreCPU |
---|
5 | * |
---|
6 | * @brief ARM exception support implementation. |
---|
7 | */ |
---|
8 | |
---|
9 | /* |
---|
10 | * Copyright (c) 2007 by Ray Xu, <Rayx.cn@gmail.com> |
---|
11 | * Thumb support added. |
---|
12 | * |
---|
13 | * Copyright (c) 2002 by Advent Networks, Inc. |
---|
14 | * Jay Monkman <jmonkman@adventnetworks.com> |
---|
15 | * |
---|
16 | * COPYRIGHT (c) 2000 Canon Research Centre France SA. |
---|
17 | * Emmanuel Raguet, mailto:raguet@crf.canon.fr |
---|
18 | * |
---|
19 | * The license and distribution terms for this file may be |
---|
20 | * found in the file LICENSE in this distribution or at |
---|
21 | * http://www.rtems.com/license/LICENSE. |
---|
22 | * |
---|
23 | * Moved from file 'cpukit/score/cpu/arm/cpu_asm.S'. |
---|
24 | * |
---|
25 | */ |
---|
26 | |
---|
27 | #ifdef HAVE_CONFIG_H |
---|
28 | #include "config.h" |
---|
29 | #endif |
---|
30 | |
---|
31 | #include <rtems/asm.h> |
---|
32 | #include <rtems/score/cpu_asm.h> |
---|
33 | |
---|
34 | #ifdef ARM_MULTILIB_ARCH_V4 |
---|
35 | |
---|
36 | .text |
---|
37 | |
---|
38 | /* FIXME: _Exception_Handler_Undef_Swi is untested */ |
---|
39 | DEFINE_FUNCTION_ARM(_Exception_Handler_Undef_Swi) |
---|
40 | /* FIXME: This should use load and store multiple instructions */ |
---|
41 | sub r13,r13,#SIZE_REGS |
---|
42 | str r4, [r13, #REG_R4] |
---|
43 | str r5, [r13, #REG_R5] |
---|
44 | str r6, [r13, #REG_R6] |
---|
45 | str r7, [r13, #REG_R7] |
---|
46 | str r8, [r13, #REG_R8] |
---|
47 | str r9, [r13, #REG_R9] |
---|
48 | str r10, [r13, #REG_R10] |
---|
49 | str r11, [r13, #REG_R11] |
---|
50 | str sp, [r13, #REG_SP] |
---|
51 | str lr, [r13, #REG_LR] |
---|
52 | mrs r0, cpsr /* read the status */ |
---|
53 | and r0, r0,#0x1f /* we keep the mode as exception number */ |
---|
54 | str r0, [r13, #REG_PC] /* we store it in a free place */ |
---|
55 | mov r0, r13 /* put frame address in r0 (C arg 1) */ |
---|
56 | |
---|
57 | ldr r1, =SWI_Handler |
---|
58 | ldr lr, =_go_back_1 |
---|
59 | ldr pc,[r1] /* call handler */ |
---|
60 | _go_back_1: |
---|
61 | ldr r4, [r13, #REG_R4] |
---|
62 | ldr r5, [r13, #REG_R5] |
---|
63 | ldr r6, [r13, #REG_R6] |
---|
64 | ldr r7, [r13, #REG_R7] |
---|
65 | ldr r8, [r13, #REG_R8] |
---|
66 | ldr r9, [r13, #REG_R9] |
---|
67 | ldr r10, [r13, #REG_R10] |
---|
68 | ldr r11, [r13, #REG_R11] |
---|
69 | ldr sp, [r13, #REG_SP] |
---|
70 | ldr lr, [r13, #REG_LR] |
---|
71 | add r13,r13,#SIZE_REGS |
---|
72 | movs pc,r14 /* return */ |
---|
73 | |
---|
74 | /* FIXME: _Exception_Handler_Abort is untested */ |
---|
75 | DEFINE_FUNCTION_ARM(_Exception_Handler_Abort) |
---|
76 | /* FIXME: This should use load and store multiple instructions */ |
---|
77 | sub r13,r13,#SIZE_REGS |
---|
78 | str r4, [r13, #REG_R4] |
---|
79 | str r5, [r13, #REG_R5] |
---|
80 | str r6, [r13, #REG_R6] |
---|
81 | str r7, [r13, #REG_R7] |
---|
82 | str r8, [r13, #REG_R8] |
---|
83 | str r9, [r13, #REG_R9] |
---|
84 | str sp, [r13, #REG_R11] |
---|
85 | str lr, [r13, #REG_SP] |
---|
86 | str lr, [r13, #REG_LR] |
---|
87 | mrs r0, cpsr /* read the status */ |
---|
88 | and r0, r0,#0x1f /* we keep the mode as exception number */ |
---|
89 | str r0, [r13, #REG_PC] /* we store it in a free place */ |
---|
90 | mov r0, r13 /* put frame address in ro (C arg 1) */ |
---|
91 | |
---|
92 | ldr r1, =_currentExcHandler |
---|
93 | ldr lr, =_go_back_2 |
---|
94 | ldr pc,[r1] /* call handler */ |
---|
95 | _go_back_2: |
---|
96 | ldr r4, [r13, #REG_R4] |
---|
97 | ldr r5, [r13, #REG_R5] |
---|
98 | ldr r6, [r13, #REG_R6] |
---|
99 | ldr r7, [r13, #REG_R7] |
---|
100 | ldr r8, [r13, #REG_R8] |
---|
101 | ldr r9, [r13, #REG_R9] |
---|
102 | ldr r10, [r13, #REG_R10] |
---|
103 | ldr sp, [r13, #REG_R11] |
---|
104 | ldr lr, [r13, #REG_SP] |
---|
105 | ldr lr, [r13, #REG_LR] |
---|
106 | add r13,r13,#SIZE_REGS |
---|
107 | #ifdef __thumb__ |
---|
108 | subs r11, r14,#4 |
---|
109 | bx r11 |
---|
110 | nop |
---|
111 | #else |
---|
112 | subs pc,r14,#4 /* return */ |
---|
113 | #endif |
---|
114 | |
---|
115 | #define ABORT_REGS_OFFS 32-REG_R4 |
---|
116 | #define ABORT_SIZE_REGS SIZE_REGS+ABORT_REGS_OFFS |
---|
117 | |
---|
118 | DEFINE_FUNCTION_ARM(_exc_data_abort) |
---|
119 | sub sp, sp, #ABORT_SIZE_REGS /* reserve register frame */ |
---|
120 | stmia sp, {r0-r11} |
---|
121 | add sp, sp, #ABORT_REGS_OFFS /* the Context_Control structure starts by CPSR, R4, ... */ |
---|
122 | |
---|
123 | str ip, [sp, #REG_PC] /* store R12 (ip) somewhere, oh hackery, hackery, hack */ |
---|
124 | str lr, [sp, #REG_LR] |
---|
125 | |
---|
126 | mov r1, lr |
---|
127 | ldr r0, [r1, #-8] /* r0 = bad instruction */ |
---|
128 | mrs r1, spsr /* r1 = spsr */ |
---|
129 | mov r2, r13 /* r2 = exception frame of Context_Control type */ |
---|
130 | #if defined(__thumb__) |
---|
131 | .code 32 |
---|
132 | /*arm to thumb*/ |
---|
133 | adr r5, to_thumb + 1 |
---|
134 | bx r5 |
---|
135 | .code 16 |
---|
136 | to_thumb: |
---|
137 | #endif |
---|
138 | bl do_data_abort |
---|
139 | #if defined(__thumb__) |
---|
140 | /*back to arm*/ |
---|
141 | .code 16 |
---|
142 | thumb_to_arm: |
---|
143 | .align 2 |
---|
144 | adr r5, arm_code |
---|
145 | bx r5 |
---|
146 | nop |
---|
147 | .code 32 |
---|
148 | arm_code: |
---|
149 | #endif |
---|
150 | |
---|
151 | ldr lr, [sp, #REG_LR] |
---|
152 | ldr ip, [sp, #REG_PC] /* restore R12 (ip) */ |
---|
153 | |
---|
154 | sub sp, sp, #ABORT_REGS_OFFS |
---|
155 | ldmia sp, {r0-r11} |
---|
156 | add sp, sp, #ABORT_SIZE_REGS |
---|
157 | #ifdef __thumb__ |
---|
158 | subs r11, r14, #4 /* return to the instruction */ |
---|
159 | bx r11 |
---|
160 | nop |
---|
161 | #else |
---|
162 | subs pc, r14, #4 |
---|
163 | #endif |
---|
164 | /* _AFTER_ the aborted one */ |
---|
165 | |
---|
166 | #endif /* ARM_MULTILIB_ARCH_V4 */ |
---|