Thread (1 message) 1 message, 1 author, 1998-01-28

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help