Re: Q: R3000, how to manipulate CP0_EPC?
From: <hidden>
Date: 1998-01-28 01:04:58
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