Ignore:
Timestamp:
Jul 2, 2010, 5:28:12 PM (15 years ago)
Author:
[email protected]
Message:

Bug 41552 - Clean up ARMv7 vfp code generation
Emit separate opcode individually, remove magic numbers.

Reviewed by Oliver Hunt.

Also remove invalid assert from JSImmediate (number cells are not CELL_MASK aligned).

  • assembler/ARMv7Assembler.h:

(JSC::ARMv7Assembler::):
(JSC::ARMv7Assembler::vadd_F64):
(JSC::ARMv7Assembler::vcmp_F64):
(JSC::ARMv7Assembler::vcvt_F64_S32):
(JSC::ARMv7Assembler::vcvtr_S32_F64):
(JSC::ARMv7Assembler::vdiv_F64):
(JSC::ARMv7Assembler::vldr):
(JSC::ARMv7Assembler::vmov_F64_0):
(JSC::ARMv7Assembler::vmov):
(JSC::ARMv7Assembler::vmrs):
(JSC::ARMv7Assembler::vmul_F64):
(JSC::ARMv7Assembler::vstr):
(JSC::ARMv7Assembler::vsub_F64):
(JSC::ARMv7Assembler::VFPOperand::VFPOperand):
(JSC::ARMv7Assembler::VFPOperand::bits1):
(JSC::ARMv7Assembler::VFPOperand::bits4):
(JSC::ARMv7Assembler::vcvtOp):
(JSC::ARMv7Assembler::ARMInstructionFormatter::vfpOp):
(JSC::ARMv7Assembler::ARMInstructionFormatter::vfpMemOp):

  • assembler/MacroAssemblerARMv7.h:

(JSC::MacroAssemblerARMv7::branchDouble):

  • runtime/JSImmediate.h:

