xref: /plan9/sys/src/9/omap/lexception.s (revision c8a340cd3a4d961f476a4f4f2d047cd5eedaced7)
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