I was looking through the ARM fp code to test out some operand changes
I'm working on, and I noticed something strange. The FpscrExc and
FpscrQc registers are read with code like the following:

      case MISCREG_FPSCR_QC:
        return readMiscRegNoEffect(MISCREG_FPSCR) & ~FpscrQcMask;
      case MISCREG_FPSCR_EXC:
        return readMiscRegNoEffect(MISCREG_FPSCR) & ~FpscrExcMask;

Which reads all the bits of the FPSCR *except* the bits that you
actually wanted. They're set like this:

          case MISCREG_FPSCR_QC:
            {
                newVal = miscRegs[MISCREG_FPSCR] | (newVal & FpscrQcMask);
                misc_reg = MISCREG_FPSCR;
            }
            break;
          case MISCREG_FPSCR_EXC:
            {
                newVal = miscRegs[MISCREG_FPSCR] | (newVal & FpscrExcMask);
                misc_reg = MISCREG_FPSCR;
            }
            break;

which should work like I expect. It seems that one or the other is wrong.


But then another interesting thing is that I think this particular bug
is what makes some of the FP instructions work despite the fact that
this is wrong. For example:

    vmlsSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) FpscrExc;
        float mid = binaryOp(fpscr, FpOp1, FpOp2,
                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
        FpDest = binaryOp(fpscr, FpDest, -mid, fpAddS,
                fpscr.fz, fpscr.dn, fpscr.rMode);
        FpscrExc = fpscr;
    '''

Here we read the FpscrExc which is just supposed to be the exception
bits, but then we're using all these other control bits out of it. Then
later we write it back, but when written it only writes back the
FpscrExc bits. At the very least this dual personality is really
confusing, especially the fact that reading FpscrExc actually reads
everything else. What would make more sense, I think, would be something
like this:

    vmlsSCode = vfpEnabledCheckCode + '''
        FPSCR fpscr = (FPSCR) Fpscr;
        float mid = binaryOp(fpscr, FpOp1, FpOp2,
                fpMulS, fpscr.fz, fpscr.dn, fpscr.rMode);
        FpDest = binaryOp(fpscr, FpDest, -mid, fpAddS,
                fpscr.fz, fpscr.dn, fpscr.rMode);
        FpscrExc = fpscr;
    '''

Where we read in the whole thing, and then the non-exception bits are
filtered out when written. Then of course the polarity of the FpscrExc
read mask would get flipped. When I wrote the original version I think
there was just a single Fpscr operand which was used everywhere, and it
must not have been split out properly when that was changed.

I'm going to assume my fix is correct and see where I end up. I don't
have any FP tests that I'm aware of so I won't be able to test this
effectively.

Gabe
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to