(JSC::JSValue::isCell):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/assembler/ARMv7Assembler.h

    r62306 r62419  
    446446};
    447447
    448 
    449 /*
    450 Some features of the Thumb instruction set are deprecated in ARMv7. Deprecated features affecting
    451 instructions supported by ARMv7-M are as follows:
    452 • use of the PC as <Rd> or <Rm> in a 16-bit ADD (SP plus register) instruction
    453 • use of the SP as <Rm> in a 16-bit ADD (SP plus register) instruction
    454 • use of the SP as <Rm> in a 16-bit CMP (register) instruction
    455 • use of MOV (register) instructions in which <Rd> is the SP or PC and <Rm> is also the SP or PC.
    456 • use of <Rn> as the lowest-numbered register in the register list of a 16-bit STM instruction with base
    457 register writeback
    458 */
    459448
    460449class ARMv7Assembler {
     
    624613        OP_SUB_S_reg_T2 = 0xEBB0,
    625614        OP_CMP_reg_T2   = 0xEBB0,
     615        OP_VSTR         = 0xED00,
     616        OP_VLDR         = 0xED10,
     617        OP_VMOV_StoC    = 0xEE00,
     618        OP_VMOV_CtoS    = 0xEE10,
     619        OP_VMUL_T2      = 0xEE20,
     620        OP_VADD_T2      = 0xEE30,
     621        OP_VSUB_T2      = 0xEE30,
     622        OP_VDIV         = 0xEE80,
     623        OP_VCMP_T1      = 0xEEB0,
     624        OP_VCVT_FPIVFP  = 0xEEB0,
     625        OP_VMOV_IMM_T2  = 0xEEB0,
     626        OP_VMRS         = 0xEEB0,
    626627        OP_B_T4a        = 0xF000,
    627628        OP_AND_imm_T1   = 0xF000,
     
    663664
    664665    typedef enum {
     666        OP_VADD_T2b     = 0x0A00,
     667        OP_VDIVb        = 0x0A00,
     668        OP_VLDRb        = 0x0A00,
     669        OP_VMOV_IMM_T2b = 0x0A00,
     670        OP_VMUL_T2b     = 0x0A00,
     671        OP_VSTRb        = 0x0A00,
     672        OP_VMOV_CtoSb   = 0x0A10,
     673        OP_VMOV_StoCb   = 0x0A10,
     674        OP_VMRSb        = 0x0A10,
     675        OP_VCMP_T1b     = 0x0A40,
     676        OP_VCVT_FPIVFPb = 0x0A40,
     677        OP_VSUB_T2b     = 0x0A40,
     678        OP_NOP_T2b      = 0x8000,
    665679        OP_B_T4b        = 0x9000,
    666         OP_NOP_T2b      = 0x8000,
    667680    } OpcodeID2;
    668681
     
    14961509    void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
    14971510    {
    1498         m_formatter.vfpOp(0x0b00ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
     1511        m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
    14991512    }
    15001513
    15011514    void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
    15021515    {
    1503         m_formatter.vfpOp(0x0bc0eeb4 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rm, 21, 16));
     1516        m_formatter.vfpOp(OP_VCMP_T1, OP_VCMP_T1b, true, VFPOperand(4), rd, rm);
    15041517    }
    15051518
    15061519    void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)
    15071520    {
    1508         vcvt(doubleRegisterMask(rd, 6, 28), singleRegisterMask(rm, 16, 21), false, false, false, true);
     1521        // boolean values are 64bit (toInt, unsigned, roundZero)
     1522        m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
    15091523    }
    15101524
    15111525    void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)
    15121526    {
    1513         vcvt(singleRegisterMask(rd, 6, 28), doubleRegisterMask(rm, 16, 21), true, false, true, true);
     1527        // boolean values are 64bit (toInt, unsigned, roundZero)
     1528        m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
    15141529    }
    15151530
    15161531    void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
    15171532    {
    1518         m_formatter.vfpOp(0x0b00ee80 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
     1533        m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
    15191534    }
    15201535
    15211536    void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
    15221537    {
    1523         vmem(rd, rn, imm, true);
     1538        m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
    15241539    }
    15251540
    15261541    void vmov_F64_0(FPDoubleRegisterID rd)
    15271542    {
    1528         m_formatter.vfpOp(0x0b00eeb0 | doubleRegisterMask(rd, 28, 6));
    1529     }
    1530 
    1531     void vmov(RegisterID rd, FPSingleRegisterID sn)
    1532     {
    1533         m_formatter.vfpOp(0x0a10ee10 | (rd << 28) | singleRegisterMask(sn, 0, 23));
    1534     }
    1535 
    1536     void vmov(FPSingleRegisterID sn, RegisterID rd)
    1537     {
    1538         m_formatter.vfpOp(0x0a10ee00 | (rd << 28) | singleRegisterMask(sn, 0, 23));
    1539     }
    1540 
    1541     // move FPSCR flags to APSR.
    1542     void vmrs_APSR_nzcv_FPSCR()
    1543     {
    1544         m_formatter.vfpOp(0xfa10eef1);
     1543        m_formatter.vfpOp(OP_VMOV_IMM_T2, OP_VMOV_IMM_T2b, true, VFPOperand(0), rd, VFPOperand(0));
     1544    }
     1545
     1546    void vmov(RegisterID rd, FPSingleRegisterID rn)
     1547    {
     1548        ASSERT(!BadReg(rd));
     1549        m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));
     1550    }
     1551
     1552    void vmov(FPSingleRegisterID rd, RegisterID rn)
     1553    {
     1554        ASSERT(!BadReg(rn));
     1555        m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0));
     1556    }
     1557
     1558    void vmrs(RegisterID reg = ARMRegisters::pc)
     1559    {
     1560        ASSERT(reg != ARMRegisters::sp);
     1561        m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
    15451562    }
    15461563
    15471564    void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
    15481565    {
    1549         m_formatter.vfpOp(0x0b00ee20 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
     1566        m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
    15501567    }
    15511568
    15521569    void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
    15531570    {
    1554         vmem(rd, rn, imm, false);
     1571        m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
    15551572    }
    15561573
    15571574    void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
    15581575    {
    1559         m_formatter.vfpOp(0x0b40ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
    1560     }
    1561 
     1576        m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
     1577    }
    15621578
    15631579    JmpDst label()
     
    17211737
    17221738private:
    1723 
    1724     void vcvt(uint32_t rdMask, uint32_t rmMask, bool toInteger, bool isUnsigned, bool isRoundZero, bool isDouble)
     1739    // VFP operations commonly take one or more 5-bit operands, typically representing a
     1740    // floating point register number.  This will commonly be encoded in the instruction
     1741    // in two parts, with one single bit field, and one 4-bit field.  In the case of
     1742    // double precision operands the high bit of the register number will be encoded
     1743    // separately, and for single precision operands the high bit of the register number
     1744    // will be encoded individually.
     1745    // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit
     1746    // field to be encoded together in the instruction (the low 4-bits of a double
     1747    // register number, or the high 4-bits of a single register number), and bit 4
     1748    // contains the bit value to be encoded individually.
     1749    struct VFPOperand {
     1750        explicit VFPOperand(uint32_t value)
     1751            : m_value(value)
     1752        {
     1753            ASSERT(!(m_value & ~0x1f));
     1754        }
     1755
     1756        VFPOperand(FPDoubleRegisterID reg)
     1757            : m_value(reg)
     1758        {
     1759        }
     1760
     1761        VFPOperand(RegisterID reg)
     1762            : m_value(reg)
     1763        {
     1764        }
     1765
     1766        VFPOperand(FPSingleRegisterID reg)
     1767            : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top.
     1768        {
     1769        }
     1770
     1771        uint32_t bits1()
     1772        {
     1773            return m_value >> 4;
     1774        }
     1775
     1776        uint32_t bits4()
     1777        {
     1778            return m_value & 0xf;
     1779        }
     1780
     1781        uint32_t m_value;
     1782    };
     1783
     1784    VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero)
    17251785    {
    17261786        // Cannot specify rounding when converting to float.
    17271787        ASSERT(toInteger || !isRoundZero);
    17281788
    1729         // 'sz' field
    1730         int op = isDouble ? 0x0b40eeb8 : 0x0a40eeb8;
    1731 
     1789        uint32_t op = 0x8;
    17321790        if (toInteger) {
    17331791            // opc2 indicates both toInteger & isUnsigned.
    1734             op |= isUnsigned ? 0x00000004 : 0x00000005;
     1792            op |= isUnsigned ? 0x4 : 0x5;
    17351793            // 'op' field in instruction is isRoundZero
    17361794            if (isRoundZero)
    1737                 op |= 0x00800000;
     1795                op |= 0x10;
    17381796        } else {
    17391797            // 'op' field in instruction is isUnsigned
    17401798            if (!isUnsigned)
    1741                 op |= 0x00800000;
    1742         }
    1743         m_formatter.vfpOp(op | rdMask | rmMask);
    1744     }
    1745 
    1746     // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
    1747     // (i.e. +/-(0..255) 32-bit words)
    1748     void vmem(FPDoubleRegisterID rd, RegisterID rn, int32_t imm, bool isLoad)
    1749     {
    1750         bool up;
    1751         uint32_t offset;
    1752         if (imm < 0) {
    1753             offset = -imm;
    1754             up = false;
    1755         } else {
    1756             offset = imm;
    1757             up = true;
    1758         }
    1759 
    1760         // offset is effectively leftshifted by 2 already (the bottom two bits are zero, and not
    1761         // reperesented in the instruction.  Left shift by 14, to mov it into position 0x00AA0000.
    1762         ASSERT((offset & ~(0xff << 2)) == 0);
    1763         offset <<= 14;
    1764 
    1765         m_formatter.vfpOp(0x0b00ed00 | offset | (up << 7) | (isLoad << 4) | doubleRegisterMask(rd, 6, 28) | rn);
     1799                op |= 0x10;
     1800        }
     1801        return VFPOperand(op);
    17661802    }
    17671803
     
    19531989        }
    19541990
    1955         void vfpOp(int32_t op)
    1956         {
    1957             m_buffer.putInt(op);
    1958         }
    1959 
     1991        // Formats up instructions of the pattern:
     1992        //    111111111B11aaaa:bbbb222SA2C2cccc
     1993        // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
     1994        // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
     1995        void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
     1996        {
     1997            ASSERT(!(op1 & 0x004f));
     1998            ASSERT(!(op2 & 0xf1af));
     1999            m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4());
     2000            m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4());
     2001        }
     2002
     2003        // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
     2004        // (i.e. +/-(0..255) 32-bit words)
     2005        void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
     2006        {
     2007            bool up = true;
     2008            if (imm < 0) {
     2009                imm = -imm;
     2010                up = false;
     2011            }
     2012           
     2013            uint32_t offset = imm;
     2014            ASSERT(!(offset & ~0x3fc));
     2015            offset >>= 2;
     2016
     2017            m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn);
     2018            m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset);
     2019        }
    19602020
    19612021        // Administrative methods:
Note: See TracChangeset for help on using the changeset viewer.