197 lines · 6.1 KB · Assembly
RawDownload
/* * arm exception handlers */#include "arm.s" /* *  exception vectors, copied by trapinit() to somewhere useful */TEXT vectors(SB), 1, $-4	MOVW	0x18(R15), R15		/* reset */	MOVW	0x18(R15), R15		/* undefined instr. */	MOVW	0x18(R15), R15		/* SWI & SMC */	MOVW	0x18(R15), R15		/* prefetch abort */	MOVW	0x18(R15), R15		/* data abort */	MOVW	0x18(R15), R15		/* reserved */	MOVW	0x18(R15), R15		/* IRQ */	MOVW	0x18(R15), R15		/* FIQ */ TEXT vtable(SB), 1, $-4	WORD	$_vsvc(SB)		/* reset, in svc mode already */	WORD	$_vund(SB)		/* undefined, switch to svc mode */	WORD	$_vsvc(SB)		/* swi, in svc mode already */	WORD	$_vpabt(SB)		/* prefetch abort, switch to svc mode */	WORD	$_vdabt(SB)		/* data abort, switch to svc mode */	WORD	$_vsvc(SB)		/* reserved */	WORD	$_virq(SB)		/* IRQ, switch to svc mode */	WORD	$_vfiq(SB)		/* FIQ, switch to svc mode */ TEXT _vsvc(SB), 1, $-4			/* SWI */	MOVW.W	R14, -4(R13)		/* ureg->pc = interrupted PC */	MOVW	SPSR, R14		/* ureg->psr = SPSR */	MOVW.W	R14, -4(R13)		/* ... */	MOVW	$PsrMsvc, R14		/* ureg->type = PsrMsvc */	MOVW.W	R14, -4(R13)		/* ... */ 	/* avoid the ambiguity described in notes/movm.w. */	MOVM.DB.S [R0-R14], (R13)	/* save user level registers */	SUB	$(15*4), R13		/* r13 now points to ureg */ 	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */ //	MOVW	$(KSEG0+16*KiB-MACHSIZE), R10	/* m */	MOVW	$(MACHADDR), R10	/* m */	MOVW	8(R10), R9		/* up */ 	MOVW	R13, R0			/* first arg is pointer to ureg */	SUB	$8, R13			/* space for argument+link */ 	BL	syscall(SB) 	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */	MOVW	8(R13), R14		/* restore link */	MOVW	4(R13), R0		/* restore SPSR */	MOVW	R0, SPSR		/* ... */	MOVM.DB.S (R13), [R0-R14]	/* restore registers */	ADD	$8, R13			/* pop past ureg->{type+psr} */	RFE				/* MOVM.IA.S.W (R13), [R15] */ TEXT _vund(SB), 1, $-4			/* undefined */	MOVM.IA	[R0-R4], (R13)		/* free some working space */	MOVW	$PsrMund, R0	B	_vswitch TEXT _vpabt(SB), 1, $-4			/* prefetch abort */	MOVM.IA	[R0-R4], (R13)		/* free some working space */	MOVW	$PsrMabt, R0		/* r0 = type */	B	_vswitch TEXT _vdabt(SB), 1, $-4			/* data abort */	MOVM.IA	[R0-R4], (R13)		/* free some working space */	MOVW	$(PsrMabt+1), R0	/* r0 = type */	B	_vswitch TEXT _virq(SB), 1, $-4			/* IRQ */	MOVM.IA	[R0-R4], (R13)		/* free some working space */	MOVW	$PsrMirq, R0		/* r0 = type */	B	_vswitch 	/*	 *  come here with type in R0 and R13 pointing above saved [r0-r4].	 *  we'll switch to SVC mode and then call trap.	 */_vswitch:	MOVW	SPSR, R1		/* save SPSR for ureg */	MOVW	R14, R2			/* save interrupted pc for ureg */	MOVW	R13, R3			/* save pointer to where the original [R0-R4] are */ 	/*	 * switch processor to svc mode.  this switches the banked registers	 * (r13 [sp] and r14 [link]) to those of svc mode.	 */	MOVW	CPSR, R14	BIC	$PsrMask, R14	ORR	$(PsrDirq|PsrMsvc), R14	MOVW	R14, CPSR		/* switch! */ 	AND.S	$0xf, R1, R4		/* interrupted code kernel or user? */	BEQ	_userexcep 	/* here for trap from SVC mode */	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */ 	/*	 * avoid the ambiguity described in notes/movm.w.	 * In order to get a predictable value in R13 after the stores,	 * separate the store-multiple from the stack-pointer adjustment.	 * We'll assume that the old value of R13 should be stored on the stack.	 */	/* save kernel level registers, at end r13 points to ureg */	MOVM.DB	[R0-R14], (R13)	SUB	$(15*4), R13		/* SP now points to saved R0 */ 	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */ 	MOVW	R13, R0			/* first arg is pointer to ureg */	SUB	$(4*2), R13		/* space for argument+link (for debugger) */	MOVW	$0xdeaddead, R11	/* marker */ 	BL	trap(SB) 	ADD	$(4*2+4*15), R13	/* make r13 point to ureg->type */	MOVW	8(R13), R14		/* restore link */	MOVW	4(R13), R0		/* restore SPSR */	MOVW	R0, SPSR		/* ... */ 	MOVM.DB (R13), [R0-R14]		/* restore registers */ 	ADD	$(4*2), R13		/* pop past ureg->{type+psr} to pc */	RFE				/* MOVM.IA.S.W (R13), [R15] */ 	/* here for trap from USER mode */_userexcep:	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */ 	/* avoid the ambiguity described in notes/movm.w. */	MOVM.DB.S [R0-R14], (R13)	/* save kernel level registers */	SUB	$(15*4), R13		/* r13 now points to ureg */ 	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */ //	MOVW	$(KSEG0+16*KiB-MACHSIZE), R10	/* m */	MOVW	$(MACHADDR), R10	/* m */	MOVW	8(R10), R9		/* up */ 	MOVW	R13, R0			/* first arg is pointer to ureg */	SUB	$(4*2), R13		/* space for argument+link (for debugger) */ 	BL	trap(SB) 	ADD	$(4*2+4*15), R13	/* make r13 point to ureg->type */	MOVW	8(R13), R14		/* restore link */	MOVW	4(R13), R0		/* restore SPSR */	MOVW	R0, SPSR		/* ... */	MOVM.DB.S (R13), [R0-R14]	/* restore registers */	ADD	$(4*2), R13		/* pop past ureg->{type+psr} */	RFE				/* MOVM.IA.S.W (R13), [R15] */ TEXT _vfiq(SB), 1, $-4			/* FIQ */	MOVW	$PsrMfiq, R8		/* trap type */	MOVW	SPSR, R9		/* interrupted psr */	MOVW	R14, R10		/* interrupted pc */	MOVM.DB.W [R8-R10], (R13)	/* save in ureg */	MOVM.DB.W.S [R0-R14], (R13)	/* save interrupted regs */	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */	MOVW	$(MACHADDR), R10	/* m */	MOVW	8(R10), R9		/* up */	MOVW	R13, R0			/* first arg is pointer to ureg */	SUB	$(4*2), R13		/* space for argument+link (for debugger) */ 	BL	fiq(SB) 	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */	MOVW	8(R13), R14		/* restore link */	MOVW	4(R13), R0		/* restore SPSR */	MOVW	R0, SPSR		/* ... */	MOVM.DB.S (R13), [R0-R14]	/* restore registers */	ADD	$8, R13			/* pop past ureg->{type+psr} */	RFE				/* MOVM.IA.S.W (R13), [R15] */ /* *  set the stack value for the mode passed in R0 */TEXT setr13(SB), 1, $-4	MOVW	4(FP), R1 	MOVW	CPSR, R2	BIC	$PsrMask, R2, R3	ORR	R0, R3	MOVW	R3, CPSR		/* switch to new mode */ 	MOVW	R13, R0			/* return old sp */	MOVW	R1, R13			/* install new one */ 	MOVW	R2, CPSR		/* switch back to old mode */	RET