17bb09086SDavid du Colombier/* 27bb09086SDavid du Colombier * arm exception handlers 37bb09086SDavid du Colombier */ 47bb09086SDavid du Colombier#include "arm.s" 57bb09086SDavid du Colombier 67bb09086SDavid du Colombier#undef B /* B is for 'botch' */ 77bb09086SDavid du Colombier 87bb09086SDavid du Colombier/* 97bb09086SDavid du Colombier * exception vectors, copied by trapinit() to somewhere useful 107bb09086SDavid du Colombier */ 117bb09086SDavid du ColombierTEXT vectors(SB), 1, $-4 127bb09086SDavid du Colombier MOVW 0x18(R15), R15 /* reset */ 137bb09086SDavid du Colombier MOVW 0x18(R15), R15 /* undefined instr. */ 147bb09086SDavid du Colombier MOVW 0x18(R15), R15 /* SWI & SMC */ 157bb09086SDavid du Colombier MOVW 0x18(R15), R15 /* prefetch abort */ 167bb09086SDavid du Colombier MOVW 0x18(R15), R15 /* data abort */ 177bb09086SDavid du Colombier MOVW 0x18(R15), R15 /* reserved */ 187bb09086SDavid du Colombier MOVW 0x18(R15), R15 /* IRQ */ 197bb09086SDavid du Colombier MOVW 0x18(R15), R15 /* FIQ */ 207bb09086SDavid du Colombier 217bb09086SDavid du ColombierTEXT vtable(SB), 1, $-4 227bb09086SDavid du Colombier WORD $_vsvc(SB) /* reset, in svc mode already */ 237bb09086SDavid du Colombier WORD $_vund(SB) /* undefined, switch to svc mode */ 247bb09086SDavid du Colombier WORD $_vsvc(SB) /* swi, in svc mode already */ 257bb09086SDavid du Colombier WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */ 267bb09086SDavid du Colombier WORD $_vdabt(SB) /* data abort, switch to svc mode */ 277bb09086SDavid du Colombier WORD $_vsvc(SB) /* reserved */ 287bb09086SDavid du Colombier WORD $_virq(SB) /* IRQ, switch to svc mode */ 29*c8a340cdSDavid du Colombier// WORD $_vfiq(SB) /* FIQ, switch to svc mode */ 30*c8a340cdSDavid du Colombier WORD $_virq(SB) /* FIQ, switch to svc mode */ 317bb09086SDavid du Colombier 327bb09086SDavid du ColombierTEXT _vrst(SB), 1, $-4 337bb09086SDavid du Colombier BL _reset(SB) 347bb09086SDavid du Colombier 357bb09086SDavid du ColombierTEXT _vsvc(SB), 1, $-4 /* SWI */ 367bb09086SDavid du Colombier MOVW.W R14, -4(R13) /* ureg->pc = interrupted PC */ 377bb09086SDavid du Colombier MOVW SPSR, R14 /* ureg->psr = SPSR */ 387bb09086SDavid du Colombier MOVW.W R14, -4(R13) /* ... */ 397bb09086SDavid du Colombier MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */ 407bb09086SDavid du Colombier MOVW.W R14, -4(R13) /* ... */ 417bb09086SDavid du Colombier 42*c8a340cdSDavid du Colombier /* avoid the ambiguity described in notes/movm.w. */ 437bb09086SDavid du Colombier// MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */ 447bb09086SDavid du Colombier MOVM.DB.S [R0-R14], (R13) /* save user level registers */ 457bb09086SDavid du Colombier SUB $(15*4), R13 /* r13 now points to ureg */ 467bb09086SDavid du Colombier 477bb09086SDavid du Colombier MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ 487bb09086SDavid du Colombier 49*c8a340cdSDavid du Colombier// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */ 507bb09086SDavid du Colombier MOVW $(L1-MACHSIZE), R10 /* m */ 517bb09086SDavid du Colombier MOVW 8(R10), R9 /* up */ 527bb09086SDavid du Colombier 537bb09086SDavid du Colombier MOVW R13, R0 /* first arg is pointer to ureg */ 547bb09086SDavid du Colombier SUB $8, R13 /* space for argument+link */ 557bb09086SDavid du Colombier 567bb09086SDavid du Colombier BL syscall(SB) 577bb09086SDavid du Colombier 587bb09086SDavid du Colombier ADD $(8+4*15), R13 /* make r13 point to ureg->type */ 597bb09086SDavid du Colombier MOVW 8(R13), R14 /* restore link */ 607bb09086SDavid du Colombier MOVW 4(R13), R0 /* restore SPSR */ 617bb09086SDavid du Colombier MOVW R0, SPSR /* ... */ 627bb09086SDavid du Colombier MOVM.DB.S (R13), [R0-R14] /* restore registers */ 637bb09086SDavid du Colombier ADD $8, R13 /* pop past ureg->{type+psr} */ 647bb09086SDavid du Colombier RFE /* MOVM.IA.S.W (R13), [R15] */ 657bb09086SDavid du Colombier 667bb09086SDavid du ColombierTEXT _vund(SB), 1, $-4 /* undefined */ 677bb09086SDavid du Colombier MOVM.IA [R0-R4], (R13) /* free some working space */ 687bb09086SDavid du Colombier MOVW $PsrMund, R0 697bb09086SDavid du Colombier B _vswitch 707bb09086SDavid du Colombier 717bb09086SDavid du ColombierTEXT _vpabt(SB), 1, $-4 /* prefetch abort */ 727bb09086SDavid du Colombier MOVM.IA [R0-R4], (R13) /* free some working space */ 737bb09086SDavid du Colombier MOVW $PsrMabt, R0 /* r0 = type */ 747bb09086SDavid du Colombier B _vswitch 757bb09086SDavid du Colombier 767bb09086SDavid du ColombierTEXT _vdabt(SB), 1, $-4 /* data abort */ 777bb09086SDavid du Colombier MOVM.IA [R0-R4], (R13) /* free some working space */ 787bb09086SDavid du Colombier MOVW $(PsrMabt+1), R0 /* r0 = type */ 797bb09086SDavid du Colombier B _vswitch 807bb09086SDavid du Colombier 817bb09086SDavid du ColombierTEXT _virq(SB), 1, $-4 /* IRQ */ 827bb09086SDavid du Colombier MOVM.IA [R0-R4], (R13) /* free some working space */ 837bb09086SDavid du Colombier MOVW $PsrMirq, R0 /* r0 = type */ 847bb09086SDavid du Colombier B _vswitch 857bb09086SDavid du Colombier 867bb09086SDavid du Colombier /* 877bb09086SDavid du Colombier * come here with type in R0 and R13 pointing above saved [r0-r4]. 887bb09086SDavid du Colombier * we'll switch to SVC mode and then call trap. 897bb09086SDavid du Colombier */ 907bb09086SDavid du Colombier_vswitch: 917bb09086SDavid du Colombier MOVW SPSR, R1 /* save SPSR for ureg */ 927bb09086SDavid du Colombier MOVW R14, R2 /* save interrupted pc for ureg */ 937bb09086SDavid du Colombier MOVW R13, R3 /* save pointer to where the original [R0-R4] are */ 947bb09086SDavid du Colombier 957bb09086SDavid du Colombier /* 967bb09086SDavid du Colombier * switch processor to svc mode. this switches the banked registers 977bb09086SDavid du Colombier * (r13 [sp] and r14 [link]) to those of svc mode. 987bb09086SDavid du Colombier */ 997bb09086SDavid du Colombier MOVW CPSR, R14 1007bb09086SDavid du Colombier BIC $PsrMask, R14 1017bb09086SDavid du Colombier ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14 1027bb09086SDavid du Colombier MOVW R14, CPSR /* switch! */ 1037bb09086SDavid du Colombier 1047bb09086SDavid du Colombier AND.S $0xf, R1, R4 /* interrupted code kernel or user? */ 1057bb09086SDavid du Colombier BEQ _userexcep 1067bb09086SDavid du Colombier 1077bb09086SDavid du Colombier /* here for trap from SVC mode */ 1087bb09086SDavid du Colombier MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */ 1097bb09086SDavid du Colombier MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */ 1107bb09086SDavid du Colombier 1117bb09086SDavid du Colombier /* 112*c8a340cdSDavid du Colombier * avoid the ambiguity described in notes/movm.w. 1137bb09086SDavid du Colombier * In order to get a predictable value in R13 after the stores, 1147bb09086SDavid du Colombier * separate the store-multiple from the stack-pointer adjustment. 1157bb09086SDavid du Colombier * We'll assume that the old value of R13 should be stored on the stack. 1167bb09086SDavid du Colombier */ 1177bb09086SDavid du Colombier /* save kernel level registers, at end r13 points to ureg */ 1187bb09086SDavid du Colombier// MOVM.DB.W [R0-R14], (R13) 1197bb09086SDavid du Colombier MOVM.DB [R0-R14], (R13) 1207bb09086SDavid du Colombier SUB $(15*4), R13 /* SP now points to saved R0 */ 1217bb09086SDavid du Colombier 1227bb09086SDavid du Colombier MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ 1237bb09086SDavid du Colombier 1247bb09086SDavid du Colombier MOVW R13, R0 /* first arg is pointer to ureg */ 1257bb09086SDavid du Colombier SUB $(4*2), R13 /* space for argument+link (for debugger) */ 1267bb09086SDavid du Colombier MOVW $0xdeaddead, R11 /* marker */ 1277bb09086SDavid du Colombier 1287bb09086SDavid du Colombier BL trap(SB) 1297bb09086SDavid du Colombier 1307bb09086SDavid du Colombier ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */ 1317bb09086SDavid du Colombier MOVW 8(R13), R14 /* restore link */ 1327bb09086SDavid du Colombier MOVW 4(R13), R0 /* restore SPSR */ 1337bb09086SDavid du Colombier MOVW R0, SPSR /* ... */ 1347bb09086SDavid du Colombier 1357bb09086SDavid du Colombier MOVM.DB (R13), [R0-R14] /* restore registers */ 1367bb09086SDavid du Colombier 1377bb09086SDavid du Colombier ADD $(4*2), R13 /* pop past ureg->{type+psr} to pc */ 1387bb09086SDavid du Colombier RFE /* MOVM.IA.S.W (R13), [R15] */ 1397bb09086SDavid du Colombier 1407bb09086SDavid du Colombier /* here for trap from USER mode */ 1417bb09086SDavid du Colombier_userexcep: 1427bb09086SDavid du Colombier MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */ 1437bb09086SDavid du Colombier MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */ 1447bb09086SDavid du Colombier 145*c8a340cdSDavid du Colombier /* avoid the ambiguity described in notes/movm.w. */ 1467bb09086SDavid du Colombier// MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */ 1477bb09086SDavid du Colombier MOVM.DB.S [R0-R14], (R13) /* save kernel level registers */ 1487bb09086SDavid du Colombier SUB $(15*4), R13 /* r13 now points to ureg */ 1497bb09086SDavid du Colombier 1507bb09086SDavid du Colombier MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ 1517bb09086SDavid du Colombier 152*c8a340cdSDavid du Colombier// MOVW $(KSEG0+16*KiB-MACHSIZE), R10 /* m */ 1537bb09086SDavid du Colombier MOVW $(L1-MACHSIZE), R10 /* m */ 1547bb09086SDavid du Colombier MOVW 8(R10), R9 /* up */ 1557bb09086SDavid du Colombier 1567bb09086SDavid du Colombier MOVW R13, R0 /* first arg is pointer to ureg */ 1577bb09086SDavid du Colombier SUB $(4*2), R13 /* space for argument+link (for debugger) */ 1587bb09086SDavid du Colombier 1597bb09086SDavid du Colombier BL trap(SB) 1607bb09086SDavid du Colombier 1617bb09086SDavid du Colombier ADD $(4*2+4*15), R13 /* make r13 point to ureg->type */ 1627bb09086SDavid du Colombier MOVW 8(R13), R14 /* restore link */ 1637bb09086SDavid du Colombier MOVW 4(R13), R0 /* restore SPSR */ 1647bb09086SDavid du Colombier MOVW R0, SPSR /* ... */ 1657bb09086SDavid du Colombier MOVM.DB.S (R13), [R0-R14] /* restore registers */ 1667bb09086SDavid du Colombier ADD $(4*2), R13 /* pop past ureg->{type+psr} */ 1677bb09086SDavid du Colombier RFE /* MOVM.IA.S.W (R13), [R15] */ 1687bb09086SDavid du Colombier 1697bb09086SDavid du ColombierTEXT _vfiq(SB), 1, $-4 /* FIQ */ 1707bb09086SDavid du Colombier RFE /* FIQ is special, ignore it for now */ 1717bb09086SDavid du Colombier 1727bb09086SDavid du Colombier/* 1737bb09086SDavid du Colombier * set the stack value for the mode passed in R0 1747bb09086SDavid du Colombier */ 1757bb09086SDavid du ColombierTEXT setr13(SB), 1, $-4 1767bb09086SDavid du Colombier MOVW 4(FP), R1 1777bb09086SDavid du Colombier 1787bb09086SDavid du Colombier MOVW CPSR, R2 1797bb09086SDavid du Colombier BIC $PsrMask, R2, R3 1807bb09086SDavid du Colombier ORR R0, R3 181895a9494SDavid du Colombier MOVW R3, CPSR /* switch to new mode */ 1827bb09086SDavid du Colombier 183895a9494SDavid du Colombier MOVW R13, R0 /* return old sp */ 184895a9494SDavid du Colombier MOVW R1, R13 /* install new one */ 1857bb09086SDavid du Colombier 186895a9494SDavid du Colombier MOVW R2, CPSR /* switch back to old mode */ 1877bb09086SDavid du Colombier RET 188