Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@272 cc03376c-175c-47c8-b038-4cd826a8556b
181 lines
3.7 KiB
ArmAsm
181 lines
3.7 KiB
ArmAsm
#include <regdef.h>
|
|
#include <xcpt_asm.h>
|
|
|
|
.section .ktext,"ax"
|
|
|
|
LEAF(xcptlow_handler)
|
|
.set noreorder
|
|
.set noat
|
|
/* Note: exceptions do not save and restore registers k0 and k1.
|
|
* on entry, k1 = exception class.
|
|
*/
|
|
|
|
/* allocate exception stack frame (on 8-byte boundary) */
|
|
subu k1, sp, XCP_SIZE
|
|
srl k1, 3 /* shift right/left -> alligned on boundary */
|
|
sll k1, 3
|
|
|
|
/* save enough registers to get by */
|
|
sw AT, XCP_AT(k1)
|
|
sw v0, XCP_V0(k1)
|
|
sw v1, XCP_V1(k1)
|
|
sw a0, XCP_A0(k1)
|
|
sw a1, XCP_A1(k1)
|
|
sw a2, XCP_A2(k1)
|
|
sw a3, XCP_A3(k1)
|
|
sw sp, XCP_SP(k1)
|
|
sw ra, XCP_RA(k1)
|
|
|
|
/* get coprocessor 0 exception state */
|
|
mfc0 a0, CP0_CR
|
|
mfc0 a1, CP0_SR
|
|
mfc0 a2, CP0_BADDR
|
|
mfc0 a3, CP0_EPC
|
|
|
|
/* we can safely use AT now */
|
|
.set at
|
|
|
|
/* switch to using sp to point at exception frame */
|
|
move sp, k1
|
|
|
|
/* nothing sensible to store for k0/k1, store zero */
|
|
sw zero, XCP_K0(sp)
|
|
sw zero, XCP_K1(sp)
|
|
|
|
/* we are now interruptible: dump all remaining state
|
|
* into the exception stack frame.
|
|
*/
|
|
/* coprocessor exception state */
|
|
sw a0, XCP_CR(sp)
|
|
sw a1, XCP_SR(sp)
|
|
sw a2, XCP_BADDR(sp)
|
|
sw a3, XCP_EPC(sp)
|
|
|
|
/* mdhi and mdlo */
|
|
mfhi v0
|
|
mflo v1
|
|
sw v0, XCP_MDHI(sp)
|
|
sw v1, XCP_MDLO(sp)
|
|
|
|
/* Save all the other general registers.
|
|
* We save zero, s0-s7 and s8 as well, as instruction emulators (e.g. FP
|
|
* operations) and debuggers rely on all registers stored together in
|
|
* well-defined structure.
|
|
*/
|
|
sw zero, XCP_ZERO(sp)
|
|
sw t0, XCP_T0(sp)
|
|
sw t1, XCP_T1(sp)
|
|
sw t2, XCP_T2(sp)
|
|
sw t3, XCP_T3(sp)
|
|
sw t4, XCP_T4(sp)
|
|
sw t5, XCP_T5(sp)
|
|
sw t6, XCP_T6(sp)
|
|
sw t7, XCP_T7(sp)
|
|
sw s0, XCP_S0(sp)
|
|
sw s1, XCP_S1(sp)
|
|
sw s2, XCP_S2(sp)
|
|
sw s3, XCP_S3(sp)
|
|
sw s4, XCP_S4(sp)
|
|
sw s5, XCP_S5(sp)
|
|
sw s6, XCP_S6(sp)
|
|
sw s7, XCP_S7(sp)
|
|
sw t8, XCP_T8(sp)
|
|
sw t9, XCP_T9(sp)
|
|
sw gp, XCP_GP(sp)
|
|
sw s8, XCP_S8(sp)
|
|
|
|
/* I don't know what the following does. [rb] */
|
|
/* load our _gp pointer */
|
|
# la gp, _gp
|
|
|
|
/* and call the C exception handler */
|
|
move a0, sp # arg1 = &xcp
|
|
subu sp, 16 # (arg save area)
|
|
j _xcptcall
|
|
move ra, zero # fake return address
|
|
|
|
/* This strange call to _xcptcall with zero return address is to
|
|
* help exception-aware debuggers to trace back over the exception event.
|
|
* We are basically interposing a bogus stackframe (with a zero return
|
|
* address) between the C exception handler and the actual machine
|
|
* exception.
|
|
*/
|
|
xcptrest:
|
|
.set noat
|
|
add AT, sp, 16
|
|
|
|
/* at points to exception frame */
|
|
xcptrestother:
|
|
/* restore all state */
|
|
/* restore most general registers */
|
|
lw t0, XCP_T0(AT)
|
|
lw t1, XCP_T1(AT)
|
|
lw t2, XCP_T2(AT)
|
|
lw t3, XCP_T3(AT)
|
|
lw t4, XCP_T4(AT)
|
|
lw t5, XCP_T5(AT)
|
|
lw t6, XCP_T6(AT)
|
|
lw t7, XCP_T7(AT)
|
|
lw s0, XCP_S0(AT)
|
|
lw s1, XCP_S1(AT)
|
|
lw s2, XCP_S2(AT)
|
|
lw s3, XCP_S3(AT)
|
|
lw s4, XCP_S4(AT)
|
|
lw s5, XCP_S5(AT)
|
|
lw s6, XCP_S6(AT)
|
|
lw s7, XCP_S7(AT)
|
|
lw t8, XCP_T8(AT)
|
|
lw t9, XCP_T9(AT)
|
|
lw gp, XCP_GP(AT)
|
|
lw s8, XCP_S8(AT)
|
|
|
|
/* mdhi and mdlo */
|
|
lw v0, XCP_MDHI(AT)
|
|
lw v1, XCP_MDLO(AT)
|
|
mthi v0
|
|
mtlo v1
|
|
|
|
/* remaining general registers */
|
|
lw a0, XCP_A0(AT)
|
|
lw a1, XCP_A1(AT)
|
|
lw a2, XCP_A2(AT)
|
|
lw a3, XCP_A3(AT)
|
|
lw ra, XCP_RA(AT)
|
|
|
|
/* restore the exception-time status register */
|
|
.set noreorder
|
|
lw v0, XCP_SR(AT)
|
|
nop
|
|
mtc0 v0, CP0_SR
|
|
lw v1, XCP_V1(AT)
|
|
lw v0, XCP_V0(AT)
|
|
lw sp, XCP_SP(AT)
|
|
|
|
/* we are not uninterruptible and can use k1 safely */
|
|
lw k1, XCP_EPC(AT)
|
|
lw AT, XCP_AT(AT)
|
|
mtc0 k1, CP0_EPC
|
|
j k1
|
|
rfe
|
|
|
|
.set reorder
|
|
.set at
|
|
END(xcptlow_handler)
|
|
|
|
|
|
LEAF(_xcptcall)
|
|
/* on entry: a0 == &xcp */
|
|
subu sp, 24
|
|
sw ra, 16(sp)
|
|
|
|
/* punt out to _xcpt_deliver */
|
|
jal _xcpt_deliver
|
|
nop
|
|
lw ra, 16(sp)
|
|
addu sp, 24
|
|
beqz ra, xcptrest
|
|
nop
|
|
j ra
|
|
nop
|
|
END(_xcptcall)
|