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