Ignore:
Timestamp:
Nov 9, 2017, 1:02:10 AM (8 years ago)
Author:
[email protected]
Message:

[JSC][MIPS] Use fcsr to check the validity of the result of trunc.w.d
https://bugs.webkit.org/show_bug.cgi?id=179446

Reviewed by Žan Doberšek.

The trunc.w.d mips instruction should give a 0x7fffffff result when
the source value is Infinity, NaN, or rounds to an integer outside the
range -231 to 231 -1. This is what branchTruncateDoubleToInt32() and
branchTruncateDoubleToUInt32() have been relying on. It turns out that
this assumption is not true on some CPUs, including on the ci20 on
which we run the testbot (we get 0x80000000 instead). We should the
invalid operation cause bit instead to check whether the source value
could be properly truncated. This requires the addition of the cfc1
instruction, as well as the special registers that can be used with it
(control registers of CP1).

  • assembler/MIPSAssembler.h:

(JSC::MIPSAssembler::firstSPRegister):
(JSC::MIPSAssembler::lastSPRegister):
(JSC::MIPSAssembler::numberOfSPRegisters):
(JSC::MIPSAssembler::sprName):
Added control registers of CP1.
(JSC::MIPSAssembler::cfc1):
Added.

  • assembler/MacroAssemblerMIPS.h:

(JSC::MacroAssemblerMIPS::branchOnTruncateResult):
(JSC::MacroAssemblerMIPS::branchTruncateDoubleToInt32):
(JSC::MacroAssemblerMIPS::branchTruncateDoubleToUint32):
Use fcsr to check if the value could be properly truncated.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/assembler/MIPSAssembler.h

    r224258 r224623  
    109109} RegisterID;
    110110
    111 // Currently, we don't have support for any special purpose registers.
    112111typedef enum {
    113     firstInvalidSPR,
    114     lastInvalidSPR = -1,
     112    fir = 0,
     113    fccr = 25,
     114    fexr = 26,
     115    fenr = 28,
     116    fcsr = 31
    115117} SPRegisterID;
    116118
     
    163165    static constexpr unsigned numberOfRegisters() { return lastRegister() - firstRegister() + 1; }
    164166
    165     static constexpr SPRegisterID firstSPRegister() { return MIPSRegisters::firstInvalidSPR; }
    166     static constexpr SPRegisterID lastSPRegister() { return MIPSRegisters::lastInvalidSPR; }
    167     static constexpr unsigned numberOfSPRegisters() { return 0; }
     167    static constexpr SPRegisterID firstSPRegister() { return MIPSRegisters::fir; }
     168    static constexpr SPRegisterID lastSPRegister() { return MIPSRegisters::fcsr; }
     169    static constexpr unsigned numberOfSPRegisters() { return 5; }
    168170
    169171    static constexpr FPRegisterID firstFPRegister() { return MIPSRegisters::f0; }
     
    185187    static const char* sprName(SPRegisterID id)
    186188    {
    187         // Currently, we don't have support for any special purpose registers.
    188         RELEASE_ASSERT_NOT_REACHED();
     189        switch (id) {
     190        case MIPSRegisters::fir:
     191            return "fir";
     192        case MIPSRegisters::fccr:
     193            return "fccr";
     194        case MIPSRegisters::fexr:
     195            return "fexr";
     196        case MIPSRegisters::fenr:
     197            return "fenr";
     198        case MIPSRegisters::fcsr:
     199            return "fcsr";
     200        default:
     201            RELEASE_ASSERT_NOT_REACHED();
     202        }
    189203    }
    190204
     
    225239    };
    226240
     241    // FCSR Bits
     242    enum {
     243        FP_CAUSE_INVALID_OPERATION = 1 << 16
     244    };
     245
    227246    void emitInst(MIPSWord op)
    228247    {
     
    715734    {
    716735        emitInst(0x46200035 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
     736        copDelayNop();
     737    }
     738
     739    void cfc1(RegisterID rt, SPRegisterID fs)
     740    {
     741        emitInst(0x44400000 | (rt << OP_SH_RT) | (fs << OP_SH_FS));
    717742        copDelayNop();
    718743    }
Note: See TracChangeset for help on using the changeset viewer.