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 .rept 64 121 .word 0xdeadbeef 122 .endr 123 124abort_stack: 125 .word . - 4 126 .word 0xdeadbeef 127 128 .rept 64 129 .word 0xcafebabe 130 .endr 131 132irq_stack: 133 .word . - 4 134 .word 0xcafebabe 135 136 .rept 64 137 .word 0xaaaabbbb 138 .endr 139 140fiq_stack: 141 .word . - 4 142 .word 0xaaaabbbb 143 144 .rept 64 145 .word 0xccccdddd 146 .endr 147 148und_stack: 149 .word . - 4 150 .word 0xccccdddd 151 152 153FUNCTION(arm_undefined): 154 PUSHFRAMEINSVC 155 156 mov r0, sp 157 bl arch_arm_undefined 158 159 PULLFRAMEFROMSVCANDEXIT 160FUNCTION_END(arm_undefined) 161 162 163FUNCTION(arm_syscall): 164 PUSHFRAMEINSWI 165 166 mov r0, sp 167 bl arch_arm_syscall 168 169 PULLFRAMEINSWIANDEXIT 170FUNCTION_END(arm_syscall) 171 172 173FUNCTION(arm_prefetch_abort): 174#ifdef __XSCALE__ 175 nop /* Make absolutely sure any pending */ 176 nop /* imprecise aborts have occurred. */ 177#endif 178 sub lr, lr, #4 179 PUSHFRAMEINSVC 180 181 mov r0, sp 182 bl arch_arm_prefetch_abort 183 184 PULLFRAMEFROMSVCANDEXIT 185FUNCTION_END(arm_prefetch_abort) 186 187 188FUNCTION(arm_data_abort): 189#ifdef __XSCALE__ 190 nop /* Make absolutely sure any pending */ 191 nop /* imprecise aborts have occurred. */ 192#endif 193 sub lr, lr, #8 /* Adjust the lr */ 194 PUSHFRAMEINSVC 195 196 mov r0, sp 197 bl arch_arm_data_abort 198 199 PULLFRAMEFROMSVCANDEXIT 200FUNCTION_END(arm_data_abort) 201 202 203FUNCTION(arm_reserved): 204 b . 205FUNCTION_END(arm_reserved) 206 207 208FUNCTION(arm_irq): 209 sub lr, lr, #4 210 PUSHFRAMEINSVC 211 212 mov r0, sp /* iframe */ 213 bl arch_arm_irq 214 215 PULLFRAMEFROMSVCANDEXIT 216FUNCTION_END(arm_irq) 217 218 219FUNCTION(arm_fiq): 220 sub lr, lr, #4 221 PUSHFRAMEINSVC 222 223 mov r0, sp /* iframe */ 224 bl arch_arm_fiq 225 226 PULLFRAMEFROMSVCANDEXIT 227FUNCTION_END(arm_fiq) 228 229 230 231FUNCTION(arm_vector_init): 232 mrs r1, cpsr 233 bic r1, r1, #CPSR_MODE_MASK 234 235 /* move into modes and set initial sp */ 236 mov r0, r1 237 orr r0, r0, #CPSR_MODE_FIQ 238 msr cpsr_c, r0 239 ldr sp, fiq_stack 240 241 mov r0, r1 242 orr r0, r0, #CPSR_MODE_IRQ 243 msr cpsr_c, r0 244 ldr sp, irq_stack 245 246 mov r0, r1 247 orr r0, r0, #CPSR_MODE_ABT 248 msr cpsr_c, r0 249 ldr sp, abort_stack 250 251 mov r0, r1 252 orr r0, r0, #CPSR_MODE_UND 253 msr cpsr_c, r0 254 ldr sp, und_stack 255 256 /* ... and return back to supervisor mode */ 257 mov r0, r1 258 orr r0, r0, #CPSR_MODE_SVC 259 msr cpsr_c, r0 260 261 bx lr 262FUNCTION_END(arm_vector_init) 263