Adding support for a single stack, GCC check in will follow
[mirror_edk2.git] / ArmPkg / Drivers / CpuDxe / ExceptionSupport.S
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2008-2010 Apple Inc. All rights reserved.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13 #------------------------------------------------------------------------------
14
15 .text
16 .align 3
17
18 .globl ASM_PFX(ExceptionHandlersStart)
19 .globl ASM_PFX(ExceptionHandlersEnd)
20 .globl ASM_PFX(CommonExceptionEntry)
21 .globl ASM_PFX(AsmCommonExceptionEntry)
22 .globl ASM_PFX(CommonCExceptionHandler)
23
24 ASM_PFX(ExceptionHandlersStart):
25
26 ASM_PFX(Reset):
27 b ASM_PFX(ResetEntry)
28
29 ASM_PFX(UndefinedInstruction):
30 b ASM_PFX(UndefinedInstructionEntry)
31
32 ASM_PFX(SoftwareInterrupt):
33 b ASM_PFX(SoftwareInterruptEntry)
34
35 ASM_PFX(PrefetchAbort):
36 b ASM_PFX(PrefetchAbortEntry)
37
38 ASM_PFX(DataAbort):
39 b ASM_PFX(DataAbortEntry)
40
41 ASM_PFX(ReservedException):
42 b ASM_PFX(ReservedExceptionEntry)
43
44 ASM_PFX(Irq):
45 b ASM_PFX(IrqEntry)
46
47 ASM_PFX(Fiq):
48 b ASM_PFX(FiqEntry)
49
50 ASM_PFX(ResetEntry):
51 srsdb #0x13! @ Store return state on SVC stack
52 stmfd SP!,{LR} @ Store the link register for the current mode
53 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
54 stmfd SP!,{R0-R12} @ Store the register state
55
56 mov R0,#0
57 ldr R1,ASM_PFX(CommonExceptionEntry)
58 bx R1
59
60 ASM_PFX(UndefinedInstructionEntry):
61 srsdb #0x13! @ Store return state on SVC stack
62 cps #0x13 @ Switch to SVC for common stack
63 stmfd SP!,{LR} @ Store the link register for the current mode
64 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
65 stmfd SP!,{R0-R12} @ Store the register state
66
67 mov r0,#1
68 ldr r1,ASM_PFX(CommonExceptionEntry)
69 bx r1
70
71 ASM_PFX(SoftwareInterruptEntry):
72 srsdb #0x13! @ Store return state on SVC stack
73 stmfd SP!,{LR} @ Store the link register for the current mode
74 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
75 stmfd SP!,{R0-R12} @ Store the register state
76
77 mov r0,#2
78 ldr r1,ASM_PFX(CommonExceptionEntry)
79 bx r1
80
81 ASM_PFX(PrefetchAbortEntry):
82 sub LR,LR,#4
83 srsdb #0x13! @ Store return state on SVC stack
84 cps #0x13 @ Switch to SVC for common stack
85 stmfd SP!,{LR} @ Store the link register for the current mode
86 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
87 stmfd SP!,{R0-R12} @ Store the register state
88
89 mov r0,#3
90 ldr r1,ASM_PFX(CommonExceptionEntry)
91 bx r1
92
93 ASM_PFX(DataAbortEntry):
94 sub LR,LR,#8
95 srsdb #0x13! @ Store return state on SVC stack
96 cps #0x13 @ Switch to SVC for common stack
97 stmfd SP!,{LR} @ Store the link register for the current mode
98 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
99 stmfd SP!,{R0-R12} @ Store the register state
100
101 mov r0,#4
102 ldr r1,ASM_PFX(CommonExceptionEntry)
103 bx r1
104
105 ASM_PFX(ReservedExceptionEntry):
106 srsdb #0x13! @ Store return state on SVC stack
107 cps #0x13 @ Switch to SVC for common stack
108 stmfd SP!,{LR} @ Store the link register for the current mode
109 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
110 stmfd SP!,{R0-R12} @ Store the register state
111
112 mov r0,#5
113 ldr r1,ASM_PFX(CommonExceptionEntry)
114 bx r1
115
116 ASM_PFX(IrqEntry):
117 sub LR,LR,#4
118 srsdb #0x13! @ Store return state on SVC stack
119 cps #0x13 @ Switch to SVC for common stack
120 stmfd SP!,{LR} @ Store the link register for the current mode
121 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
122 stmfd SP!,{R0-R12} @ Store the register state
123
124 mov r0,#6
125 ldr r1,ASM_PFX(CommonExceptionEntry)
126 bx r1
127
128 ASM_PFX(FiqEntry):
129 sub LR,LR,#4
130 srsdb #0x13! @ Store return state on SVC stack
131 cps #0x13 @ Switch to SVC for common stack
132 stmfd SP!,{LR} @ Store the link register for the current mode
133 sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
134 stmfd SP!,{R0-R12} @ Store the register state
135
136 mov r0,#7
137 ldr r1,ASM_PFX(CommonExceptionEntry)
138 bx r1
139
140 ASM_PFX(CommonExceptionEntry):
141 .byte 0x12
142 .byte 0x34
143 .byte 0x56
144 .byte 0x78
145
146 ASM_PFX(ExceptionHandlersEnd):
147
148 ASM_PFX(AsmCommonExceptionEntry):
149 mrc p15, 0, R1, c6, c0, 2 @ Read IFAR
150 str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
151
152 mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
153 str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
154
155 mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
156 str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
157
158 mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
159 str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
160
161 ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack
162 str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
163 and r1, r1, #0x1f @ Check to see if User or System Mode
164 cmp r1, #0x1f
165 cmpne r1, #0x10
166 add R2, SP, #0x38 @ Store it in EFI_SYSTEM_CONTEXT_ARM.LR
167 ldmneed r2, {lr}^ @ User or System mode, use unbanked register
168 ldmneed r2, {lr} @ All other modes used banked register
169
170 ldr R1, [SP, #0x58] @ PC is the LR pushed by srsdb
171 str R1, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
172
173 sub R1, SP, #0x60 @ We pused 0x60 bytes on the stack
174 str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
175
176 @ R0 is exception type
177 mov R1,SP @ Prepare System Context pointer as an argument for the exception handler
178 blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
179
180 ldr R2,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
181 str R2,[SP,#0x5c] @ Store it back to srsdb stack slot so it can be restored
182
183 ldr R2,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
184 str R2,[SP,#0x58] @ Store it back to srsdb stack slot so it can be restored
185
186 ldmfd SP!,{R0-R12} @ Restore general purpose registers
187 @ Exception handler can not change SP or LR as we would blow chunks
188
189 add SP,SP,#0x20 @ Clear out the remaining stack space
190 ldmfd SP!,{LR} @ restore the link register for this context
191 rfefd SP! @ return from exception via srsdb stack slot