Changeset 99798 in webkit


Ignore:
Timestamp:
Nov 9, 2011 6:32:49 PM (13 years ago)
Author:
barraclough@apple.com
Message:

Renovate ARMv7 assembler/macro-assembler
https://bugs.webkit.org/show_bug.cgi?id=71982

Reviewed by Geoff Garen.

ARMv7Assembler:

  • add support for strb (byte stores)
  • rename the VMOV_CtoS opcodes (there are currently backwards!)
  • add support for adc (add with carry)
  • add support for vsqrt, vabs
  • add support for vmov (between FPRs, and to/from GPR pairs).
  • remove '_F64' postfixes from instructions (these aren't helpful, functions can already be distinguished by their signatures).
  • rename vcvt_F64_S32 to vcvt_signedToFloatingPoint, the prior postfix was unhelpful in failing to distinguish the types (S32 indicates a single precision register, but the type could be float, int32, or uint32).
  • rename vcvtr_S32_F64 to vcvt_floatingPointToSigned, as for previous, also vcvtr was the incorrect name for the operation (the emitted instruction truncates).

MacroAssemblerARMv7:

  • add 3-operand versions of and32, lshift32, or32, rshift32, urshift32, sub32, xor32,
  • add store8, and store32 imm to base-index.
  • fix load32WithCompactAddressOffsetPatch to work for all gprs (the fix is a little kludgy but functional; to do better we'll have to also fix the repatching code).
  • Update supportsFloating* flags (all features now supported).
  • add moveDouble, storeDouble to absolute address, addDouble to absolute address
  • add 3-operand double operations.
  • implement sqrtDouble/absDouble
  • add branchTruncateDoubleToInt32, implement truncateDoubleToInt32
  • move should do nothing if src == dest
  • branchTest8-on-memory can be implemented in terms of branchTest32-on-register (branchTest8-on-register has been removed).
  • add 3-operand branchAdd32, branchSub32, also branchAdd32 absolute address.
Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r99788 r99798  
     12011-11-09  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Renovate ARMv7 assembler/macro-assembler
     4        https://bugs.webkit.org/show_bug.cgi?id=71982
     5
     6        Reviewed by Geoff Garen.
     7
     8        ARMv7Assembler:
     9        * add support for strb (byte stores)
     10        * rename the VMOV_CtoS opcodes (there are currently backwards!)
     11        * add support for adc (add with carry)
     12        * add support for vsqrt, vabs
     13        * add support for vmov (between FPRs, and to/from GPR pairs).
     14        * remove '_F64' postfixes from instructions (these aren't helpful, functions can already be distinguished by their signatures).
     15        * rename vcvt_F64_S32  to vcvt_signedToFloatingPoint, the prior postfix was unhelpful in failing to distinguish the types (S32 indicates a single precision register, but the type could be float, int32, or uint32).
     16        * rename vcvtr_S32_F64 to vcvt_floatingPointToSigned, as for previous, also vcvtr was the incorrect name for the operation (the emitted instruction truncates).
     17
     18        MacroAssemblerARMv7:
     19        * add 3-operand versions of and32, lshift32, or32, rshift32, urshift32, sub32, xor32,
     20        * add store8, and store32 imm to base-index.
     21        * fix load32WithCompactAddressOffsetPatch to work for all gprs (the fix is a little kludgy but functional; to do better we'll have to also fix the repatching code).
     22        * Update supportsFloating* flags (all features now supported).
     23        * add moveDouble, storeDouble to absolute address, addDouble to absolute address
     24        * add 3-operand double operations.
     25        * implement sqrtDouble/absDouble
     26        * add branchTruncateDoubleToInt32, implement truncateDoubleToInt32
     27        * move should do nothing if src == dest
     28        * branchTest8-on-memory can be implemented in terms of branchTest32-on-register (branchTest8-on-register has been removed).
     29        * add 3-operand branchAdd32, branchSub32, also branchAdd32 absolute address.
     30
    1312011-11-09  Gavin Barraclough  <barraclough@apple.com>
    232
  • trunk/Source/JavaScriptCore/assembler/ARMv7Assembler.h

    r95901 r99798  
    535535        OP_BX               = 0x4700,
    536536        OP_STR_reg_T1       = 0x5000,
     537        OP_STRB_reg_T1      = 0x5400,
    537538        OP_LDR_reg_T1       = 0x5800,
    538539        OP_LDRH_reg_T1      = 0x5A00,
     
    540541        OP_STR_imm_T1       = 0x6000,
    541542        OP_LDR_imm_T1       = 0x6800,
     543        OP_STRB_imm_T1      = 0x7000,
    542544        OP_LDRB_imm_T1      = 0x7800,
    543545        OP_LDRH_imm_T1      = 0x8800,
     
    570572        OP_SUB_S_reg_T2 = 0xEBB0,
    571573        OP_CMP_reg_T2   = 0xEBB0,
     574        OP_VMOV_CtoD    = 0xEC00,
     575        OP_VMOV_DtoC    = 0xEC10,
    572576        OP_VSTR         = 0xED00,
    573577        OP_VLDR         = 0xED10,
    574         OP_VMOV_StoC    = 0xEE00,
    575         OP_VMOV_CtoS    = 0xEE10,
     578        OP_VMOV_CtoS    = 0xEE00,
     579        OP_VMOV_StoC    = 0xEE10,
    576580        OP_VMUL_T2      = 0xEE20,
    577581        OP_VADD_T2      = 0xEE30,
    578582        OP_VSUB_T2      = 0xEE30,
    579583        OP_VDIV         = 0xEE80,
     584        OP_VABS_T2      = 0xEEB0,
    580585        OP_VCMP         = 0xEEB0,
    581586        OP_VCVT_FPIVFP  = 0xEEB0,
     587        OP_VMOV_T2      = 0xEEB0,
    582588        OP_VMOV_IMM_T2  = 0xEEB0,
    583589        OP_VMRS         = 0xEEB0,
     590        OP_VSQRT_T1     = 0xEEB0,
    584591        OP_B_T3a        = 0xF000,
    585592        OP_B_T4a        = 0xF000,
     
    593600        OP_ADD_S_imm_T3 = 0xF110,
    594601        OP_CMN_imm      = 0xF110,
     602        OP_ADC_imm      = 0xF140,
    595603        OP_SUB_imm_T3   = 0xF1A0,
    596604        OP_SUB_S_imm_T3 = 0xF1B0,
     
    603611        OP_UBFX_T1      = 0xF3C0,
    604612        OP_NOP_T2a      = 0xF3AF,
     613        OP_STRB_imm_T3  = 0xF800,
     614        OP_STRB_reg_T2  = 0xF800,
    605615        OP_LDRB_imm_T3  = 0xF810,
    606616        OP_LDRB_reg_T2  = 0xF810,
     
    611621        OP_LDR_imm_T4   = 0xF850,
    612622        OP_LDR_reg_T2   = 0xF850,
     623        OP_STRB_imm_T2  = 0xF880,
    613624        OP_LDRB_imm_T2  = 0xF890,
    614625        OP_LDRH_imm_T2  = 0xF8B0,
     
    628639        OP_VLDRb        = 0x0A00,
    629640        OP_VMOV_IMM_T2b = 0x0A00,
     641        OP_VMOV_T2b     = 0x0A40,
    630642        OP_VMUL_T2b     = 0x0A00,
    631643        OP_VSTRb        = 0x0A00,
     644        OP_VMOV_StoCb   = 0x0A10,
    632645        OP_VMOV_CtoSb   = 0x0A10,
    633         OP_VMOV_StoCb   = 0x0A10,
     646        OP_VMOV_DtoCb   = 0x0A10,
     647        OP_VMOV_CtoDb   = 0x0A10,
    634648        OP_VMRSb        = 0x0A10,
     649        OP_VABS_T2b     = 0x0A40,
    635650        OP_VCMPb        = 0x0A40,
    636651        OP_VCVT_FPIVFPb = 0x0A40,
    637652        OP_VSUB_T2b     = 0x0A40,
     653        OP_VSQRT_T1b    = 0x0A40,
    638654        OP_NOP_T2b      = 0x8000,
    639655        OP_B_T3b        = 0x8000,
     
    701717public:
    702718   
     719    void adc(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     720    {
     721        // Rd can only be SP if Rn is also SP.
     722        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
     723        ASSERT(rd != ARMRegisters::pc);
     724        ASSERT(rn != ARMRegisters::pc);
     725        ASSERT(imm.isEncodedImm());
     726
     727        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADC_imm, rn, rd, imm);
     728    }
     729
    703730    void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    704731    {
     
    862889    }
    863890
    864     void bkpt(uint8_t imm=0)
     891    void bkpt(uint8_t imm = 0)
    865892    {
    866893        m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
     
    13551382    }
    13561383
     1384    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
     1385    ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     1386    {
     1387        ASSERT(rt != ARMRegisters::pc);
     1388        ASSERT(rn != ARMRegisters::pc);
     1389        ASSERT(imm.isUInt12());
     1390
     1391        if (!((rt | rn) & 8) && imm.isUInt7())
     1392            m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STRB_imm_T1, imm.getUInt7() >> 2, rn, rt);
     1393        else
     1394            m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T2, rn, rt, imm.getUInt12());
     1395    }
     1396
     1397    // If index is set, this is a regular offset or a pre-indexed store;
     1398    // if index is not set then is is a post-index store.
     1399    //
     1400    // If wback is set rn is updated - this is a pre or post index store,
     1401    // if wback is not set this is a regular offset memory access.
     1402    //
     1403    // (-255 <= offset <= 255)
     1404    // _reg = REG[rn]
     1405    // _tmp = _reg + offset
     1406    // MEM[index ? _tmp : _reg] = REG[rt]
     1407    // if (wback) REG[rn] = _tmp
     1408    ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     1409    {
     1410        ASSERT(rt != ARMRegisters::pc);
     1411        ASSERT(rn != ARMRegisters::pc);
     1412        ASSERT(index || wback);
     1413        ASSERT(!wback | (rt != rn));
     1414   
     1415        bool add = true;
     1416        if (offset < 0) {
     1417            add = false;
     1418            offset = -offset;
     1419        }
     1420        ASSERT((offset & ~0xff) == 0);
     1421       
     1422        offset |= (wback << 8);
     1423        offset |= (add   << 9);
     1424        offset |= (index << 10);
     1425        offset |= (1 << 11);
     1426       
     1427        m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T3, rn, rt, offset);
     1428    }
     1429
     1430    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
     1431    ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
     1432    {
     1433        ASSERT(rn != ARMRegisters::pc);
     1434        ASSERT(!BadReg(rm));
     1435        ASSERT(shift <= 3);
     1436
     1437        if (!shift && !((rt | rn | rm) & 8))
     1438            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STRB_reg_T1, rm, rn, rt);
     1439        else
     1440            m_formatter.twoWordOp12Reg4FourFours(OP_STRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
     1441    }
     1442
    13571443    ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    13581444    {
     
    14901576    }
    14911577
    1492     void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     1578    void vadd(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
    14931579    {
    14941580        m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
    14951581    }
    14961582
    1497     void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
     1583    void vcmp(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
    14981584    {
    14991585        m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
    15001586    }
    15011587
    1502     void vcmpz_F64(FPDoubleRegisterID rd)
     1588    void vcmpz(FPDoubleRegisterID rd)
    15031589    {
    15041590        m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
    15051591    }
    15061592
    1507     void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)
     1593    void vcvt_signedToFloatingPoint(FPDoubleRegisterID rd, FPSingleRegisterID rm)
    15081594    {
    15091595        // boolean values are 64bit (toInt, unsigned, roundZero)
     
    15111597    }
    15121598
    1513     void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)
     1599    void vcvt_floatingPointToSigned(FPSingleRegisterID rd, FPDoubleRegisterID rm)
    15141600    {
    15151601        // boolean values are 64bit (toInt, unsigned, roundZero)
     
    15171603    }
    15181604
    1519     void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     1605    void vdiv(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
    15201606    {
    15211607        m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
     
    15301616    {
    15311617        ASSERT(!BadReg(rd));
    1532         m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));
     1618        m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rn, rd, VFPOperand(0));
    15331619    }
    15341620
     
    15361622    {
    15371623        ASSERT(!BadReg(rn));
    1538         m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0));
     1624        m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rd, rn, VFPOperand(0));
     1625    }
     1626
     1627    void vmov(RegisterID rd1, RegisterID rd2, FPDoubleRegisterID rn)
     1628    {
     1629        ASSERT(!BadReg(rd1));
     1630        ASSERT(!BadReg(rd2));
     1631        m_formatter.vfpOp(OP_VMOV_DtoC, OP_VMOV_DtoCb, true, rd2, VFPOperand(rd1 | 16), rn);
     1632    }
     1633
     1634    void vmov(FPDoubleRegisterID rd, RegisterID rn1, RegisterID rn2)
     1635    {
     1636        ASSERT(!BadReg(rn1));
     1637        ASSERT(!BadReg(rn2));
     1638        m_formatter.vfpOp(OP_VMOV_CtoD, OP_VMOV_CtoDb, true, rn2, VFPOperand(rn1 | 16), rd);
     1639    }
     1640
     1641    void vmov(FPDoubleRegisterID rd, FPDoubleRegisterID rn)
     1642    {
     1643        m_formatter.vfpOp(OP_VMOV_T2, OP_VMOV_T2b, true, VFPOperand(0), rd, rn);
    15391644    }
    15401645
     
    15451650    }
    15461651
    1547     void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     1652    void vmul(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
    15481653    {
    15491654        m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
     
    15551660    }
    15561661
    1557     void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     1662    void vsub(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
    15581663    {
    15591664        m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
     1665    }
     1666
     1667    void vabs(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
     1668    {
     1669        m_formatter.vfpOp(OP_VABS_T2, OP_VABS_T2b, true, VFPOperand(16), rd, rm);
     1670    }
     1671
     1672    void vsqrt(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
     1673    {
     1674        m_formatter.vfpOp(OP_VSQRT_T1, OP_VSQRT_T1b, true, VFPOperand(17), rd, rm);
    15601675    }
    15611676
     
    18071922    }
    18081923
     1924#ifndef NDEBUG
     1925    unsigned debugOffset() { return m_formatter.debugOffset(); }
     1926#endif
     1927
    18091928private:
    18101929    // VFP operations commonly take one or more 5-bit operands, typically representing a
     
    18661985                op |= 0x10;
    18671986        } else {
     1987            ASSERT(!isRoundZero);
    18681988            // 'op' field in instruction is isUnsigned
    18691989            if (!isUnsigned)
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r99787 r99798  
    212212    }
    213213
    214     void and32(RegisterID src, RegisterID dest)
    215     {
    216         m_assembler.ARM_and(dest, dest, src);
    217     }
    218 
    219     void and32(TrustedImm32 imm, RegisterID dest)
     214    void and32(RegisterID op1, RegisterID op2, RegisterID dest)
     215    {
     216        m_assembler.ARM_and(dest, op1, op2);
     217    }
     218
     219    void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
    220220    {
    221221        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
    222222        if (armImm.isValid())
    223             m_assembler.ARM_and(dest, dest, armImm);
     223            m_assembler.ARM_and(dest, src, armImm);
    224224        else {
    225225            move(imm, dataTempRegister);
    226             m_assembler.ARM_and(dest, dest, dataTempRegister);
    227         }
     226            m_assembler.ARM_and(dest, src, dataTempRegister);
     227        }
     228    }
     229
     230    void and32(RegisterID src, RegisterID dest)
     231    {
     232        and32(dest, src, dest);
     233    }
     234
     235    void and32(TrustedImm32 imm, RegisterID dest)
     236    {
     237        and32(imm, dest, dest);
    228238    }
    229239
     
    233243    }
    234244
    235     void lshift32(RegisterID shift_amount, RegisterID dest)
     245    void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
    236246    {
    237247        // Clamp the shift to the range 0..31
    238248        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
    239249        ASSERT(armImm.isValid());
    240         m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
    241 
    242         m_assembler.lsl(dest, dest, dataTempRegister);
     250        m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm);
     251
     252        m_assembler.lsl(dest, src, dataTempRegister);
     253    }
     254
     255    void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
     256    {
     257        m_assembler.lsl(dest, src, imm.m_value & 0x1f);
     258    }
     259
     260    void lshift32(RegisterID shiftAmount, RegisterID dest)
     261    {
     262        lshift32(dest, shiftAmount, dest);
    243263    }
    244264
    245265    void lshift32(TrustedImm32 imm, RegisterID dest)
    246266    {
    247         m_assembler.lsl(dest, dest, imm.m_value & 0x1f);
     267        lshift32(dest, imm, dest);
    248268    }
    249269
     
    276296    void or32(TrustedImm32 imm, RegisterID dest)
    277297    {
     298        or32(imm, dest, dest);
     299    }
     300
     301    void or32(RegisterID op1, RegisterID op2, RegisterID dest)
     302    {
     303        m_assembler.orr(dest, op1, op2);
     304    }
     305
     306    void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     307    {
    278308        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
    279309        if (armImm.isValid())
    280             m_assembler.orr(dest, dest, armImm);
     310            m_assembler.orr(dest, src, armImm);
    281311        else {
    282312            move(imm, dataTempRegister);
    283             m_assembler.orr(dest, dest, dataTempRegister);
    284         }
    285     }
    286 
    287     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
    288     {
    289         m_assembler.orr(dest, op1, op2);
    290     }
    291 
    292     void rshift32(RegisterID shift_amount, RegisterID dest)
     313            m_assembler.orr(dest, src, dataTempRegister);
     314        }
     315    }
     316
     317    void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
    293318    {
    294319        // Clamp the shift to the range 0..31
    295320        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
    296321        ASSERT(armImm.isValid());
    297         m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
    298 
    299         m_assembler.asr(dest, dest, dataTempRegister);
    300     }
    301 
     322        m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm);
     323
     324        m_assembler.asr(dest, src, dataTempRegister);
     325    }
     326
     327    void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
     328    {
     329        m_assembler.asr(dest, src, imm.m_value & 0x1f);
     330    }
     331
     332    void rshift32(RegisterID shiftAmount, RegisterID dest)
     333    {
     334        rshift32(dest, shiftAmount, dest);
     335    }
     336   
    302337    void rshift32(TrustedImm32 imm, RegisterID dest)
    303338    {
     
    305340    }
    306341
    307     void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
    308     {
    309         m_assembler.asr(dest, src, imm.m_value & 0x1f);
    310     }
    311    
    312     void urshift32(RegisterID shift_amount, RegisterID dest)
     342    void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
    313343    {
    314344        // Clamp the shift to the range 0..31
    315345        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
    316346        ASSERT(armImm.isValid());
    317         m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
     347        m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm);
    318348       
    319         m_assembler.lsr(dest, dest, dataTempRegister);
     349        m_assembler.lsr(dest, src, dataTempRegister);
     350    }
     351   
     352    void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
     353    {
     354        m_assembler.lsr(dest, src, imm.m_value & 0x1f);
     355    }
     356
     357    void urshift32(RegisterID shiftAmount, RegisterID dest)
     358    {
     359        urshift32(dest, shiftAmount, dest);
    320360    }
    321361   
    322362    void urshift32(TrustedImm32 imm, RegisterID dest)
    323363    {
    324         m_assembler.lsr(dest, dest, imm.m_value & 0x1f);
     364        urshift32(dest, imm, dest);
    325365    }
    326366
     
    381421    }
    382422
    383     void xor32(RegisterID src, RegisterID dest)
    384     {
    385         m_assembler.eor(dest, dest, src);
    386     }
    387 
    388     void xor32(TrustedImm32 imm, RegisterID dest)
     423    void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
     424    {
     425        m_assembler.eor(dest, op1, op2);
     426    }
     427
     428    void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
    389429    {
    390430        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
    391431        if (armImm.isValid())
    392             m_assembler.eor(dest, dest, armImm);
     432            m_assembler.eor(dest, src, armImm);
    393433        else {
    394434            move(imm, dataTempRegister);
    395             m_assembler.eor(dest, dest, dataTempRegister);
    396         }
     435            m_assembler.eor(dest, src, dataTempRegister);
     436        }
     437    }
     438
     439    void xor32(RegisterID src, RegisterID dest)
     440    {
     441        xor32(dest, src, dest);
     442    }
     443
     444    void xor32(TrustedImm32 imm, RegisterID dest)
     445    {
     446        xor32(imm, dest, dest);
    397447    }
    398448   
     
    462512    }
    463513
     514    void store8(RegisterID src, ArmAddress address)
     515    {
     516        if (address.type == ArmAddress::HasIndex)
     517            m_assembler.strb(src, address.base, address.u.index, address.u.scale);
     518        else if (address.u.offset >= 0) {
     519            ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset);
     520            ASSERT(armImm.isValid());
     521            m_assembler.strb(src, address.base, armImm);
     522        } else {
     523            ASSERT(address.u.offset >= -255);
     524            m_assembler.strb(src, address.base, address.u.offset, true, false);
     525        }
     526    }
     527
    464528public:
    465529    void load32(ImplicitAddress address, RegisterID dest)
     
    501565    }
    502566   
     567    // FIXME: we should be able to plant a compact load relative to/from any base/dest register.
    503568    DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
    504569    {
     570        RegisterID base = address.base;
     571       
     572        if (base >= ARMRegisters::r8) {
     573            move(base, addressTempRegister);
     574            base = addressTempRegister;
     575        }
     576
    505577        DataLabelCompact label(this);
    506578        ASSERT(address.offset >= 0);
    507579        ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
    508580        ASSERT(ARMThumbImmediate::makeUInt12(address.offset).isUInt7());
    509         m_assembler.ldrCompact(dest, address.base, ARMThumbImmediate::makeUInt12(address.offset));
     581
     582        if (dest >= ARMRegisters::r8) {
     583            m_assembler.ldrCompact(addressTempRegister, base, ARMThumbImmediate::makeUInt12(address.offset));
     584            move(addressTempRegister, dest);
     585        } else
     586            m_assembler.ldrCompact(dest, base, ARMThumbImmediate::makeUInt12(address.offset));
    510587        return label;
    511588    }
     
    550627    }
    551628
     629    void store32(TrustedImm32 imm, BaseIndex address)
     630    {
     631        move(imm, dataTempRegister);
     632        store32(dataTempRegister, setupArmAddress(address));
     633    }
     634
    552635    void store32(RegisterID src, const void* address)
    553636    {
     
    562645    }
    563646
     647    void store8(RegisterID src, BaseIndex address)
     648    {
     649        store8(src, setupArmAddress(address));
     650    }
     651
    564652
    565653    // Floating-point operations:
    566654
    567655    static bool supportsFloatingPoint() { return true; }
    568     // On x86(_64) the MacroAssembler provides an interface to truncate a double to an integer.
    569     // If a value is not representable as an integer, and possibly for some values that are,
    570     // (on x86 INT_MIN, since this is indistinguishable from results for out-of-range/NaN input)
    571     // a branch will  be taken.  It is not clear whether this interface will be well suited to
    572     // other platforms.  On ARMv7 the hardware truncation operation produces multiple possible
    573     // failure values (saturates to INT_MIN & INT_MAX, NaN reulsts in a value of 0).  This is a
    574     // temporary solution while we work out what this interface should be.  Either we need to
    575     // decide to make this interface work on all platforms, rework the interface to make it more
    576     // generic, or decide that the MacroAssembler cannot practically be used to abstracted these
    577     // operations, and make clients go directly to the m_assembler to plant truncation instructions.
    578     // In short, FIXME:.
    579     static bool supportsFloatingPointTruncate() { return false; }
    580 
    581     static bool supportsFloatingPointSqrt()
    582     {
    583         return false;
    584     }
    585     static bool supportsFloatingPointAbs() { return false; }
     656    static bool supportsFloatingPointTruncate() { return true; }
     657    static bool supportsFloatingPointSqrt() { return true; }
     658    static bool supportsFloatingPointAbs() { return true; }
    586659
    587660    void loadDouble(ImplicitAddress address, FPRegisterID dest)
     
    600673    }
    601674
     675    void moveDouble(FPRegisterID src, FPRegisterID dest)
     676    {
     677        if (src != dest)
     678            m_assembler.vmov(dest, src);
     679    }
     680
    602681    void loadDouble(const void* address, FPRegisterID dest)
    603682    {
     
    621700    }
    622701
     702    void storeDouble(FPRegisterID src, const void* address)
     703    {
     704        move(ImmPtr(address), addressTempRegister);
     705        storeDouble(src, addressTempRegister);
     706    }
     707
    623708    void addDouble(FPRegisterID src, FPRegisterID dest)
    624709    {
    625         m_assembler.vadd_F64(dest, dest, src);
     710        m_assembler.vadd(dest, dest, src);
    626711    }
    627712
     
    632717    }
    633718
     719    void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
     720    {
     721        m_assembler.vadd(dest, op1, op2);
     722    }
     723
     724    void addDouble(AbsoluteAddress address, FPRegisterID dest)
     725    {
     726        loadDouble(address.m_ptr, fpTempRegister);
     727        m_assembler.vadd(dest, dest, fpTempRegister);
     728    }
     729
    634730    void divDouble(FPRegisterID src, FPRegisterID dest)
    635731    {
    636         m_assembler.vdiv_F64(dest, dest, src);
     732        m_assembler.vdiv(dest, dest, src);
     733    }
     734
     735    void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
     736    {
     737        m_assembler.vdiv(dest, op1, op2);
    637738    }
    638739
    639740    void subDouble(FPRegisterID src, FPRegisterID dest)
    640741    {
    641         m_assembler.vsub_F64(dest, dest, src);
     742        m_assembler.vsub(dest, dest, src);
    642743    }
    643744
     
    648749    }
    649750
     751    void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
     752    {
     753        m_assembler.vsub(dest, op1, op2);
     754    }
     755
    650756    void mulDouble(FPRegisterID src, FPRegisterID dest)
    651757    {
    652         m_assembler.vmul_F64(dest, dest, src);
     758        m_assembler.vmul(dest, dest, src);
    653759    }
    654760
     
    659765    }
    660766
    661     void sqrtDouble(FPRegisterID, FPRegisterID) NO_RETURN_DUE_TO_ASSERT
    662     {
    663         ASSERT_NOT_REACHED();
    664     }
    665    
    666     void absDouble(FPRegisterID, FPRegisterID) NO_RETURN_DUE_TO_ASSERT
    667     {
    668         ASSERT_NOT_REACHED();
     767    void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
     768    {
     769        m_assembler.vmul(dest, op1, op2);
     770    }
     771
     772    void sqrtDouble(FPRegisterID src, FPRegisterID dest)
     773    {
     774        m_assembler.vsqrt(dest, src);
     775    }
     776   
     777    void absDouble(FPRegisterID src, FPRegisterID dest)
     778    {
     779        m_assembler.vabs(dest, src);
    669780    }
    670781
     
    672783    {
    673784        m_assembler.vmov(fpTempRegisterAsSingle(), src);
    674         m_assembler.vcvt_F64_S32(dest, fpTempRegisterAsSingle());
     785        m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
    675786    }
    676787
     
    680791        load32(address, dataTempRegister);
    681792        m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister);
    682         m_assembler.vcvt_F64_S32(dest, fpTempRegisterAsSingle());
     793        m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
    683794    }
    684795
     
    688799        load32(address.m_ptr, dataTempRegister);
    689800        m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister);
    690         m_assembler.vcvt_F64_S32(dest, fpTempRegisterAsSingle());
     801        m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
    691802    }
    692803
    693804    Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
    694805    {
    695         m_assembler.vcmp_F64(left, right);
     806        m_assembler.vcmp(left, right);
    696807        m_assembler.vmrs();
    697808
     
    715826    }
    716827
    717     Jump branchTruncateDoubleToInt32(FPRegisterID, RegisterID)
    718     {
    719         ASSERT_NOT_REACHED();
    720         return jump();
    721     }
    722 
     828    enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
     829    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
     830    {
     831        // Convert into dest.
     832        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
     833        m_assembler.vmov(dest, fpTempRegisterAsSingle());
     834
     835        // Calculate 2x dest.  If the value potentially underflowed, it will have
     836        // clamped to 0x80000000, so 2x dest is zero in this case. In the case of
     837        // overflow the result will be equal to -2.
     838        Jump underflow = branchAdd32(Zero, dest, dest, dataTempRegister);
     839        Jump noOverflow = branch32(NotEqual, dataTempRegister, Imm32(-2));
     840
     841        // For BranchIfTruncateSuccessful, we branch if 'noOverflow' jumps.
     842        underflow.link(this);
     843        if (branchType == BranchIfTruncateSuccessful)
     844            return noOverflow;
     845
     846        // We'll reach the current point in the code on failure, so plant a
     847        // jump here & link the success case.
     848        Jump failure = jump();
     849        noOverflow.link(this);
     850        return failure;
     851    }
     852
     853    // Result is undefined if the value is outside of the integer range.
     854    void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     855    {
     856        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
     857        m_assembler.vmov(dest, fpTempRegisterAsSingle());
     858    }
     859   
    723860    // Convert 'src' to an integer, and places the resulting 'dest'.
    724861    // If the result is not representable as a 32 bit value, branch.
     
    727864    void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID)
    728865    {
    729         m_assembler.vcvtr_S32_F64(fpTempRegisterAsSingle(), src);
     866        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
    730867        m_assembler.vmov(dest, fpTempRegisterAsSingle());
    731868
    732869        // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
    733         m_assembler.vcvt_F64_S32(fpTempRegister, fpTempRegisterAsSingle());
     870        m_assembler.vcvt_signedToFloatingPoint(fpTempRegister, fpTempRegisterAsSingle());
    734871        failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, fpTempRegister));
    735872
     
    740877    Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID)
    741878    {
    742         m_assembler.vcmpz_F64(reg);
     879        m_assembler.vcmpz(reg);
    743880        m_assembler.vmrs();
    744881        Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
     
    750887    Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID)
    751888    {
    752         m_assembler.vcmpz_F64(reg);
     889        m_assembler.vcmpz(reg);
    753890        m_assembler.vmrs();
    754891        Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
     
    820957    void move(RegisterID src, RegisterID dest)
    821958    {
    822         m_assembler.mov(dest, src);
     959        if (src != dest)
     960            m_assembler.mov(dest, src);
    823961    }
    824962
     
    837975    void signExtend32ToPtr(RegisterID src, RegisterID dest)
    838976    {
    839         if (src != dest)
    840             move(src, dest);
     977        move(src, dest);
    841978    }
    842979
    843980    void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
    844981    {
    845         if (src != dest)
    846             move(src, dest);
     982        move(src, dest);
     983    }
     984
     985    // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
     986    static RelationalCondition invert(RelationalCondition cond)
     987    {
     988        return static_cast<RelationalCondition>(cond ^ 1);
    847989    }
    848990
     
    10181160        // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/
    10191161        load8(address, addressTempRegister);
    1020         return branchTest8(cond, addressTempRegister, mask);
     1162        return branchTest32(cond, addressTempRegister, mask);
    10211163    }
    10221164
     
    10351177    void jump(AbsoluteAddress address)
    10361178    {
    1037         move(TrusteddImmPtr(address.m_ptr), dataTempRegister);
     1179        move(TrustedImmPtr(address.m_ptr), dataTempRegister);
    10381180        load32(Address(dataTempRegister), dataTempRegister);
    10391181        m_assembler.bx(dataTempRegister);
     
    10511193    //   operation caused an overflow to occur.
    10521194   
    1053     Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
    1054     {
    1055         m_assembler.add_S(dest, dest, src);
     1195    Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
     1196    {
     1197        m_assembler.add_S(dest, op1, op2);
    10561198        return Jump(makeBranch(cond));
    10571199    }
    10581200
    1059     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     1201    Jump branchAdd32(ResultCondition cond, RegisterID op1, TrustedImm32 imm, RegisterID dest)
    10601202    {
    10611203        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
    10621204        if (armImm.isValid())
    1063             m_assembler.add_S(dest, dest, armImm);
     1205            m_assembler.add_S(dest, op1, armImm);
    10641206        else {
    10651207            move(imm, dataTempRegister);
    1066             m_assembler.add_S(dest, dest, dataTempRegister);
    1067         }
     1208            m_assembler.add_S(dest, op1, dataTempRegister);
     1209        }
     1210        return Jump(makeBranch(cond));
     1211    }
     1212
     1213    Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
     1214    {
     1215        return branchAdd32(cond, dest, src, dest);
     1216    }
     1217
     1218    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     1219    {
     1220        return branchAdd32(cond, dest, imm, dest);
     1221    }
     1222
     1223    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
     1224    {
     1225        // Move the high bits of the address into addressTempRegister,
     1226        // and load the value into dataTempRegister.
     1227        move(ImmPtr(dest.m_ptr), addressTempRegister);
     1228        m_assembler.ldr(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
     1229
     1230        // Do the add.
     1231        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
     1232        if (armImm.isValid())
     1233            m_assembler.add_S(dataTempRegister, dataTempRegister, armImm);
     1234        else {
     1235            // If the operand does not fit into an immediate then load it temporarily
     1236            // into addressTempRegister; since we're overwriting addressTempRegister
     1237            // we'll need to reload it with the high bits of the address afterwards.
     1238            move(imm, addressTempRegister);
     1239            m_assembler.add_S(dataTempRegister, dataTempRegister, addressTempRegister);
     1240            move(ImmPtr(dest.m_ptr), addressTempRegister);
     1241        }
     1242
     1243        // Store the result.
     1244        m_assembler.str(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
     1245
    10681246        return Jump(makeBranch(cond));
    10691247    }
     
    10981276    }
    10991277
    1100     Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
    1101     {
    1102         m_assembler.sub_S(dest, dest, src);
     1278    Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
     1279    {
     1280        m_assembler.sub_S(dest, op1, op2);
    11031281        return Jump(makeBranch(cond));
    11041282    }
    11051283
    1106     Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     1284    Jump branchSub32(ResultCondition cond, RegisterID op1, TrustedImm32 imm, RegisterID dest)
    11071285    {
    11081286        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
    11091287        if (armImm.isValid())
    1110             m_assembler.sub_S(dest, dest, armImm);
     1288            m_assembler.sub_S(dest, op1, armImm);
    11111289        else {
    11121290            move(imm, dataTempRegister);
    1113             m_assembler.sub_S(dest, dest, dataTempRegister);
     1291            m_assembler.sub_S(dest, op1, dataTempRegister);
    11141292        }
    11151293        return Jump(makeBranch(cond));
     1294    }
     1295   
     1296    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
     1297    {
     1298        return branchSub32(cond, dest, src, dest);
     1299    }
     1300
     1301    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     1302    {
     1303        return branchSub32(cond, dest, imm, dest);
    11161304    }
    11171305   
     
    11311319    // Miscellaneous operations:
    11321320
    1133     void breakpoint()
    1134     {
    1135         m_assembler.bkpt(0);
     1321    void breakpoint(uint8_t imm = 0)
     1322    {
     1323        m_assembler.bkpt(imm);
    11361324    }
    11371325
Note: See TracChangeset for help on using the changeset viewer.