Changeset 224623 in webkit


Ignore:
Timestamp:
Nov 9, 2017 1:02:10 AM (6 years ago)
Author:
guijemont@igalia.com
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.

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r224607 r224623  
     12017-11-09  Guillaume Emont  <guijemont@igalia.com>
     2
     3        [JSC][MIPS] Use fcsr to check the validity of the result of trunc.w.d
     4        https://bugs.webkit.org/show_bug.cgi?id=179446
     5
     6        Reviewed by Žan Doberšek.
     7
     8        The trunc.w.d mips instruction should give a 0x7fffffff result when
     9        the source value is Infinity, NaN, or rounds to an integer outside the
     10        range -2^31 to 2^31 -1. This is what branchTruncateDoubleToInt32() and
     11        branchTruncateDoubleToUInt32() have been relying on. It turns out that
     12        this assumption is not true on some CPUs, including on the ci20 on
     13        which we run the testbot (we get 0x80000000 instead). We should the
     14        invalid operation cause bit instead to check whether the source value
     15        could be properly truncated. This requires the addition of the cfc1
     16        instruction, as well as the special registers that can be used with it
     17        (control registers of CP1).
     18
     19        * assembler/MIPSAssembler.h:
     20        (JSC::MIPSAssembler::firstSPRegister):
     21        (JSC::MIPSAssembler::lastSPRegister):
     22        (JSC::MIPSAssembler::numberOfSPRegisters):
     23        (JSC::MIPSAssembler::sprName):
     24        Added control registers of CP1.
     25        (JSC::MIPSAssembler::cfc1):
     26        Added.
     27        * assembler/MacroAssemblerMIPS.h:
     28        (JSC::MacroAssemblerMIPS::branchOnTruncateResult):
     29        (JSC::MacroAssemblerMIPS::branchTruncateDoubleToInt32):
     30        (JSC::MacroAssemblerMIPS::branchTruncateDoubleToUint32):
     31        Use fcsr to check if the value could be properly truncated.
     32
    1332017-11-08  Jeremy Jones  <jeremyj@apple.com>
    234
  • 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    }
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h

    r223916 r224623  
    29532953    // Truncates 'src' to an integer, and places the resulting 'dest'.
    29542954    // If the result is not representable as a 32 bit value, branch.
    2955     // May also branch for some values that are representable in 32 bits
    2956     // (specifically, in this case, INT_MAX 0x7fffffff).
    29572955    enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
     2956
     2957    Jump branchOnTruncateResult(BranchTruncateType branchType)
     2958    {
     2959        m_assembler.cfc1(dataTempRegister, MIPSRegisters::fcsr);
     2960        and32(TrustedImm32(MIPSAssembler::FP_CAUSE_INVALID_OPERATION), dataTempRegister);
     2961        return branch32(branchType == BranchIfTruncateFailed ? NotEqual : Equal, dataTempRegister, MIPSRegisters::zero);
     2962    }
     2963
    29582964    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
    29592965    {
    29602966        m_assembler.truncwd(fpTempRegister, src);
     2967        Jump truncateResult = branchOnTruncateResult(branchType);
    29612968        m_assembler.mfc1(dest, fpTempRegister);
    2962         return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff));
     2969        return truncateResult;
    29632970    }
    29642971
     
    29662973    {
    29672974        m_assembler.truncwd(fpTempRegister, src);
     2975        Jump truncateResult = branchOnTruncateResult(branchType);
    29682976        m_assembler.mfc1(dest, fpTempRegister);
    2969         return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff));
     2977        return truncateResult;
    29702978    }
    29712979
Note: See TracChangeset for help on using the changeset viewer.