Re: Unexpected behaviour when catching SIGFPE on FPU-less system

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



OK, I think I've found the line that's causing me the problem.

On Mon, May 3, 2010 at 10:35 PM, Shane McDonald
<mcdonald.shane@xxxxxxxxx> wrote:
> On Mon, May 3, 2010 at 9:49 PM, Shane McDonald <mcdonald.shane@xxxxxxxxx> wrote:
>> Looking at env[0], I see that the __fpc_csr field has a value of 1024,
>> indicating a divide-by-zero.  As soon as that ctc1 instruction
>> is executed, the exception is raised.  I guess that makes
>> sense, but I don't understand why __fpc_csr has a value of 1024.
>> When I step through the call to setjmp(), it gets set to a value of 0.
>> In longjmp(), every other field in env[0] has the value that it was
>> set to in the call to setjmp().
>
> Wait, I take that back -- I was looking at the wrong env[0] variable!
> I can see that __fpc_csr actually does have a value of 1024 when
> I call setjmp(), and that's why longjmp() is setting the FCSR
> register to indicate divide-by-zero.  If I comment out my call to
> feenableexcept( FE_DIVBYZERO ), it is set to 0; if I include that call,
> it is set to 1024.
>
> Looking further, I also see that I confused the Cause bits and the
> Enable bits of the FCSR -- the Enable divide-by-zero bit is set,
> not the Cause bit.  Clearly, the call to feenableexcept() must
> be setting that bit.  But, it no longer makes sense that an exception
> is raised when the FCSR register is restored to the value 1024.

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.

Now that I've figured that out, I have to admit that I don't know
if the emulator has the proper behaviour, or if not, what the fix is.
Kevin, what do you think?

Shane


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux