Home | History | Annotate | Download | only in assembler
      1 /*
      2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
      3  * Copyright (C) 2010 University of Szeged
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #ifndef ARMAssembler_h
     28 #define ARMAssembler_h
     29 
     30 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
     31 
     32 #include "AssemblerBuffer.h"
     33 #include <wtf/Assertions.h>
     34 #include <wtf/Vector.h>
     35 #include <stdint.h>
     36 
     37 namespace JSC {
     38 
     39 namespace ARMRegisters {
     40     typedef enum {
     41         r0,
     42         r1,
     43         r2,
     44         r3,
     45         r4,
     46         r5,
     47         r6,
     48         r7, wr = r7,   // thumb work register
     49         r8,
     50         r9, sb = r9,   // static base
     51         r10, sl = r10, // stack limit
     52         r11, fp = r11, // frame pointer
     53         r12, ip = r12,
     54         r13, sp = r13,
     55         r14, lr = r14,
     56         r15, pc = r15,
     57     } RegisterID;
     58 
     59     typedef enum {
     60         s0,
     61         s1,
     62         s2,
     63         s3,
     64         s4,
     65         s5,
     66         s6,
     67         s7,
     68         s8,
     69         s9,
     70         s10,
     71         s11,
     72         s12,
     73         s13,
     74         s14,
     75         s15,
     76         s16,
     77         s17,
     78         s18,
     79         s19,
     80         s20,
     81         s21,
     82         s22,
     83         s23,
     84         s24,
     85         s25,
     86         s26,
     87         s27,
     88         s28,
     89         s29,
     90         s30,
     91         s31,
     92     } FPSingleRegisterID;
     93 
     94     typedef enum {
     95         d0,
     96         d1,
     97         d2,
     98         d3,
     99         d4,
    100         d5,
    101         d6,
    102         d7,
    103         d8,
    104         d9,
    105         d10,
    106         d11,
    107         d12,
    108         d13,
    109         d14,
    110         d15,
    111         d16,
    112         d17,
    113         d18,
    114         d19,
    115         d20,
    116         d21,
    117         d22,
    118         d23,
    119         d24,
    120         d25,
    121         d26,
    122         d27,
    123         d28,
    124         d29,
    125         d30,
    126         d31,
    127     } FPDoubleRegisterID;
    128 
    129     typedef enum {
    130         q0,
    131         q1,
    132         q2,
    133         q3,
    134         q4,
    135         q5,
    136         q6,
    137         q7,
    138         q8,
    139         q9,
    140         q10,
    141         q11,
    142         q12,
    143         q13,
    144         q14,
    145         q15,
    146         q16,
    147         q17,
    148         q18,
    149         q19,
    150         q20,
    151         q21,
    152         q22,
    153         q23,
    154         q24,
    155         q25,
    156         q26,
    157         q27,
    158         q28,
    159         q29,
    160         q30,
    161         q31,
    162     } FPQuadRegisterID;
    163 
    164     inline FPSingleRegisterID asSingle(FPDoubleRegisterID reg)
    165     {
    166         ASSERT(reg < d16);
    167         return (FPSingleRegisterID)(reg << 1);
    168     }
    169 
    170     inline FPDoubleRegisterID asDouble(FPSingleRegisterID reg)
    171     {
    172         ASSERT(!(reg & 1));
    173         return (FPDoubleRegisterID)(reg >> 1);
    174     }
    175 }
    176 
    177 class ARMv7Assembler;
    178 class ARMThumbImmediate {
    179     friend class ARMv7Assembler;
    180 
    181     typedef uint8_t ThumbImmediateType;
    182     static const ThumbImmediateType TypeInvalid = 0;
    183     static const ThumbImmediateType TypeEncoded = 1;
    184     static const ThumbImmediateType TypeUInt16 = 2;
    185 
    186     typedef union {
    187         int16_t asInt;
    188         struct {
    189             unsigned imm8 : 8;
    190             unsigned imm3 : 3;
    191             unsigned i    : 1;
    192             unsigned imm4 : 4;
    193         };
    194         // If this is an encoded immediate, then it may describe a shift, or a pattern.
    195         struct {
    196             unsigned shiftValue7 : 7;
    197             unsigned shiftAmount : 5;
    198         };
    199         struct {
    200             unsigned immediate   : 8;
    201             unsigned pattern     : 4;
    202         };
    203     } ThumbImmediateValue;
    204 
    205     // byte0 contains least significant bit; not using an array to make client code endian agnostic.
    206     typedef union {
    207         int32_t asInt;
    208         struct {
    209             uint8_t byte0;
    210             uint8_t byte1;
    211             uint8_t byte2;
    212             uint8_t byte3;
    213         };
    214     } PatternBytes;
    215 
    216     ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
    217     {
    218         if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
    219             value >>= N;             /* if any were set, lose the bottom N */
    220         else                         /* if none of the top N bits are set, */
    221             zeros += N;              /* then we have identified N leading zeros */
    222     }
    223 
    224     static int32_t countLeadingZeros(uint32_t value)
    225     {
    226         if (!value)
    227             return 32;
    228 
    229         int32_t zeros = 0;
    230         countLeadingZerosPartial(value, zeros, 16);
    231         countLeadingZerosPartial(value, zeros, 8);
    232         countLeadingZerosPartial(value, zeros, 4);
    233         countLeadingZerosPartial(value, zeros, 2);
    234         countLeadingZerosPartial(value, zeros, 1);
    235         return zeros;
    236     }
    237 
    238     ARMThumbImmediate()
    239         : m_type(TypeInvalid)
    240     {
    241         m_value.asInt = 0;
    242     }
    243 
    244     ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
    245         : m_type(type)
    246         , m_value(value)
    247     {
    248     }
    249 
    250     ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
    251         : m_type(TypeUInt16)
    252     {
    253         // Make sure this constructor is only reached with type TypeUInt16;
    254         // this extra parameter makes the code a little clearer by making it
    255         // explicit at call sites which type is being constructed
    256         ASSERT_UNUSED(type, type == TypeUInt16);
    257 
    258         m_value.asInt = value;
    259     }
    260 
    261 public:
    262     static ARMThumbImmediate makeEncodedImm(uint32_t value)
    263     {
    264         ThumbImmediateValue encoding;
    265         encoding.asInt = 0;
    266 
    267         // okay, these are easy.
    268         if (value < 256) {
    269             encoding.immediate = value;
    270             encoding.pattern = 0;
    271             return ARMThumbImmediate(TypeEncoded, encoding);
    272         }
    273 
    274         int32_t leadingZeros = countLeadingZeros(value);
    275         // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
    276         ASSERT(leadingZeros < 24);
    277 
    278         // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
    279         // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
    280         // zero.  count(B) == 8, so the count of bits to be checked is 24 - count(Z).
    281         int32_t rightShiftAmount = 24 - leadingZeros;
    282         if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
    283             // Shift the value down to the low byte position.  The assign to
    284             // shiftValue7 drops the implicit top bit.
    285             encoding.shiftValue7 = value >> rightShiftAmount;
    286             // The endoded shift amount is the magnitude of a right rotate.
    287             encoding.shiftAmount = 8 + leadingZeros;
    288             return ARMThumbImmediate(TypeEncoded, encoding);
    289         }
    290 
    291         PatternBytes bytes;
    292         bytes.asInt = value;
    293 
    294         if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
    295             encoding.immediate = bytes.byte0;
    296             encoding.pattern = 3;
    297             return ARMThumbImmediate(TypeEncoded, encoding);
    298         }
    299 
    300         if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
    301             encoding.immediate = bytes.byte0;
    302             encoding.pattern = 1;
    303             return ARMThumbImmediate(TypeEncoded, encoding);
    304         }
    305 
    306         if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
    307             encoding.immediate = bytes.byte1;
    308             encoding.pattern = 2;
    309             return ARMThumbImmediate(TypeEncoded, encoding);
    310         }
    311 
    312         return ARMThumbImmediate();
    313     }
    314 
    315     static ARMThumbImmediate makeUInt12(int32_t value)
    316     {
    317         return (!(value & 0xfffff000))
    318             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
    319             : ARMThumbImmediate();
    320     }
    321 
    322     static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
    323     {
    324         // If this is not a 12-bit unsigned it, try making an encoded immediate.
    325         return (!(value & 0xfffff000))
    326             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
    327             : makeEncodedImm(value);
    328     }
    329 
    330     // The 'make' methods, above, return a !isValid() value if the argument
    331     // cannot be represented as the requested type.  This methods  is called
    332     // 'get' since the argument can always be represented.
    333     static ARMThumbImmediate makeUInt16(uint16_t value)
    334     {
    335         return ARMThumbImmediate(TypeUInt16, value);
    336     }
    337 
    338     bool isValid()
    339     {
    340         return m_type != TypeInvalid;
    341     }
    342 
    343     // These methods rely on the format of encoded byte values.
    344     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
    345     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
    346     bool isUInt5() { return !(m_value.asInt & 0xffe0); }
    347     bool isUInt6() { return !(m_value.asInt & 0xffc0); }
    348     bool isUInt7() { return !(m_value.asInt & 0xff80); }
    349     bool isUInt8() { return !(m_value.asInt & 0xff00); }
    350     bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
    351     bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
    352     bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
    353     bool isUInt16() { return m_type == TypeUInt16; }
    354     uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
    355     uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
    356     uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
    357     uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
    358     uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
    359     uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
    360     uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
    361     uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
    362     uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
    363     uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
    364 
    365     bool isEncodedImm() { return m_type == TypeEncoded; }
    366 
    367 private:
    368     ThumbImmediateType m_type;
    369     ThumbImmediateValue m_value;
    370 };
    371 
    372 typedef enum {
    373     SRType_LSL,
    374     SRType_LSR,
    375     SRType_ASR,
    376     SRType_ROR,
    377 
    378     SRType_RRX = SRType_ROR
    379 } ARMShiftType;
    380 
    381 class ShiftTypeAndAmount {
    382     friend class ARMv7Assembler;
    383 
    384 public:
    385     ShiftTypeAndAmount()
    386     {
    387         m_u.type = (ARMShiftType)0;
    388         m_u.amount = 0;
    389     }
    390 
    391     ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
    392     {
    393         m_u.type = type;
    394         m_u.amount = amount & 31;
    395     }
    396 
    397     unsigned lo4() { return m_u.lo4; }
    398     unsigned hi4() { return m_u.hi4; }
    399 
    400 private:
    401     union {
    402         struct {
    403             unsigned lo4 : 4;
    404             unsigned hi4 : 4;
    405         };
    406         struct {
    407             unsigned type   : 2;
    408             unsigned amount : 6;
    409         };
    410     } m_u;
    411 };
    412 
    413 class ARMv7Assembler {
    414 public:
    415     ~ARMv7Assembler()
    416     {
    417         ASSERT(m_jumpsToLink.isEmpty());
    418     }
    419 
    420     typedef ARMRegisters::RegisterID RegisterID;
    421     typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
    422     typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
    423     typedef ARMRegisters::FPQuadRegisterID FPQuadRegisterID;
    424 
    425     // (HS, LO, HI, LS) -> (AE, B, A, BE)
    426     // (VS, VC) -> (O, NO)
    427     typedef enum {
    428         ConditionEQ,
    429         ConditionNE,
    430         ConditionHS, ConditionCS = ConditionHS,
    431         ConditionLO, ConditionCC = ConditionLO,
    432         ConditionMI,
    433         ConditionPL,
    434         ConditionVS,
    435         ConditionVC,
    436         ConditionHI,
    437         ConditionLS,
    438         ConditionGE,
    439         ConditionLT,
    440         ConditionGT,
    441         ConditionLE,
    442         ConditionAL,
    443         ConditionInvalid
    444     } Condition;
    445 
    446     enum JumpType { JumpFixed, JumpNoCondition, JumpCondition, JumpNoConditionFixedSize, JumpConditionFixedSize, JumpTypeCount };
    447     enum JumpLinkType { LinkInvalid, LinkJumpT1, LinkJumpT2, LinkJumpT3,
    448         LinkJumpT4, LinkConditionalJumpT4, LinkBX, LinkConditionalBX, JumpLinkTypeCount };
    449     static const int JumpSizes[JumpLinkTypeCount];
    450     static const int JumpPaddingSizes[JumpTypeCount];
    451     class LinkRecord {
    452     public:
    453         LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
    454             : m_from(from)
    455             , m_to(to)
    456             , m_type(type)
    457             , m_linkType(LinkInvalid)
    458             , m_condition(condition)
    459         {
    460         }
    461         intptr_t from() const { return m_from; }
    462         void setFrom(intptr_t from) { m_from = from; }
    463         intptr_t to() const { return m_to; }
    464         JumpType type() const { return m_type; }
    465         JumpLinkType linkType() const { return m_linkType; }
    466         void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; }
    467         Condition condition() const { return m_condition; }
    468     private:
    469         intptr_t m_from : 31;
    470         intptr_t m_to : 31;
    471         JumpType m_type : 3;
    472         JumpLinkType m_linkType : 4;
    473         Condition m_condition : 16;
    474     };
    475 
    476     class JmpSrc {
    477         friend class ARMv7Assembler;
    478         friend class ARMInstructionFormatter;
    479         friend class LinkBuffer;
    480     public:
    481         JmpSrc()
    482             : m_offset(-1)
    483         {
    484         }
    485 
    486     private:
    487         JmpSrc(int offset, JumpType type)
    488             : m_offset(offset)
    489             , m_condition(ConditionInvalid)
    490             , m_type(type)
    491         {
    492             ASSERT(m_type == JumpFixed || m_type == JumpNoCondition || m_type == JumpNoConditionFixedSize);
    493         }
    494 
    495         JmpSrc(int offset, JumpType type, Condition condition)
    496             : m_offset(offset)
    497             , m_condition(condition)
    498             , m_type(type)
    499         {
    500             ASSERT(m_type == JumpFixed || m_type == JumpCondition || m_type == JumpConditionFixedSize);
    501         }
    502 
    503         int m_offset;
    504         Condition m_condition : 16;
    505         JumpType m_type : 16;
    506 
    507     };
    508 
    509     class JmpDst {
    510         friend class ARMv7Assembler;
    511         friend class ARMInstructionFormatter;
    512         friend class LinkBuffer;
    513     public:
    514         JmpDst()
    515             : m_offset(-1)
    516             , m_used(false)
    517         {
    518         }
    519 
    520         bool isUsed() const { return m_used; }
    521         bool isSet() const { return (m_offset != -1); }
    522         void used() { m_used = true; }
    523     private:
    524         JmpDst(int offset)
    525             : m_offset(offset)
    526             , m_used(false)
    527         {
    528             ASSERT(m_offset == offset);
    529         }
    530 
    531         signed int m_offset : 31;
    532         int m_used : 1;
    533     };
    534 
    535 private:
    536 
    537     // ARMv7, Appx-A.6.3
    538     bool BadReg(RegisterID reg)
    539     {
    540         return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
    541     }
    542 
    543     uint32_t singleRegisterMask(FPSingleRegisterID rdNum, int highBitsShift, int lowBitShift)
    544     {
    545         uint32_t rdMask = (rdNum >> 1) << highBitsShift;
    546         if (rdNum & 1)
    547             rdMask |= 1 << lowBitShift;
    548         return rdMask;
    549     }
    550 
    551     uint32_t doubleRegisterMask(FPDoubleRegisterID rdNum, int highBitShift, int lowBitsShift)
    552     {
    553         uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
    554         if (rdNum & 16)
    555             rdMask |= 1 << highBitShift;
    556         return rdMask;
    557     }
    558 
    559     typedef enum {
    560         OP_ADD_reg_T1       = 0x1800,
    561         OP_SUB_reg_T1       = 0x1A00,
    562         OP_ADD_imm_T1       = 0x1C00,
    563         OP_SUB_imm_T1       = 0x1E00,
    564         OP_MOV_imm_T1       = 0x2000,
    565         OP_CMP_imm_T1       = 0x2800,
    566         OP_ADD_imm_T2       = 0x3000,
    567         OP_SUB_imm_T2       = 0x3800,
    568         OP_AND_reg_T1       = 0x4000,
    569         OP_EOR_reg_T1       = 0x4040,
    570         OP_TST_reg_T1       = 0x4200,
    571         OP_RSB_imm_T1       = 0x4240,
    572         OP_CMP_reg_T1       = 0x4280,
    573         OP_ORR_reg_T1       = 0x4300,
    574         OP_MVN_reg_T1       = 0x43C0,
    575         OP_ADD_reg_T2       = 0x4400,
    576         OP_MOV_reg_T1       = 0x4600,
    577         OP_BLX              = 0x4700,
    578         OP_BX               = 0x4700,
    579         OP_STR_reg_T1       = 0x5000,
    580         OP_LDR_reg_T1       = 0x5800,
    581         OP_LDRH_reg_T1      = 0x5A00,
    582         OP_LDRB_reg_T1      = 0x5C00,
    583         OP_STR_imm_T1       = 0x6000,
    584         OP_LDR_imm_T1       = 0x6800,
    585         OP_LDRB_imm_T1      = 0x7800,
    586         OP_LDRH_imm_T1      = 0x8800,
    587         OP_STR_imm_T2       = 0x9000,
    588         OP_LDR_imm_T2       = 0x9800,
    589         OP_ADD_SP_imm_T1    = 0xA800,
    590         OP_ADD_SP_imm_T2    = 0xB000,
    591         OP_SUB_SP_imm_T1    = 0xB080,
    592         OP_BKPT             = 0xBE00,
    593         OP_IT               = 0xBF00,
    594         OP_NOP_T1           = 0xBF00,
    595     } OpcodeID;
    596 
    597     typedef enum {
    598         OP_B_T1         = 0xD000,
    599         OP_B_T2         = 0xE000,
    600         OP_AND_reg_T2   = 0xEA00,
    601         OP_TST_reg_T2   = 0xEA10,
    602         OP_ORR_reg_T2   = 0xEA40,
    603         OP_ORR_S_reg_T2 = 0xEA50,
    604         OP_ASR_imm_T1   = 0xEA4F,
    605         OP_LSL_imm_T1   = 0xEA4F,
    606         OP_LSR_imm_T1   = 0xEA4F,
    607         OP_ROR_imm_T1   = 0xEA4F,
    608         OP_MVN_reg_T2   = 0xEA6F,
    609         OP_EOR_reg_T2   = 0xEA80,
    610         OP_ADD_reg_T3   = 0xEB00,
    611         OP_ADD_S_reg_T3 = 0xEB10,
    612         OP_SUB_reg_T2   = 0xEBA0,
    613         OP_SUB_S_reg_T2 = 0xEBB0,
    614         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         = 0xEEB0,
    624         OP_VCVT_FPIVFP  = 0xEEB0,
    625         OP_VMOV_IMM_T2  = 0xEEB0,
    626         OP_VMRS         = 0xEEB0,
    627         OP_B_T3a        = 0xF000,
    628         OP_B_T4a        = 0xF000,
    629         OP_AND_imm_T1   = 0xF000,
    630         OP_TST_imm      = 0xF010,
    631         OP_ORR_imm_T1   = 0xF040,
    632         OP_MOV_imm_T2   = 0xF040,
    633         OP_MVN_imm      = 0xF060,
    634         OP_EOR_imm_T1   = 0xF080,
    635         OP_ADD_imm_T3   = 0xF100,
    636         OP_ADD_S_imm_T3 = 0xF110,
    637         OP_CMN_imm      = 0xF110,
    638         OP_SUB_imm_T3   = 0xF1A0,
    639         OP_SUB_S_imm_T3 = 0xF1B0,
    640         OP_CMP_imm_T2   = 0xF1B0,
    641         OP_RSB_imm_T2   = 0xF1C0,
    642         OP_ADD_imm_T4   = 0xF200,
    643         OP_MOV_imm_T3   = 0xF240,
    644         OP_SUB_imm_T4   = 0xF2A0,
    645         OP_MOVT         = 0xF2C0,
    646         OP_NOP_T2a      = 0xF3AF,
    647         OP_LDRB_imm_T3  = 0xF810,
    648         OP_LDRB_reg_T2  = 0xF810,
    649         OP_LDRH_reg_T2  = 0xF830,
    650         OP_LDRH_imm_T3  = 0xF830,
    651         OP_STR_imm_T4   = 0xF840,
    652         OP_STR_reg_T2   = 0xF840,
    653         OP_LDR_imm_T4   = 0xF850,
    654         OP_LDR_reg_T2   = 0xF850,
    655         OP_LDRB_imm_T2  = 0xF890,
    656         OP_LDRH_imm_T2  = 0xF8B0,
    657         OP_STR_imm_T3   = 0xF8C0,
    658         OP_LDR_imm_T3   = 0xF8D0,
    659         OP_LSL_reg_T2   = 0xFA00,
    660         OP_LSR_reg_T2   = 0xFA20,
    661         OP_ASR_reg_T2   = 0xFA40,
    662         OP_ROR_reg_T2   = 0xFA60,
    663         OP_CLZ          = 0xFAB0,
    664         OP_SMULL_T1     = 0xFB80,
    665     } OpcodeID1;
    666 
    667     typedef enum {
    668         OP_VADD_T2b     = 0x0A00,
    669         OP_VDIVb        = 0x0A00,
    670         OP_VLDRb        = 0x0A00,
    671         OP_VMOV_IMM_T2b = 0x0A00,
    672         OP_VMUL_T2b     = 0x0A00,
    673         OP_VSTRb        = 0x0A00,
    674         OP_VMOV_CtoSb   = 0x0A10,
    675         OP_VMOV_StoCb   = 0x0A10,
    676         OP_VMRSb        = 0x0A10,
    677         OP_VCMPb        = 0x0A40,
    678         OP_VCVT_FPIVFPb = 0x0A40,
    679         OP_VSUB_T2b     = 0x0A40,
    680         OP_NOP_T2b      = 0x8000,
    681         OP_B_T3b        = 0x8000,
    682         OP_B_T4b        = 0x9000,
    683     } OpcodeID2;
    684 
    685     struct FourFours {
    686         FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
    687         {
    688             m_u.f0 = f0;
    689             m_u.f1 = f1;
    690             m_u.f2 = f2;
    691             m_u.f3 = f3;
    692         }
    693 
    694         union {
    695             unsigned value;
    696             struct {
    697                 unsigned f0 : 4;
    698                 unsigned f1 : 4;
    699                 unsigned f2 : 4;
    700                 unsigned f3 : 4;
    701             };
    702         } m_u;
    703     };
    704 
    705     class ARMInstructionFormatter;
    706 
    707     // false means else!
    708     bool ifThenElseConditionBit(Condition condition, bool isIf)
    709     {
    710         return isIf ? (condition & 1) : !(condition & 1);
    711     }
    712     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
    713     {
    714         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
    715             | (ifThenElseConditionBit(condition, inst3if) << 2)
    716             | (ifThenElseConditionBit(condition, inst4if) << 1)
    717             | 1;
    718         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
    719         return (condition << 4) | mask;
    720     }
    721     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
    722     {
    723         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
    724             | (ifThenElseConditionBit(condition, inst3if) << 2)
    725             | 2;
    726         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
    727         return (condition << 4) | mask;
    728     }
    729     uint8_t ifThenElse(Condition condition, bool inst2if)
    730     {
    731         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
    732             | 4;
    733         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
    734         return (condition << 4) | mask;
    735     }
    736 
    737     uint8_t ifThenElse(Condition condition)
    738     {
    739         int mask = 8;
    740         return (condition << 4) | mask;
    741     }
    742 
    743 public:
    744 
    745     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    746     {
    747         // Rd can only be SP if Rn is also SP.
    748         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
    749         ASSERT(rd != ARMRegisters::pc);
    750         ASSERT(rn != ARMRegisters::pc);
    751         ASSERT(imm.isValid());
    752 
    753         if (rn == ARMRegisters::sp) {
    754             if (!(rd & 8) && imm.isUInt10()) {
    755                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
    756                 return;
    757             } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
    758                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
    759                 return;
    760             }
    761         } else if (!((rd | rn) & 8)) {
    762             if (imm.isUInt3()) {
    763                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
    764                 return;
    765             } else if ((rd == rn) && imm.isUInt8()) {
    766                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
    767                 return;
    768             }
    769         }
    770 
    771         if (imm.isEncodedImm())
    772             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
    773         else {
    774             ASSERT(imm.isUInt12());
    775             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
    776         }
    777     }
    778 
    779     void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    780     {
    781         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
    782         ASSERT(rd != ARMRegisters::pc);
    783         ASSERT(rn != ARMRegisters::pc);
    784         ASSERT(!BadReg(rm));
    785         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    786     }
    787 
    788     // NOTE: In an IT block, add doesn't modify the flags register.
    789     void add(RegisterID rd, RegisterID rn, RegisterID rm)
    790     {
    791         if (rd == rn)
    792             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
    793         else if (rd == rm)
    794             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
    795         else if (!((rd | rn | rm) & 8))
    796             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
    797         else
    798             add(rd, rn, rm, ShiftTypeAndAmount());
    799     }
    800 
    801     // Not allowed in an IT (if then) block.
    802     void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    803     {
    804         // Rd can only be SP if Rn is also SP.
    805         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
    806         ASSERT(rd != ARMRegisters::pc);
    807         ASSERT(rn != ARMRegisters::pc);
    808         ASSERT(imm.isEncodedImm());
    809 
    810         if (!((rd | rn) & 8)) {
    811             if (imm.isUInt3()) {
    812                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
    813                 return;
    814             } else if ((rd == rn) && imm.isUInt8()) {
    815                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
    816                 return;
    817             }
    818         }
    819 
    820         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
    821     }
    822 
    823     // Not allowed in an IT (if then) block?
    824     void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    825     {
    826         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
    827         ASSERT(rd != ARMRegisters::pc);
    828         ASSERT(rn != ARMRegisters::pc);
    829         ASSERT(!BadReg(rm));
    830         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    831     }
    832 
    833     // Not allowed in an IT (if then) block.
    834     void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
    835     {
    836         if (!((rd | rn | rm) & 8))
    837             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
    838         else
    839             add_S(rd, rn, rm, ShiftTypeAndAmount());
    840     }
    841 
    842     void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    843     {
    844         ASSERT(!BadReg(rd));
    845         ASSERT(!BadReg(rn));
    846         ASSERT(imm.isEncodedImm());
    847         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
    848     }
    849 
    850     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    851     {
    852         ASSERT(!BadReg(rd));
    853         ASSERT(!BadReg(rn));
    854         ASSERT(!BadReg(rm));
    855         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    856     }
    857 
    858     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
    859     {
    860         if ((rd == rn) && !((rd | rm) & 8))
    861             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
    862         else if ((rd == rm) && !((rd | rn) & 8))
    863             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
    864         else
    865             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
    866     }
    867 
    868     void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
    869     {
    870         ASSERT(!BadReg(rd));
    871         ASSERT(!BadReg(rm));
    872         ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
    873         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    874     }
    875 
    876     void asr(RegisterID rd, RegisterID rn, RegisterID rm)
    877     {
    878         ASSERT(!BadReg(rd));
    879         ASSERT(!BadReg(rn));
    880         ASSERT(!BadReg(rm));
    881         m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
    882     }
    883 
    884     // Only allowed in IT (if then) block if last instruction.
    885     JmpSrc b(JumpType type)
    886     {
    887         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
    888         return JmpSrc(m_formatter.size(), type);
    889     }
    890 
    891     // Only allowed in IT (if then) block if last instruction.
    892     JmpSrc blx(RegisterID rm, JumpType type)
    893     {
    894         ASSERT(rm != ARMRegisters::pc);
    895         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
    896         return JmpSrc(m_formatter.size(), type);
    897     }
    898 
    899     // Only allowed in IT (if then) block if last instruction.
    900     JmpSrc bx(RegisterID rm, JumpType type, Condition condition)
    901     {
    902         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
    903         return JmpSrc(m_formatter.size(), type, condition);
    904     }
    905 
    906     JmpSrc bx(RegisterID rm, JumpType type)
    907     {
    908         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
    909         return JmpSrc(m_formatter.size(), type);
    910     }
    911 
    912     void bkpt(uint8_t imm=0)
    913     {
    914         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
    915     }
    916 
    917     void clz(RegisterID rd, RegisterID rm)
    918     {
    919         ASSERT(!BadReg(rd));
    920         ASSERT(!BadReg(rm));
    921         m_formatter.twoWordOp12Reg4FourFours(OP_CLZ, rm, FourFours(0xf, rd, 8, rm));
    922     }
    923 
    924     void cmn(RegisterID rn, ARMThumbImmediate imm)
    925     {
    926         ASSERT(rn != ARMRegisters::pc);
    927         ASSERT(imm.isEncodedImm());
    928 
    929         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
    930     }
    931 
    932     void cmp(RegisterID rn, ARMThumbImmediate imm)
    933     {
    934         ASSERT(rn != ARMRegisters::pc);
    935         ASSERT(imm.isEncodedImm());
    936 
    937         if (!(rn & 8) && imm.isUInt8())
    938             m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
    939         else
    940             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
    941     }
    942 
    943     void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    944     {
    945         ASSERT(rn != ARMRegisters::pc);
    946         ASSERT(!BadReg(rm));
    947         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
    948     }
    949 
    950     void cmp(RegisterID rn, RegisterID rm)
    951     {
    952         if ((rn | rm) & 8)
    953             cmp(rn, rm, ShiftTypeAndAmount());
    954         else
    955             m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
    956     }
    957 
    958     // xor is not spelled with an 'e'. :-(
    959     void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    960     {
    961         ASSERT(!BadReg(rd));
    962         ASSERT(!BadReg(rn));
    963         ASSERT(imm.isEncodedImm());
    964         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
    965     }
    966 
    967     // xor is not spelled with an 'e'. :-(
    968     void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    969     {
    970         ASSERT(!BadReg(rd));
    971         ASSERT(!BadReg(rn));
    972         ASSERT(!BadReg(rm));
    973         m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    974     }
    975 
    976     // xor is not spelled with an 'e'. :-(
    977     void eor(RegisterID rd, RegisterID rn, RegisterID rm)
    978     {
    979         if ((rd == rn) && !((rd | rm) & 8))
    980             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
    981         else if ((rd == rm) && !((rd | rn) & 8))
    982             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
    983         else
    984             eor(rd, rn, rm, ShiftTypeAndAmount());
    985     }
    986 
    987     void it(Condition cond)
    988     {
    989         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
    990     }
    991 
    992     void it(Condition cond, bool inst2if)
    993     {
    994         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
    995     }
    996 
    997     void it(Condition cond, bool inst2if, bool inst3if)
    998     {
    999         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
   1000     }
   1001 
   1002     void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
   1003     {
   1004         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
   1005     }
   1006 
   1007     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1008     void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
   1009     {
   1010         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
   1011         ASSERT(imm.isUInt12());
   1012 
   1013         if (!((rt | rn) & 8) && imm.isUInt7())
   1014             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
   1015         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
   1016             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
   1017         else
   1018             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
   1019     }
   1020 
   1021     // If index is set, this is a regular offset or a pre-indexed load;
   1022     // if index is not set then is is a post-index load.
   1023     //
   1024     // If wback is set rn is updated - this is a pre or post index load,
   1025     // if wback is not set this is a regular offset memory access.
   1026     //
   1027     // (-255 <= offset <= 255)
   1028     // _reg = REG[rn]
   1029     // _tmp = _reg + offset
   1030     // MEM[index ? _tmp : _reg] = REG[rt]
   1031     // if (wback) REG[rn] = _tmp
   1032     void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
   1033     {
   1034         ASSERT(rt != ARMRegisters::pc);
   1035         ASSERT(rn != ARMRegisters::pc);
   1036         ASSERT(index || wback);
   1037         ASSERT(!wback | (rt != rn));
   1038 
   1039         bool add = true;
   1040         if (offset < 0) {
   1041             add = false;
   1042             offset = -offset;
   1043         }
   1044         ASSERT((offset & ~0xff) == 0);
   1045 
   1046         offset |= (wback << 8);
   1047         offset |= (add   << 9);
   1048         offset |= (index << 10);
   1049         offset |= (1 << 11);
   1050 
   1051         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
   1052     }
   1053 
   1054     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1055     void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
   1056     {
   1057         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
   1058         ASSERT(!BadReg(rm));
   1059         ASSERT(shift <= 3);
   1060 
   1061         if (!shift && !((rt | rn | rm) & 8))
   1062             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
   1063         else
   1064             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
   1065     }
   1066 
   1067     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1068     void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
   1069     {
   1070         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
   1071         ASSERT(imm.isUInt12());
   1072 
   1073         if (!((rt | rn) & 8) && imm.isUInt6())
   1074             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
   1075         else
   1076             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
   1077     }
   1078 
   1079     // If index is set, this is a regular offset or a pre-indexed load;
   1080     // if index is not set then is is a post-index load.
   1081     //
   1082     // If wback is set rn is updated - this is a pre or post index load,
   1083     // if wback is not set this is a regular offset memory access.
   1084     //
   1085     // (-255 <= offset <= 255)
   1086     // _reg = REG[rn]
   1087     // _tmp = _reg + offset
   1088     // MEM[index ? _tmp : _reg] = REG[rt]
   1089     // if (wback) REG[rn] = _tmp
   1090     void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
   1091     {
   1092         ASSERT(rt != ARMRegisters::pc);
   1093         ASSERT(rn != ARMRegisters::pc);
   1094         ASSERT(index || wback);
   1095         ASSERT(!wback | (rt != rn));
   1096 
   1097         bool add = true;
   1098         if (offset < 0) {
   1099             add = false;
   1100             offset = -offset;
   1101         }
   1102         ASSERT((offset & ~0xff) == 0);
   1103 
   1104         offset |= (wback << 8);
   1105         offset |= (add   << 9);
   1106         offset |= (index << 10);
   1107         offset |= (1 << 11);
   1108 
   1109         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
   1110     }
   1111 
   1112     void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
   1113     {
   1114         ASSERT(!BadReg(rt));   // Memory hint
   1115         ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
   1116         ASSERT(!BadReg(rm));
   1117         ASSERT(shift <= 3);
   1118 
   1119         if (!shift && !((rt | rn | rm) & 8))
   1120             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
   1121         else
   1122             m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
   1123     }
   1124 
   1125     void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
   1126     {
   1127         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
   1128         ASSERT(imm.isUInt12());
   1129 
   1130         if (!((rt | rn) & 8) && imm.isUInt5())
   1131             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
   1132         else
   1133             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
   1134     }
   1135 
   1136     void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
   1137     {
   1138         ASSERT(rt != ARMRegisters::pc);
   1139         ASSERT(rn != ARMRegisters::pc);
   1140         ASSERT(index || wback);
   1141         ASSERT(!wback | (rt != rn));
   1142 
   1143         bool add = true;
   1144         if (offset < 0) {
   1145             add = false;
   1146             offset = -offset;
   1147         }
   1148 
   1149         ASSERT(!(offset & ~0xff));
   1150 
   1151         offset |= (wback << 8);
   1152         offset |= (add   << 9);
   1153         offset |= (index << 10);
   1154         offset |= (1 << 11);
   1155 
   1156         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
   1157     }
   1158 
   1159     void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
   1160     {
   1161         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
   1162         ASSERT(!BadReg(rm));
   1163         ASSERT(shift <= 3);
   1164 
   1165         if (!shift && !((rt | rn | rm) & 8))
   1166             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
   1167         else
   1168             m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
   1169     }
   1170 
   1171     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
   1172     {
   1173         ASSERT(!BadReg(rd));
   1174         ASSERT(!BadReg(rm));
   1175         ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
   1176         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1177     }
   1178 
   1179     void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
   1180     {
   1181         ASSERT(!BadReg(rd));
   1182         ASSERT(!BadReg(rn));
   1183         ASSERT(!BadReg(rm));
   1184         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
   1185     }
   1186 
   1187     void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
   1188     {
   1189         ASSERT(!BadReg(rd));
   1190         ASSERT(!BadReg(rm));
   1191         ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
   1192         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1193     }
   1194 
   1195     void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
   1196     {
   1197         ASSERT(!BadReg(rd));
   1198         ASSERT(!BadReg(rn));
   1199         ASSERT(!BadReg(rm));
   1200         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
   1201     }
   1202 
   1203     void movT3(RegisterID rd, ARMThumbImmediate imm)
   1204     {
   1205         ASSERT(imm.isValid());
   1206         ASSERT(!imm.isEncodedImm());
   1207         ASSERT(!BadReg(rd));
   1208 
   1209         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
   1210     }
   1211 
   1212      void mov(RegisterID rd, ARMThumbImmediate imm)
   1213     {
   1214         ASSERT(imm.isValid());
   1215         ASSERT(!BadReg(rd));
   1216 
   1217         if ((rd < 8) && imm.isUInt8())
   1218             m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
   1219         else if (imm.isEncodedImm())
   1220             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
   1221         else
   1222             movT3(rd, imm);
   1223     }
   1224 
   1225    void mov(RegisterID rd, RegisterID rm)
   1226     {
   1227         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
   1228     }
   1229 
   1230     void movt(RegisterID rd, ARMThumbImmediate imm)
   1231     {
   1232         ASSERT(imm.isUInt16());
   1233         ASSERT(!BadReg(rd));
   1234         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
   1235     }
   1236 
   1237     void mvn(RegisterID rd, ARMThumbImmediate imm)
   1238     {
   1239         ASSERT(imm.isEncodedImm());
   1240         ASSERT(!BadReg(rd));
   1241 
   1242         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
   1243     }
   1244 
   1245     void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
   1246     {
   1247         ASSERT(!BadReg(rd));
   1248         ASSERT(!BadReg(rm));
   1249         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1250     }
   1251 
   1252     void mvn(RegisterID rd, RegisterID rm)
   1253     {
   1254         if (!((rd | rm) & 8))
   1255             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
   1256         else
   1257             mvn(rd, rm, ShiftTypeAndAmount());
   1258     }
   1259 
   1260     void neg(RegisterID rd, RegisterID rm)
   1261     {
   1262         ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
   1263         sub(rd, zero, rm);
   1264     }
   1265 
   1266     void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
   1267     {
   1268         ASSERT(!BadReg(rd));
   1269         ASSERT(!BadReg(rn));
   1270         ASSERT(imm.isEncodedImm());
   1271         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
   1272     }
   1273 
   1274     void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1275     {
   1276         ASSERT(!BadReg(rd));
   1277         ASSERT(!BadReg(rn));
   1278         ASSERT(!BadReg(rm));
   1279         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1280     }
   1281 
   1282     void orr(RegisterID rd, RegisterID rn, RegisterID rm)
   1283     {
   1284         if ((rd == rn) && !((rd | rm) & 8))
   1285             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
   1286         else if ((rd == rm) && !((rd | rn) & 8))
   1287             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
   1288         else
   1289             orr(rd, rn, rm, ShiftTypeAndAmount());
   1290     }
   1291 
   1292     void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1293     {
   1294         ASSERT(!BadReg(rd));
   1295         ASSERT(!BadReg(rn));
   1296         ASSERT(!BadReg(rm));
   1297         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1298     }
   1299 
   1300     void orr_S(RegisterID rd, RegisterID rn, RegisterID rm)
   1301     {
   1302         if ((rd == rn) && !((rd | rm) & 8))
   1303             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
   1304         else if ((rd == rm) && !((rd | rn) & 8))
   1305             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
   1306         else
   1307             orr_S(rd, rn, rm, ShiftTypeAndAmount());
   1308     }
   1309 
   1310     void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
   1311     {
   1312         ASSERT(!BadReg(rd));
   1313         ASSERT(!BadReg(rm));
   1314         ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
   1315         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1316     }
   1317 
   1318     void ror(RegisterID rd, RegisterID rn, RegisterID rm)
   1319     {
   1320         ASSERT(!BadReg(rd));
   1321         ASSERT(!BadReg(rn));
   1322         ASSERT(!BadReg(rm));
   1323         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
   1324     }
   1325 
   1326     void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
   1327     {
   1328         ASSERT(!BadReg(rdLo));
   1329         ASSERT(!BadReg(rdHi));
   1330         ASSERT(!BadReg(rn));
   1331         ASSERT(!BadReg(rm));
   1332         ASSERT(rdLo != rdHi);
   1333         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
   1334     }
   1335 
   1336     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1337     void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
   1338     {
   1339         ASSERT(rt != ARMRegisters::pc);
   1340         ASSERT(rn != ARMRegisters::pc);
   1341         ASSERT(imm.isUInt12());
   1342 
   1343         if (!((rt | rn) & 8) && imm.isUInt7())
   1344             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
   1345         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
   1346             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
   1347         else
   1348             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
   1349     }
   1350 
   1351     // If index is set, this is a regular offset or a pre-indexed store;
   1352     // if index is not set then is is a post-index store.
   1353     //
   1354     // If wback is set rn is updated - this is a pre or post index store,
   1355     // if wback is not set this is a regular offset memory access.
   1356     //
   1357     // (-255 <= offset <= 255)
   1358     // _reg = REG[rn]
   1359     // _tmp = _reg + offset
   1360     // MEM[index ? _tmp : _reg] = REG[rt]
   1361     // if (wback) REG[rn] = _tmp
   1362     void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
   1363     {
   1364         ASSERT(rt != ARMRegisters::pc);
   1365         ASSERT(rn != ARMRegisters::pc);
   1366         ASSERT(index || wback);
   1367         ASSERT(!wback | (rt != rn));
   1368 
   1369         bool add = true;
   1370         if (offset < 0) {
   1371             add = false;
   1372             offset = -offset;
   1373         }
   1374         ASSERT((offset & ~0xff) == 0);
   1375 
   1376         offset |= (wback << 8);
   1377         offset |= (add   << 9);
   1378         offset |= (index << 10);
   1379         offset |= (1 << 11);
   1380 
   1381         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
   1382     }
   1383 
   1384     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1385     void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
   1386     {
   1387         ASSERT(rn != ARMRegisters::pc);
   1388         ASSERT(!BadReg(rm));
   1389         ASSERT(shift <= 3);
   1390 
   1391         if (!shift && !((rt | rn | rm) & 8))
   1392             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
   1393         else
   1394             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
   1395     }
   1396 
   1397     void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
   1398     {
   1399         // Rd can only be SP if Rn is also SP.
   1400         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
   1401         ASSERT(rd != ARMRegisters::pc);
   1402         ASSERT(rn != ARMRegisters::pc);
   1403         ASSERT(imm.isValid());
   1404 
   1405         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
   1406             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
   1407             return;
   1408         } else if (!((rd | rn) & 8)) {
   1409             if (imm.isUInt3()) {
   1410                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
   1411                 return;
   1412             } else if ((rd == rn) && imm.isUInt8()) {
   1413                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
   1414                 return;
   1415             }
   1416         }
   1417 
   1418         if (imm.isEncodedImm())
   1419             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
   1420         else {
   1421             ASSERT(imm.isUInt12());
   1422             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
   1423         }
   1424     }
   1425 
   1426     void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
   1427     {
   1428         ASSERT(rd != ARMRegisters::pc);
   1429         ASSERT(rn != ARMRegisters::pc);
   1430         ASSERT(imm.isValid());
   1431         ASSERT(imm.isUInt12());
   1432 
   1433         if (!((rd | rn) & 8) && !imm.getUInt12())
   1434             m_formatter.oneWordOp10Reg3Reg3(OP_RSB_imm_T1, rn, rd);
   1435         else
   1436             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
   1437     }
   1438 
   1439     void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1440     {
   1441         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
   1442         ASSERT(rd != ARMRegisters::pc);
   1443         ASSERT(rn != ARMRegisters::pc);
   1444         ASSERT(!BadReg(rm));
   1445         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1446     }
   1447 
   1448     // NOTE: In an IT block, add doesn't modify the flags register.
   1449     void sub(RegisterID rd, RegisterID rn, RegisterID rm)
   1450     {
   1451         if (!((rd | rn | rm) & 8))
   1452             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
   1453         else
   1454             sub(rd, rn, rm, ShiftTypeAndAmount());
   1455     }
   1456 
   1457     // Not allowed in an IT (if then) block.
   1458     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
   1459     {
   1460         // Rd can only be SP if Rn is also SP.
   1461         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
   1462         ASSERT(rd != ARMRegisters::pc);
   1463         ASSERT(rn != ARMRegisters::pc);
   1464         ASSERT(imm.isValid());
   1465 
   1466         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
   1467             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
   1468             return;
   1469         } else if (!((rd | rn) & 8)) {
   1470             if (imm.isUInt3()) {
   1471                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
   1472                 return;
   1473             } else if ((rd == rn) && imm.isUInt8()) {
   1474                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
   1475                 return;
   1476             }
   1477         }
   1478 
   1479         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
   1480     }
   1481 
   1482     // Not allowed in an IT (if then) block?
   1483     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1484     {
   1485         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
   1486         ASSERT(rd != ARMRegisters::pc);
   1487         ASSERT(rn != ARMRegisters::pc);
   1488         ASSERT(!BadReg(rm));
   1489         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1490     }
   1491 
   1492     // Not allowed in an IT (if then) block.
   1493     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
   1494     {
   1495         if (!((rd | rn | rm) & 8))
   1496             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
   1497         else
   1498             sub_S(rd, rn, rm, ShiftTypeAndAmount());
   1499     }
   1500 
   1501     void tst(RegisterID rn, ARMThumbImmediate imm)
   1502     {
   1503         ASSERT(!BadReg(rn));
   1504         ASSERT(imm.isEncodedImm());
   1505 
   1506         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
   1507     }
   1508 
   1509     void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1510     {
   1511         ASSERT(!BadReg(rn));
   1512         ASSERT(!BadReg(rm));
   1513         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
   1514     }
   1515 
   1516     void tst(RegisterID rn, RegisterID rm)
   1517     {
   1518         if ((rn | rm) & 8)
   1519             tst(rn, rm, ShiftTypeAndAmount());
   1520         else
   1521             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
   1522     }
   1523 
   1524     void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
   1525     {
   1526         m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
   1527     }
   1528 
   1529     void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
   1530     {
   1531         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
   1532     }
   1533 
   1534     void vcmpz_F64(FPDoubleRegisterID rd)
   1535     {
   1536         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
   1537     }
   1538 
   1539     void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)
   1540     {
   1541         // boolean values are 64bit (toInt, unsigned, roundZero)
   1542         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
   1543     }
   1544 
   1545     void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)
   1546     {
   1547         // boolean values are 64bit (toInt, unsigned, roundZero)
   1548         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
   1549     }
   1550 
   1551     void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
   1552     {
   1553         m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
   1554     }
   1555 
   1556     void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
   1557     {
   1558         m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
   1559     }
   1560 
   1561     void vmov(RegisterID rd, FPSingleRegisterID rn)
   1562     {
   1563         ASSERT(!BadReg(rd));
   1564         m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));
   1565     }
   1566 
   1567     void vmov(FPSingleRegisterID rd, RegisterID rn)
   1568     {
   1569         ASSERT(!BadReg(rn));
   1570         m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0));
   1571     }
   1572 
   1573     void vmrs(RegisterID reg = ARMRegisters::pc)
   1574     {
   1575         ASSERT(reg != ARMRegisters::sp);
   1576         m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
   1577     }
   1578 
   1579     void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
   1580     {
   1581         m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
   1582     }
   1583 
   1584     void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
   1585     {
   1586         m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
   1587     }
   1588 
   1589     void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
   1590     {
   1591         m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
   1592     }
   1593 
   1594     JmpDst label()
   1595     {
   1596         return JmpDst(m_formatter.size());
   1597     }
   1598 
   1599     JmpDst align(int alignment)
   1600     {
   1601         while (!m_formatter.isAligned(alignment))
   1602             bkpt();
   1603 
   1604         return label();
   1605     }
   1606 
   1607     static void* getRelocatedAddress(void* code, JmpSrc jump)
   1608     {
   1609         ASSERT(jump.m_offset != -1);
   1610 
   1611         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
   1612     }
   1613 
   1614     static void* getRelocatedAddress(void* code, JmpDst destination)
   1615     {
   1616         ASSERT(destination.m_offset != -1);
   1617 
   1618         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
   1619     }
   1620 
   1621     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
   1622     {
   1623         return dst.m_offset - src.m_offset;
   1624     }
   1625 
   1626     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
   1627     {
   1628         return dst.m_offset - src.m_offset;
   1629     }
   1630 
   1631     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
   1632     {
   1633         return dst.m_offset - src.m_offset;
   1634     }
   1635 
   1636     int executableOffsetFor(int location)
   1637     {
   1638         if (!location)
   1639             return 0;
   1640         return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1];
   1641     }
   1642 
   1643     int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JumpPaddingSizes[jumpType] - JumpSizes[jumpLinkType]; }
   1644 
   1645     // Assembler admin methods:
   1646 
   1647     size_t size() const
   1648     {
   1649         return m_formatter.size();
   1650     }
   1651 
   1652     static bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
   1653     {
   1654         return a.from() < b.from();
   1655     }
   1656 
   1657     bool canCompact(JumpType jumpType)
   1658     {
   1659         // The following cannot be compacted:
   1660         //   JumpFixed: represents custom jump sequence
   1661         //   JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size
   1662         //   JumpConditionFixedSize: represents conditional jump that must remain a fixed size
   1663         return (jumpType == JumpNoCondition) || (jumpType == JumpCondition);
   1664     }
   1665 
   1666     JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
   1667     {
   1668         if (jumpType == JumpFixed)
   1669             return LinkInvalid;
   1670 
   1671         // for patchable jump we must leave space for the longest code sequence
   1672         if (jumpType == JumpNoConditionFixedSize)
   1673             return LinkBX;
   1674         if (jumpType == JumpConditionFixedSize)
   1675             return LinkConditionalBX;
   1676 
   1677         const int paddingSize = JumpPaddingSizes[jumpType];
   1678         bool mayTriggerErrata = false;
   1679 
   1680         if (jumpType == JumpCondition) {
   1681             // 2-byte conditional T1
   1682             const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT1]));
   1683             if (canBeJumpT1(jumpT1Location, to))
   1684                 return LinkJumpT1;
   1685             // 4-byte conditional T3
   1686             const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT3]));
   1687             if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) {
   1688                 if (!mayTriggerErrata)
   1689                     return LinkJumpT3;
   1690             }
   1691             // 4-byte conditional T4 with IT
   1692             const uint16_t* conditionalJumpT4Location =
   1693             reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkConditionalJumpT4]));
   1694             if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) {
   1695                 if (!mayTriggerErrata)
   1696                     return LinkConditionalJumpT4;
   1697             }
   1698         } else {
   1699             // 2-byte unconditional T2
   1700             const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT2]));
   1701             if (canBeJumpT2(jumpT2Location, to))
   1702                 return LinkJumpT2;
   1703             // 4-byte unconditional T4
   1704             const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT4]));
   1705             if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) {
   1706                 if (!mayTriggerErrata)
   1707                     return LinkJumpT4;
   1708             }
   1709             // use long jump sequence
   1710             return LinkBX;
   1711         }
   1712 
   1713         ASSERT(jumpType == JumpCondition);
   1714         return LinkConditionalBX;
   1715     }
   1716 
   1717     JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
   1718     {
   1719         JumpLinkType linkType = computeJumpType(record.type(), from, to);
   1720         record.setLinkType(linkType);
   1721         return linkType;
   1722     }
   1723 
   1724     void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
   1725     {
   1726         int32_t ptr = regionStart / sizeof(int32_t);
   1727         const int32_t end = regionEnd / sizeof(int32_t);
   1728         int32_t* offsets = static_cast<int32_t*>(m_formatter.data());
   1729         while (ptr < end)
   1730             offsets[ptr++] = offset;
   1731     }
   1732 
   1733     Vector<LinkRecord>& jumpsToLink()
   1734     {
   1735         std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
   1736         return m_jumpsToLink;
   1737     }
   1738 
   1739     void link(LinkRecord& record, uint8_t* from, uint8_t* to)
   1740     {
   1741         switch (record.linkType()) {
   1742         case LinkJumpT1:
   1743             linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to);
   1744             break;
   1745         case LinkJumpT2:
   1746             linkJumpT2(reinterpret_cast<uint16_t*>(from), to);
   1747             break;
   1748         case LinkJumpT3:
   1749             linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to);
   1750             break;
   1751         case LinkJumpT4:
   1752             linkJumpT4(reinterpret_cast<uint16_t*>(from), to);
   1753             break;
   1754         case LinkConditionalJumpT4:
   1755             linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to);
   1756             break;
   1757         case LinkConditionalBX:
   1758             linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to);
   1759             break;
   1760         case LinkBX:
   1761             linkBX(reinterpret_cast<uint16_t*>(from), to);
   1762             break;
   1763         default:
   1764             ASSERT_NOT_REACHED();
   1765             break;
   1766         }
   1767     }
   1768 
   1769     void* unlinkedCode() { return m_formatter.data(); }
   1770 
   1771     static unsigned getCallReturnOffset(JmpSrc call)
   1772     {
   1773         ASSERT(call.m_offset >= 0);
   1774         return call.m_offset;
   1775     }
   1776 
   1777     // Linking & patching:
   1778     //
   1779     // 'link' and 'patch' methods are for use on unprotected code - such as the code
   1780     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
   1781     // code has been finalized it is (platform support permitting) within a non-
   1782     // writable region of memory; to modify the code in an execute-only execuable
   1783     // pool the 'repatch' and 'relink' methods should be used.
   1784 
   1785     void linkJump(JmpSrc from, JmpDst to)
   1786     {
   1787         ASSERT(to.m_offset != -1);
   1788         ASSERT(from.m_offset != -1);
   1789         m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, from.m_type, from.m_condition));
   1790     }
   1791 
   1792     static void linkJump(void* code, JmpSrc from, void* to)
   1793     {
   1794         ASSERT(from.m_offset != -1);
   1795 
   1796         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
   1797         linkJumpAbsolute(location, to);
   1798     }
   1799 
   1800     // bah, this mathod should really be static, since it is used by the LinkBuffer.
   1801     // return a bool saying whether the link was successful?
   1802     static void linkCall(void* code, JmpSrc from, void* to)
   1803     {
   1804         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
   1805         ASSERT(from.m_offset != -1);
   1806         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
   1807 
   1808         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
   1809     }
   1810 
   1811     static void linkPointer(void* code, JmpDst where, void* value)
   1812     {
   1813         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
   1814     }
   1815 
   1816     static void relinkJump(void* from, void* to)
   1817     {
   1818         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
   1819         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
   1820 
   1821         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
   1822 
   1823         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
   1824     }
   1825 
   1826     static void relinkCall(void* from, void* to)
   1827     {
   1828         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
   1829         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
   1830 
   1831         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
   1832     }
   1833 
   1834     static void repatchInt32(void* where, int32_t value)
   1835     {
   1836         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
   1837 
   1838         setInt32(where, value);
   1839     }
   1840 
   1841     static void repatchPointer(void* where, void* value)
   1842     {
   1843         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
   1844 
   1845         setPointer(where, value);
   1846     }
   1847 
   1848 private:
   1849     // VFP operations commonly take one or more 5-bit operands, typically representing a
   1850     // floating point register number.  This will commonly be encoded in the instruction
   1851     // in two parts, with one single bit field, and one 4-bit field.  In the case of
   1852     // double precision operands the high bit of the register number will be encoded
   1853     // separately, and for single precision operands the high bit of the register number
   1854     // will be encoded individually.
   1855     // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit
   1856     // field to be encoded together in the instruction (the low 4-bits of a double
   1857     // register number, or the high 4-bits of a single register number), and bit 4
   1858     // contains the bit value to be encoded individually.
   1859     struct VFPOperand {
   1860         explicit VFPOperand(uint32_t value)
   1861             : m_value(value)
   1862         {
   1863             ASSERT(!(m_value & ~0x1f));
   1864         }
   1865 
   1866         VFPOperand(FPDoubleRegisterID reg)
   1867             : m_value(reg)
   1868         {
   1869         }
   1870 
   1871         VFPOperand(RegisterID reg)
   1872             : m_value(reg)
   1873         {
   1874         }
   1875 
   1876         VFPOperand(FPSingleRegisterID reg)
   1877             : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top.
   1878         {
   1879         }
   1880 
   1881         uint32_t bits1()
   1882         {
   1883             return m_value >> 4;
   1884         }
   1885 
   1886         uint32_t bits4()
   1887         {
   1888             return m_value & 0xf;
   1889         }
   1890 
   1891         uint32_t m_value;
   1892     };
   1893 
   1894     VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero)
   1895     {
   1896         // Cannot specify rounding when converting to float.
   1897         ASSERT(toInteger || !isRoundZero);
   1898 
   1899         uint32_t op = 0x8;
   1900         if (toInteger) {
   1901             // opc2 indicates both toInteger & isUnsigned.
   1902             op |= isUnsigned ? 0x4 : 0x5;
   1903             // 'op' field in instruction is isRoundZero
   1904             if (isRoundZero)
   1905                 op |= 0x10;
   1906         } else {
   1907             // 'op' field in instruction is isUnsigned
   1908             if (!isUnsigned)
   1909                 op |= 0x10;
   1910         }
   1911         return VFPOperand(op);
   1912     }
   1913 
   1914     static void setInt32(void* code, uint32_t value)
   1915     {
   1916         uint16_t* location = reinterpret_cast<uint16_t*>(code);
   1917         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
   1918 
   1919         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
   1920         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
   1921         location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
   1922         location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
   1923         location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
   1924         location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
   1925 
   1926         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
   1927     }
   1928 
   1929     static void setPointer(void* code, void* value)
   1930     {
   1931         setInt32(code, reinterpret_cast<uint32_t>(value));
   1932     }
   1933 
   1934     static bool isB(void* address)
   1935     {
   1936         uint16_t* instruction = static_cast<uint16_t*>(address);
   1937         return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
   1938     }
   1939 
   1940     static bool isBX(void* address)
   1941     {
   1942         uint16_t* instruction = static_cast<uint16_t*>(address);
   1943         return (instruction[0] & 0xff87) == OP_BX;
   1944     }
   1945 
   1946     static bool isMOV_imm_T3(void* address)
   1947     {
   1948         uint16_t* instruction = static_cast<uint16_t*>(address);
   1949         return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
   1950     }
   1951 
   1952     static bool isMOVT(void* address)
   1953     {
   1954         uint16_t* instruction = static_cast<uint16_t*>(address);
   1955         return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
   1956     }
   1957 
   1958     static bool isNOP_T1(void* address)
   1959     {
   1960         uint16_t* instruction = static_cast<uint16_t*>(address);
   1961         return instruction[0] == OP_NOP_T1;
   1962     }
   1963 
   1964     static bool isNOP_T2(void* address)
   1965     {
   1966         uint16_t* instruction = static_cast<uint16_t*>(address);
   1967         return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
   1968     }
   1969 
   1970     static bool canBeJumpT1(const uint16_t* instruction, const void* target)
   1971     {
   1972         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   1973         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   1974 
   1975         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   1976         // It does not appear to be documented in the ARM ARM (big surprise), but
   1977         // for OP_B_T1 the branch displacement encoded in the instruction is 2
   1978         // less than the actual displacement.
   1979         relative -= 2;
   1980         return ((relative << 23) >> 23) == relative;
   1981     }
   1982 
   1983     static bool canBeJumpT2(const uint16_t* instruction, const void* target)
   1984     {
   1985         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   1986         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   1987 
   1988         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   1989         // It does not appear to be documented in the ARM ARM (big surprise), but
   1990         // for OP_B_T2 the branch displacement encoded in the instruction is 2
   1991         // less than the actual displacement.
   1992         relative -= 2;
   1993         return ((relative << 20) >> 20) == relative;
   1994     }
   1995 
   1996     static bool canBeJumpT3(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
   1997     {
   1998         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   1999         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2000 
   2001         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   2002         // From Cortex-A8 errata:
   2003         // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
   2004         // the target of the branch falls within the first region it is
   2005         // possible for the processor to incorrectly determine the branch
   2006         // instruction, and it is also possible in some cases for the processor
   2007         // to enter a deadlock state.
   2008         // The instruction is spanning two pages if it ends at an address ending 0x002
   2009         bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
   2010         mayTriggerErrata = spansTwo4K;
   2011         // The target is in the first page if the jump branch back by [3..0x1002] bytes
   2012         bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
   2013         bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
   2014         return ((relative << 11) >> 11) == relative && !wouldTriggerA8Errata;
   2015     }
   2016 
   2017     static bool canBeJumpT4(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
   2018     {
   2019         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2020         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2021 
   2022         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   2023         // From Cortex-A8 errata:
   2024         // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
   2025         // the target of the branch falls within the first region it is
   2026         // possible for the processor to incorrectly determine the branch
   2027         // instruction, and it is also possible in some cases for the processor
   2028         // to enter a deadlock state.
   2029         // The instruction is spanning two pages if it ends at an address ending 0x002
   2030         bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
   2031         mayTriggerErrata = spansTwo4K;
   2032         // The target is in the first page if the jump branch back by [3..0x1002] bytes
   2033         bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
   2034         bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
   2035         return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata;
   2036     }
   2037 
   2038     void linkJumpT1(Condition cond, uint16_t* instruction, void* target)
   2039     {
   2040         // FIMXE: this should be up in the MacroAssembler layer. :-(
   2041         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2042         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2043         ASSERT(canBeJumpT1(instruction, target));
   2044 
   2045         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   2046         // It does not appear to be documented in the ARM ARM (big surprise), but
   2047         // for OP_B_T1 the branch displacement encoded in the instruction is 2
   2048         // less than the actual displacement.
   2049         relative -= 2;
   2050 
   2051         // All branch offsets should be an even distance.
   2052         ASSERT(!(relative & 1));
   2053         instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1);
   2054     }
   2055 
   2056     static void linkJumpT2(uint16_t* instruction, void* target)
   2057     {
   2058         // FIMXE: this should be up in the MacroAssembler layer. :-(
   2059         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2060         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2061         ASSERT(canBeJumpT2(instruction, target));
   2062 
   2063         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   2064         // It does not appear to be documented in the ARM ARM (big surprise), but
   2065         // for OP_B_T2 the branch displacement encoded in the instruction is 2
   2066         // less than the actual displacement.
   2067         relative -= 2;
   2068 
   2069         // All branch offsets should be an even distance.
   2070         ASSERT(!(relative & 1));
   2071         instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1);
   2072     }
   2073 
   2074     void linkJumpT3(Condition cond, uint16_t* instruction, void* target)
   2075     {
   2076         // FIMXE: this should be up in the MacroAssembler layer. :-(
   2077         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2078         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2079         bool scratch;
   2080         UNUSED_PARAM(scratch);
   2081         ASSERT(canBeJumpT3(instruction, target, scratch));
   2082 
   2083         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   2084 
   2085         // All branch offsets should be an even distance.
   2086         ASSERT(!(relative & 1));
   2087         instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12);
   2088         instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1);
   2089     }
   2090 
   2091     static void linkJumpT4(uint16_t* instruction, void* target)
   2092     {
   2093         // FIMXE: this should be up in the MacroAssembler layer. :-(
   2094         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2095         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2096         bool scratch;
   2097         UNUSED_PARAM(scratch);
   2098         ASSERT(canBeJumpT4(instruction, target, scratch));
   2099 
   2100         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   2101         // ARM encoding for the top two bits below the sign bit is 'peculiar'.
   2102         if (relative >= 0)
   2103             relative ^= 0xC00000;
   2104 
   2105         // All branch offsets should be an even distance.
   2106         ASSERT(!(relative & 1));
   2107         instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
   2108         instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
   2109     }
   2110 
   2111     void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target)
   2112     {
   2113         // FIMXE: this should be up in the MacroAssembler layer. :-(
   2114         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2115         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2116 
   2117         instruction[-3] = ifThenElse(cond) | OP_IT;
   2118         linkJumpT4(instruction, target);
   2119     }
   2120 
   2121     static void linkBX(uint16_t* instruction, void* target)
   2122     {
   2123         // FIMXE: this should be up in the MacroAssembler layer. :-(
   2124         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2125         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2126 
   2127         const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
   2128         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
   2129         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
   2130         instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
   2131         instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
   2132         instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
   2133         instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
   2134         instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
   2135     }
   2136 
   2137     void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
   2138     {
   2139         // FIMXE: this should be up in the MacroAssembler layer. :-(
   2140         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2141         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2142 
   2143         linkBX(instruction, target);
   2144         instruction[-6] = ifThenElse(cond, true, true) | OP_IT;
   2145     }
   2146 
   2147     static void linkJumpAbsolute(uint16_t* instruction, void* target)
   2148     {
   2149         // FIMXE: this should be up in the MacroAssembler layer. :-(
   2150         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   2151         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   2152 
   2153         ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
   2154                || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
   2155 
   2156         bool scratch;
   2157         if (canBeJumpT4(instruction, target, scratch)) {
   2158             // There may be a better way to fix this, but right now put the NOPs first, since in the
   2159             // case of an conditional branch this will be coming after an ITTT predicating *three*
   2160             // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
   2161             // variable wdith encoding - the previous instruction might *look* like an ITTT but
   2162             // actually be the second half of a 2-word op.
   2163             instruction[-5] = OP_NOP_T1;
   2164             instruction[-4] = OP_NOP_T2a;
   2165             instruction[-3] = OP_NOP_T2b;
   2166             linkJumpT4(instruction, target);
   2167         } else {
   2168             const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
   2169             ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
   2170             ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
   2171             instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
   2172             instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
   2173             instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
   2174             instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
   2175             instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
   2176         }
   2177     }
   2178 
   2179     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
   2180     {
   2181         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
   2182     }
   2183 
   2184     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
   2185     {
   2186         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
   2187     }
   2188 
   2189     class ARMInstructionFormatter {
   2190     public:
   2191         void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
   2192         {
   2193             m_buffer.putShort(op | (rd << 8) | imm);
   2194         }
   2195 
   2196         void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
   2197         {
   2198             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
   2199         }
   2200 
   2201         void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
   2202         {
   2203             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
   2204         }
   2205 
   2206         void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
   2207         {
   2208             m_buffer.putShort(op | imm);
   2209         }
   2210 
   2211         void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
   2212         {
   2213             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
   2214         }
   2215         void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
   2216         {
   2217             m_buffer.putShort(op | imm);
   2218         }
   2219 
   2220         void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
   2221         {
   2222             m_buffer.putShort(op | (reg1 << 3) | reg2);
   2223         }
   2224 
   2225         void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
   2226         {
   2227             m_buffer.putShort(op | reg);
   2228             m_buffer.putShort(ff.m_u.value);
   2229         }
   2230 
   2231         void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
   2232         {
   2233             m_buffer.putShort(op);
   2234             m_buffer.putShort(ff.m_u.value);
   2235         }
   2236 
   2237         void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
   2238         {
   2239             m_buffer.putShort(op1);
   2240             m_buffer.putShort(op2);
   2241         }
   2242 
   2243         void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
   2244         {
   2245             ARMThumbImmediate newImm = imm;
   2246             newImm.m_value.imm4 = imm4;
   2247 
   2248             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
   2249             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
   2250         }
   2251 
   2252         void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
   2253         {
   2254             m_buffer.putShort(op | reg1);
   2255             m_buffer.putShort((reg2 << 12) | imm);
   2256         }
   2257 
   2258         // Formats up instructions of the pattern:
   2259         //    111111111B11aaaa:bbbb222SA2C2cccc
   2260         // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
   2261         // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
   2262         void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
   2263         {
   2264             ASSERT(!(op1 & 0x004f));
   2265             ASSERT(!(op2 & 0xf1af));
   2266             m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4());
   2267             m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4());
   2268         }
   2269 
   2270         // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
   2271         // (i.e. +/-(0..255) 32-bit words)
   2272         void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
   2273         {
   2274             bool up = true;
   2275             if (imm < 0) {
   2276                 imm = -imm;
   2277                 up = false;
   2278             }
   2279 
   2280             uint32_t offset = imm;
   2281             ASSERT(!(offset & ~0x3fc));
   2282             offset >>= 2;
   2283 
   2284             m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn);
   2285             m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset);
   2286         }
   2287 
   2288         // Administrative methods:
   2289 
   2290         size_t size() const { return m_buffer.size(); }
   2291         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
   2292         void* data() const { return m_buffer.data(); }
   2293         void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
   2294 
   2295 #ifndef NDEBUG
   2296         unsigned debugOffset() { return m_formatter.debugOffset(); }
   2297 #endif
   2298 
   2299     private:
   2300         AssemblerBuffer m_buffer;
   2301     } m_formatter;
   2302 
   2303     Vector<LinkRecord> m_jumpsToLink;
   2304     Vector<int32_t> m_offsets;
   2305 };
   2306 
   2307 } // namespace JSC
   2308 
   2309 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
   2310 
   2311 #endif // ARMAssembler_h
   2312