1/* 2 * Copyright 2012-2022, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ithamar R. Adema <ithamar@upgrade-android.com> 7 * 8 */ 9 10#include <arch/arm/arch_cpu_defs.h> 11 12#include <asm_defs.h> 13 14 15.macro DISABLE_INTERRUPTS 16 mrs r0, cpsr 17 orr r0, r0, #(CPSR_I | CPSR_F) 18 msr cpsr_c, r0 19.endm 20 21/* The following two macros are taken from FreeBSD... */ 22 23.macro PUSH_FRAME_IN_SVC 24 stmdb sp, {r0-r3} /* Save 4 registers */ 25 mov r0, lr /* Save xxx32 r14 */ 26 mov r1, sp /* Save xxx32 sp */ 27 mrs r3, spsr /* Save xxx32 spsr */ 28 mrs r2, cpsr /* Get the CPSR */ 29 bic r2, r2, #(CPSR_MODE_MASK) /* Fix for SVC mode */ 30 orr r2, r2, #(CPSR_MODE_SVC) 31 msr cpsr_c, r2 /* Punch into SVC mode */ 32 mov r2, sp /* Save SVC sp */ 33 str r0, [sp, #-4]! /* Push return address */ 34 str lr, [sp, #-4]! /* Push SVC lr */ 35 str r2, [sp, #-4]! /* Push SVC sp */ 36 msr spsr, r3 /* Restore correct spsr */ 37 ldmdb r1, {r0-r3} /* Restore 4 regs from xxx mode */ 38 sub sp, sp, #(4*15) /* Adjust the stack pointer */ 39 stmia sp, {r0-r12} /* Push the user mode registers */ 40 add r0, sp, #(4*13) /* Adjust the stack pointer */ 41 stmia r0, {r13-r14}^ /* Push the user mode registers */ 42 mov r0, r0 /* NOP for previous instruction */ 43 mrs r0, spsr 44 str r0, [sp, #-4]! /* Save spsr */ 45.endm 46 47.macro PULL_FRAME_FROM_SVC_AND_EXIT 48 ldr r0, [sp], #0x0004 /* Get the SPSR from stack */ 49 msr spsr, r0 /* restore SPSR */ 50 ldmia sp, {r0-r14}^ /* Restore registers (usr mode) */ 51 mov r0, r0 /* NOP for previous instruction */ 52 add sp, sp, #(4*15) /* Adjust the stack pointer */ 53 ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ 54.endm 55 56/* The following two macros are adapted from the two macros above, taken from FreeBSD. */ 57 58.macro PUSH_FRAME 59 str lr, [sp, #-4]! /* Push the return address */ 60 sub sp, sp, #(4*17) /* Adjust the stack pointer */ 61 stmia sp, {r0-r12} /* Store the general purpose registers */ 62 add r0, sp, #(4*13) /* Adjust the stack pointer */ 63 stmia r0, {r13-r14}^ /* Store the user mode sp and lr registers */ 64 mrs r0, spsr /* Store the SPSR */ 65 str r0, [sp, #-4]! 66 mov r0, #0 /* Fill in svc mode sp and lr with zeroes */ 67 str r0, [sp, #(4*16)] 68 str r0, [sp, #(4*17)] 69.endm 70 71.macro PULL_FRAME_AND_EXIT 72 ldr r0, [sp], #4 /* Get SPSR from stack */ 73 msr spsr, r0 74 ldmia sp, {r0-r14}^ /* Restore user mode registers */ 75 add sp, sp, #(4*17) /* Adjust the stack pointer */ 76 ldr lr, [sp], #4 /* Pull the return address */ 77 movs pc, lr /* Return to user mode */ 78.endm 79 80.text 81 82.globl _vectors_start 83_vectors_start: 84 ldr pc, _arm_reset 85 ldr pc, _arm_undefined 86 ldr pc, _arm_syscall 87 ldr pc, _arm_prefetch_abort 88 ldr pc, _arm_data_abort 89 ldr pc, _arm_reserved 90 ldr pc, _arm_irq 91 ldr pc, _arm_fiq 92 93 94_arm_reset: 95 .word arm_reserved // actually reset, but not used when mapped 96 97_arm_undefined: 98 .word arm_undefined 99 100_arm_syscall: 101 .word arm_syscall 102 103_arm_prefetch_abort: 104 .word arm_prefetch_abort 105 106_arm_data_abort: 107 .word arm_data_abort 108 109_arm_reserved: 110 .word arm_reserved 111 112_arm_irq: 113 .word arm_irq 114 115_arm_fiq: 116 .word arm_fiq 117 118 119.globl _vectors_end 120_vectors_end: 121 122.data 123 124 .rept 64 125 .word 0xdeadbeef 126 .endr 127 128abort_stack: 129 .word . - 4 130 .word 0xdeadbeef 131 132 .rept 64 133 .word 0xcafebabe 134 .endr 135 136irq_stack: 137 .word . - 4 138 .word 0xcafebabe 139 140 .rept 64 141 .word 0xaaaabbbb 142 .endr 143 144fiq_stack: 145 .word . - 4 146 .word 0xaaaabbbb 147 148 .rept 64 149 .word 0xccccdddd 150 .endr 151 152und_stack: 153 .word . - 4 154 .word 0xccccdddd 155 156.text 157 158FUNCTION(arm_undefined): 159 PUSH_FRAME_IN_SVC 160 161 mov r0, sp /* iframe */ 162 mov fp, r0 163 bl arch_arm_undefined 164 165 DISABLE_INTERRUPTS 166 PULL_FRAME_FROM_SVC_AND_EXIT 167FUNCTION_END(arm_undefined) 168 169 170FUNCTION(arm_syscall): 171 PUSH_FRAME 172 173 mov r0, sp /* iframe */ 174 mov fp, r0 175 bl arch_arm_syscall 176 177 DISABLE_INTERRUPTS 178 PULL_FRAME_AND_EXIT 179FUNCTION_END(arm_syscall) 180 181 182FUNCTION(arm_prefetch_abort): 183#ifdef __XSCALE__ 184 nop /* Make absolutely sure any pending */ 185 nop /* imprecise aborts have occurred. */ 186#endif 187 sub lr, lr, #4 /* Adjust LR */ 188 PUSH_FRAME_IN_SVC 189 190 mov r0, sp /* iframe */ 191 mov fp, r0 192 bl arch_arm_prefetch_abort 193 194 DISABLE_INTERRUPTS 195 PULL_FRAME_FROM_SVC_AND_EXIT 196FUNCTION_END(arm_prefetch_abort) 197 198 199FUNCTION(arm_data_abort): 200#ifdef __XSCALE__ 201 nop /* Make absolutely sure any pending */ 202 nop /* imprecise aborts have occurred. */ 203#endif 204 sub lr, lr, #8 /* Adjust LR */ 205 PUSH_FRAME_IN_SVC 206 207 mov r0, sp /* iframe */ 208 mov fp, r0 209 bl arch_arm_data_abort 210 211 DISABLE_INTERRUPTS 212 PULL_FRAME_FROM_SVC_AND_EXIT 213FUNCTION_END(arm_data_abort) 214 215 216FUNCTION(arm_reserved): 217 b . 218FUNCTION_END(arm_reserved) 219 220 221FUNCTION(arm_irq): 222 sub lr, lr, #4 /* Adjust LR */ 223 PUSH_FRAME_IN_SVC 224 225 mov r0, sp /* iframe */ 226 mov fp, r0 227 bl arch_arm_irq 228 229 DISABLE_INTERRUPTS 230 PULL_FRAME_FROM_SVC_AND_EXIT 231FUNCTION_END(arm_irq) 232 233 234FUNCTION(arm_fiq): 235 sub lr, lr, #4 /* Adjust LR */ 236 PUSH_FRAME_IN_SVC 237 238 mov r0, sp /* iframe */ 239 mov fp, r0 240 bl arch_arm_fiq 241 242 DISABLE_INTERRUPTS 243 PULL_FRAME_FROM_SVC_AND_EXIT 244FUNCTION_END(arm_fiq) 245 246 247 248FUNCTION(arm_vector_init): 249 mrs r1, cpsr 250 bic r1, r1, #CPSR_MODE_MASK 251 252 /* move into modes and set initial sp */ 253 mov r0, r1 254 orr r0, r0, #CPSR_MODE_FIQ 255 msr cpsr_c, r0 256 ldr r2, =fiq_stack 257 ldr sp, [r2] 258 259 mov r0, r1 260 orr r0, r0, #CPSR_MODE_IRQ 261 msr cpsr_c, r0 262 ldr r2, =irq_stack 263 ldr sp, [r2] 264 265 mov r0, r1 266 orr r0, r0, #CPSR_MODE_ABT 267 msr cpsr_c, r0 268 ldr r2, =abort_stack 269 ldr sp, [r2] 270 271 mov r0, r1 272 orr r0, r0, #CPSR_MODE_UND 273 msr cpsr_c, r0 274 ldr r2, =und_stack 275 ldr sp, [r2] 276 277 /* ... and return back to supervisor mode */ 278 mov r0, r1 279 orr r0, r0, #CPSR_MODE_SVC 280 msr cpsr_c, r0 281 282 bx lr 283FUNCTION_END(arm_vector_init) 284