1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
/*
* $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
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
*/
#include <rtems/asm.h>
#include <rtems/score/cpu_asm.h>
/*
* 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
*
* This function copies the current registers to where r0 points, then
* restores the ones from where r1 points.
*
* Using the ldm/stm opcodes save 2-3 us on 100 MHz ARM9TDMI with
* a 16 bit data bus.
*
*/
.globl _CPU_Context_switch
_CPU_Context_switch:
/* Start saving context */
mrs r2, cpsr
stmia r0, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
/* Start restoring context */
_restore:
ldmia r1, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
msr cpsr, r2
mov pc, lr
/*
* void _CPU_Context_restore( new_context )
*
* This function copies the restores the registers from where r0 points.
* It must match _CPU_Context_switch()
*
*/
.globl _CPU_Context_restore
_CPU_Context_restore:
mov r1, r0
b _restore
/* 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 r4, [r13, #REG_R4]
str r5, [r13, #REG_R5]
str r6, [r13, #REG_R6]
str r7, [r13, #REG_R7]
str r8, [r13, #REG_R8]
str r9, [r13, #REG_R9]
str r10, [r13, #REG_R10]
str r11, [r13, #REG_R11]
str sp, [r13, #REG_SP]
str lr, [r13, #REG_LR]
mrs r0, cpsr /* read the status */
and r0, r0,#0x1f /* we keep the mode as exception number */
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, =SWI_Handler
ldr lr, =_go_back_1
ldr pc,[r1] /* call handler */
_go_back_1:
ldr r4, [r13, #REG_R4]
ldr r5, [r13, #REG_R5]
ldr r6, [r13, #REG_R6]
ldr r7, [r13, #REG_R7]
ldr r8, [r13, #REG_R8]
ldr r9, [r13, #REG_R9]
ldr r10, [r13, #REG_R10]
ldr r11, [r13, #REG_R11]
ldr sp, [r13, #REG_SP]
ldr lr, [r13, #REG_LR]
add r13,r13,#SIZE_REGS
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 r4, [r13, #REG_R4]
str r5, [r13, #REG_R5]
str r6, [r13, #REG_R6]
str r7, [r13, #REG_R7]
str r8, [r13, #REG_R8]
str r9, [r13, #REG_R9]
str sp, [r13, #REG_R11]
str lr, [r13, #REG_SP]
str lr, [r13, #REG_LR]
mrs r0, cpsr /* read the status */
and r0, r0,#0x1f /* we keep the mode as exception number */
str r0, [r13, #REG_PC] /* we store it in a free place */
mov r0, r13 /* put frame address in ro (C arg 1) */
ldr r1, =_currentExcHandler
ldr lr, =_go_back_2
ldr pc,[r1] /* call handler */
_go_back_2:
ldr r4, [r13, #REG_R4]
ldr r5, [r13, #REG_R5]
ldr r6, [r13, #REG_R6]
ldr r7, [r13, #REG_R7]
ldr r8, [r13, #REG_R8]
ldr r9, [r13, #REG_R9]
ldr r10, [r13, #REG_R10]
ldr sp, [r13, #REG_R11]
ldr lr, [r13, #REG_SP]
ldr lr, [r13, #REG_LR]
add r13,r13,#SIZE_REGS
subs pc,r14,#4 /* return */
#define ABORT_REGS_OFFS 32-REG_R4
#define ABORT_SIZE_REGS SIZE_REGS+ABORT_REGS_OFFS
.globl _exc_data_abort
_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, ... */
str ip, [sp, #REG_PC] /* store R12 (ip) somewhere, oh hackery, hackery, hack */
str lr, [sp, #REG_LR]
mov r1, lr
ldr r0, [r1, #-8] /* r0 = bad instruction */
mrs r1, spsr /* r1 = spsr */
mov r2, r13 /* r2 = exception frame of Context_Control type */
bl do_data_abort
ldr lr, [sp, #REG_LR]
ldr ip, [sp, #REG_PC] /* restore R12 (ip) */
sub sp, sp, #ABORT_REGS_OFFS
ldmia sp, {r0-r11}
add sp, sp, #ABORT_SIZE_REGS
subs pc, r14, #4 /* return to the instruction */
/* _AFTER_ the aborted one */
|