On Tue, Jan 27, 1998 at 06:32:09PM +0100, harald.koerfgen@netcologne.de wrote:
> This is the begin of the RESTORE_ALL macro, which is used in
> ret_from_sys_call:
> #define RESTORE_ALL \
> mfc0 t0, CP0_STATUS; \
> nop; \
> ori t0, 0x01; \
> xori t0, 0x01; \
> mtc0 t0, CP0_STATUS; \
> lw v0, PT_STATUS(sp); \
> lw v1, PT_LO(sp); \
> mtc0 v0, CP0_STATUS; \
> mtlo v1; \
> lw v0, PT_HI(sp); \
> lw v1, PT_EPC(sp); \
> mthi v0; \
> mtc0 v1, CP0_EPC; \
> ..
>
> PT_EPC is manipulated in do_sys to point behind the syscall instruction and a
> PRINT(...) shows that v1 contains the correct value. Nevertheless CP0_EPC
> remains to be unchanged.
>
> After finding that, I used the following test code:
> #define RESTORE_ALL_TEST \
> lui v0,0xffff; \
> mtc0 v0,CP0_EPC; \
> nop; \
> mfc0 a1,CP0_EPC; \
> nop; \
> PRINT("CP0_EPC : %08x\n"); \
>
> which "compiles" into:
> 800375d0 <return_test> lui $v0,0xffff
> 800375d4 <return_test+4> mtc0 $v0,$14
> 800375dc <return_test+c> mfc0 $a1,$14
> 800375e4 <return_test+14> lui $a0,0x800c
> 800375e8 <return_test+18> jal 80054478 <printk>
> 800375ec <return_test+1c> addiu $a0,$a0,5680
>
> and the result is:
> CP0_EPC : 80036aa4
>
> which is the address of the syscall instruction itself. But the result should
> be
> 0xFFFF0000, shouldn't it?.
>
> Has anybody an explanation for this, or am I just completely blind?
On the R3000 c0_epc is a readonly register - as documented. That's ok
because the R3000 uses a different way of handling exceptions. What you'll
have to do to return from an exception is about as follows:
restore c0_status
move k1, sp ; needed later
restore all gp registers
restore hi/lo registers
lw k0, PT_EPC(sp)
jr k0
rfe ; in the delay slot of the jr
Ralf
|