On Tue, May 4, 2010 at 5:16 AM, Kevin D. Kissell <kevink@xxxxxxxxxxxxx> wrote: > Shane McDonald wrote: >> When I'm inside my handler, I see the FCSR register has the value 0x8420, >> indicating that the Z bit is set in each of the Cause, Enables, and Flags >> fields. When longjmp() is called, it tries to write the old FCSR value >> of 0x400 (just the Z bit of the Enables field). In the emulation code, >> at lines 392 - 394 of file cp1emu.c, is the code: >> >> if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { >> return SIGFPE; >> } >> >> Given the original FCSR value of 0x8420 and the new value to set >> of 0x400, the Z bit of the Cause field is still set, and as a result, the >> above code causes the SIGFPE exception to be thrown. >> > That's not how I read the code. If ctx->fcr31 is 0x400, then the result > of the AND should be zero. Sorry, I should have been more clear. In the following chunk of code from cp1emu.c: case ctc_op:{ /* copregister rd <- rt */ u32 value; if (MIPSInst_RT(ir) == 0) value = 0; else value = xcp->regs[MIPSInst_RT(ir)]; /* we only have one writable control reg */ if (MIPSInst_RD(ir) == FPCREG_CSR) { #ifdef CSRTRACE printk("%p gpr[%d]->csr=%08x\n", (void *) (xcp->cp0_epc), MIPSInst_RT(ir), value); #endif value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03); ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03); /* convert to ieee library modes */ ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3]; } if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { return SIGFPE; } break; value gets set to an initial value of 0x400, and ctx->fcr31 comes in with an initial value of 0x8420. By the time we hit the if statement around the return SIGFPE, ctx->fcr31 has been set to 0x8400, not the 0x400 I implied. Nevertheless, that's not the problem. You've given me some good pointers for where to begin searching for the problem. If anyone out there has a verification suite they can run on the emulator, that would be much appreciated! Shane