Home | History | Annotate | Download | only in assembler
      1 /*
      2  * Copyright (C) 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef ARMAssembler_h
     27 #define ARMAssembler_h
     28 
     29 #include <wtf/Platform.h>
     30 
     31 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
     32 
     33 #include "AssemblerBuffer.h"
     34 #include <wtf/Assertions.h>
     35 #include <wtf/Vector.h>
     36 #include <stdint.h>
     37 
     38 namespace JSC {
     39 
     40 namespace ARMRegisters {
     41     typedef enum {
     42         r0,
     43         r1,
     44         r2,
     45         r3,
     46         r4,
     47         r5,
     48         r6,
     49         r7, wr = r7,   // thumb work register
     50         r8,
     51         r9, sb = r9,   // static base
     52         r10, sl = r10, // stack limit
     53         r11, fp = r11, // frame pointer
     54         r12, ip = r12,
     55         r13, sp = r13,
     56         r14, lr = r14,
     57         r15, pc = r15,
     58     } RegisterID;
     59 
     60     // s0 == d0 == q0
     61     // s4 == d2 == q1
     62     // etc
     63     typedef enum {
     64         s0 = 0,
     65         s1 = 1,
     66         s2 = 2,
     67         s3 = 3,
     68         s4 = 4,
     69         s5 = 5,
     70         s6 = 6,
     71         s7 = 7,
     72         s8 = 8,
     73         s9 = 9,
     74         s10 = 10,
     75         s11 = 11,
     76         s12 = 12,
     77         s13 = 13,
     78         s14 = 14,
     79         s15 = 15,
     80         s16 = 16,
     81         s17 = 17,
     82         s18 = 18,
     83         s19 = 19,
     84         s20 = 20,
     85         s21 = 21,
     86         s22 = 22,
     87         s23 = 23,
     88         s24 = 24,
     89         s25 = 25,
     90         s26 = 26,
     91         s27 = 27,
     92         s28 = 28,
     93         s29 = 29,
     94         s30 = 30,
     95         s31 = 31,
     96         d0 = 0 << 1,
     97         d1 = 1 << 1,
     98         d2 = 2 << 1,
     99         d3 = 3 << 1,
    100         d4 = 4 << 1,
    101         d5 = 5 << 1,
    102         d6 = 6 << 1,
    103         d7 = 7 << 1,
    104         d8 = 8 << 1,
    105         d9 = 9 << 1,
    106         d10 = 10 << 1,
    107         d11 = 11 << 1,
    108         d12 = 12 << 1,
    109         d13 = 13 << 1,
    110         d14 = 14 << 1,
    111         d15 = 15 << 1,
    112         d16 = 16 << 1,
    113         d17 = 17 << 1,
    114         d18 = 18 << 1,
    115         d19 = 19 << 1,
    116         d20 = 20 << 1,
    117         d21 = 21 << 1,
    118         d22 = 22 << 1,
    119         d23 = 23 << 1,
    120         d24 = 24 << 1,
    121         d25 = 25 << 1,
    122         d26 = 26 << 1,
    123         d27 = 27 << 1,
    124         d28 = 28 << 1,
    125         d29 = 29 << 1,
    126         d30 = 30 << 1,
    127         d31 = 31 << 1,
    128         q0 = 0 << 2,
    129         q1 = 1 << 2,
    130         q2 = 2 << 2,
    131         q3 = 3 << 2,
    132         q4 = 4 << 2,
    133         q5 = 5 << 2,
    134         q6 = 6 << 2,
    135         q7 = 7 << 2,
    136         q8 = 8 << 2,
    137         q9 = 9 << 2,
    138         q10 = 10 << 2,
    139         q11 = 11 << 2,
    140         q12 = 12 << 2,
    141         q13 = 13 << 2,
    142         q14 = 14 << 2,
    143         q15 = 15 << 2,
    144         q16 = 16 << 2,
    145         q17 = 17 << 2,
    146         q18 = 18 << 2,
    147         q19 = 19 << 2,
    148         q20 = 20 << 2,
    149         q21 = 21 << 2,
    150         q22 = 22 << 2,
    151         q23 = 23 << 2,
    152         q24 = 24 << 2,
    153         q25 = 25 << 2,
    154         q26 = 26 << 2,
    155         q27 = 27 << 2,
    156         q28 = 28 << 2,
    157         q29 = 29 << 2,
    158         q30 = 30 << 2,
    159         q31 = 31 << 2,
    160     } FPRegisterID;
    161 }
    162 
    163 class ARMv7Assembler;
    164 class ARMThumbImmediate {
    165     friend class ARMv7Assembler;
    166 
    167     typedef uint8_t ThumbImmediateType;
    168     static const ThumbImmediateType TypeInvalid = 0;
    169     static const ThumbImmediateType TypeEncoded = 1;
    170     static const ThumbImmediateType TypeUInt16 = 2;
    171 
    172     typedef union {
    173         int16_t asInt;
    174         struct {
    175             unsigned imm8 : 8;
    176             unsigned imm3 : 3;
    177             unsigned i    : 1;
    178             unsigned imm4 : 4;
    179         };
    180         // If this is an encoded immediate, then it may describe a shift, or a pattern.
    181         struct {
    182             unsigned shiftValue7 : 7;
    183             unsigned shiftAmount : 5;
    184         };
    185         struct {
    186             unsigned immediate   : 8;
    187             unsigned pattern     : 4;
    188         };
    189     } ThumbImmediateValue;
    190 
    191     // byte0 contains least significant bit; not using an array to make client code endian agnostic.
    192     typedef union {
    193         int32_t asInt;
    194         struct {
    195             uint8_t byte0;
    196             uint8_t byte1;
    197             uint8_t byte2;
    198             uint8_t byte3;
    199         };
    200     } PatternBytes;
    201 
    202     ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
    203     {
    204         if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
    205             value >>= N;             /* if any were set, lose the bottom N */
    206         else                         /* if none of the top N bits are set, */
    207             zeros += N;              /* then we have identified N leading zeros */
    208     }
    209 
    210     static int32_t countLeadingZeros(uint32_t value)
    211     {
    212         if (!value)
    213             return 32;
    214 
    215         int32_t zeros = 0;
    216         countLeadingZerosPartial(value, zeros, 16);
    217         countLeadingZerosPartial(value, zeros, 8);
    218         countLeadingZerosPartial(value, zeros, 4);
    219         countLeadingZerosPartial(value, zeros, 2);
    220         countLeadingZerosPartial(value, zeros, 1);
    221         return zeros;
    222     }
    223 
    224     ARMThumbImmediate()
    225         : m_type(TypeInvalid)
    226     {
    227         m_value.asInt = 0;
    228     }
    229 
    230     ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
    231         : m_type(type)
    232         , m_value(value)
    233     {
    234     }
    235 
    236     ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
    237         : m_type(TypeUInt16)
    238     {
    239         // Make sure this constructor is only reached with type TypeUInt16;
    240         // this extra parameter makes the code a little clearer by making it
    241         // explicit at call sites which type is being constructed
    242         ASSERT_UNUSED(type, type == TypeUInt16);
    243 
    244         m_value.asInt = value;
    245     }
    246 
    247 public:
    248     static ARMThumbImmediate makeEncodedImm(uint32_t value)
    249     {
    250         ThumbImmediateValue encoding;
    251         encoding.asInt = 0;
    252 
    253         // okay, these are easy.
    254         if (value < 256) {
    255             encoding.immediate = value;
    256             encoding.pattern = 0;
    257             return ARMThumbImmediate(TypeEncoded, encoding);
    258         }
    259 
    260         int32_t leadingZeros = countLeadingZeros(value);
    261         // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
    262         ASSERT(leadingZeros < 24);
    263 
    264         // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
    265         // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
    266         // zero.  count(B) == 8, so the count of bits to be checked is 24 - count(Z).
    267         int32_t rightShiftAmount = 24 - leadingZeros;
    268         if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
    269             // Shift the value down to the low byte position.  The assign to
    270             // shiftValue7 drops the implicit top bit.
    271             encoding.shiftValue7 = value >> rightShiftAmount;
    272             // The endoded shift amount is the magnitude of a right rotate.
    273             encoding.shiftAmount = 8 + leadingZeros;
    274             return ARMThumbImmediate(TypeEncoded, encoding);
    275         }
    276 
    277         PatternBytes bytes;
    278         bytes.asInt = value;
    279 
    280         if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
    281             encoding.immediate = bytes.byte0;
    282             encoding.pattern = 3;
    283             return ARMThumbImmediate(TypeEncoded, encoding);
    284         }
    285 
    286         if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
    287             encoding.immediate = bytes.byte0;
    288             encoding.pattern = 1;
    289             return ARMThumbImmediate(TypeEncoded, encoding);
    290         }
    291 
    292         if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
    293             encoding.immediate = bytes.byte0;
    294             encoding.pattern = 2;
    295             return ARMThumbImmediate(TypeEncoded, encoding);
    296         }
    297 
    298         return ARMThumbImmediate();
    299     }
    300 
    301     static ARMThumbImmediate makeUInt12(int32_t value)
    302     {
    303         return (!(value & 0xfffff000))
    304             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
    305             : ARMThumbImmediate();
    306     }
    307 
    308     static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
    309     {
    310         // If this is not a 12-bit unsigned it, try making an encoded immediate.
    311         return (!(value & 0xfffff000))
    312             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
    313             : makeEncodedImm(value);
    314     }
    315 
    316     // The 'make' methods, above, return a !isValid() value if the argument
    317     // cannot be represented as the requested type.  This methods  is called
    318     // 'get' since the argument can always be represented.
    319     static ARMThumbImmediate makeUInt16(uint16_t value)
    320     {
    321         return ARMThumbImmediate(TypeUInt16, value);
    322     }
    323 
    324     bool isValid()
    325     {
    326         return m_type != TypeInvalid;
    327     }
    328 
    329     // These methods rely on the format of encoded byte values.
    330     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
    331     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
    332     bool isUInt5() { return !(m_value.asInt & 0xffe0); }
    333     bool isUInt6() { return !(m_value.asInt & 0xffc0); }
    334     bool isUInt7() { return !(m_value.asInt & 0xff80); }
    335     bool isUInt8() { return !(m_value.asInt & 0xff00); }
    336     bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
    337     bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
    338     bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
    339     bool isUInt16() { return m_type == TypeUInt16; }
    340     uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
    341     uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
    342     uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
    343     uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
    344     uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
    345     uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
    346     uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
    347     uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
    348     uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
    349     uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
    350 
    351     bool isEncodedImm() { return m_type == TypeEncoded; }
    352 
    353 private:
    354     ThumbImmediateType m_type;
    355     ThumbImmediateValue m_value;
    356 };
    357 
    358 
    359 typedef enum {
    360     SRType_LSL,
    361     SRType_LSR,
    362     SRType_ASR,
    363     SRType_ROR,
    364 
    365     SRType_RRX = SRType_ROR
    366 } ARMShiftType;
    367 
    368 class ARMv7Assembler;
    369 class ShiftTypeAndAmount {
    370     friend class ARMv7Assembler;
    371 
    372 public:
    373     ShiftTypeAndAmount()
    374     {
    375         m_u.type = (ARMShiftType)0;
    376         m_u.amount = 0;
    377     }
    378 
    379     ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
    380     {
    381         m_u.type = type;
    382         m_u.amount = amount & 31;
    383     }
    384 
    385     unsigned lo4() { return m_u.lo4; }
    386     unsigned hi4() { return m_u.hi4; }
    387 
    388 private:
    389     union {
    390         struct {
    391             unsigned lo4 : 4;
    392             unsigned hi4 : 4;
    393         };
    394         struct {
    395             unsigned type   : 2;
    396             unsigned amount : 5;
    397         };
    398     } m_u;
    399 };
    400 
    401 
    402 /*
    403 Some features of the Thumb instruction set are deprecated in ARMv7. Deprecated features affecting
    404 instructions supported by ARMv7-M are as follows:
    405  use of the PC as <Rd> or <Rm> in a 16-bit ADD (SP plus register) instruction
    406  use of the SP as <Rm> in a 16-bit ADD (SP plus register) instruction
    407  use of the SP as <Rm> in a 16-bit CMP (register) instruction
    408  use of MOV (register) instructions in which <Rd> is the SP or PC and <Rm> is also the SP or PC.
    409  use of <Rn> as the lowest-numbered register in the register list of a 16-bit STM instruction with base
    410 register writeback
    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::FPRegisterID FPRegisterID;
    422 
    423     // (HS, LO, HI, LS) -> (AE, B, A, BE)
    424     // (VS, VC) -> (O, NO)
    425     typedef enum {
    426         ConditionEQ,
    427         ConditionNE,
    428         ConditionHS,
    429         ConditionLO,
    430         ConditionMI,
    431         ConditionPL,
    432         ConditionVS,
    433         ConditionVC,
    434         ConditionHI,
    435         ConditionLS,
    436         ConditionGE,
    437         ConditionLT,
    438         ConditionGT,
    439         ConditionLE,
    440         ConditionAL,
    441 
    442         ConditionCS = ConditionHS,
    443         ConditionCC = ConditionLO,
    444     } Condition;
    445 
    446     class JmpSrc {
    447         friend class ARMv7Assembler;
    448         friend class ARMInstructionFormatter;
    449     public:
    450         JmpSrc()
    451             : m_offset(-1)
    452         {
    453         }
    454 
    455     private:
    456         JmpSrc(int offset)
    457             : m_offset(offset)
    458         {
    459         }
    460 
    461         int m_offset;
    462     };
    463 
    464     class JmpDst {
    465         friend class ARMv7Assembler;
    466         friend class ARMInstructionFormatter;
    467     public:
    468         JmpDst()
    469             : m_offset(-1)
    470             , m_used(false)
    471         {
    472         }
    473 
    474         bool isUsed() const { return m_used; }
    475         void used() { m_used = true; }
    476     private:
    477         JmpDst(int offset)
    478             : m_offset(offset)
    479             , m_used(false)
    480         {
    481             ASSERT(m_offset == offset);
    482         }
    483 
    484         int m_offset : 31;
    485         int m_used : 1;
    486     };
    487 
    488 private:
    489 
    490     struct LinkRecord {
    491         LinkRecord(intptr_t from, intptr_t to)
    492             : from(from)
    493             , to(to)
    494         {
    495         }
    496 
    497         intptr_t from;
    498         intptr_t to;
    499     };
    500 
    501     // ARMv7, Appx-A.6.3
    502     bool BadReg(RegisterID reg)
    503     {
    504         return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
    505     }
    506 
    507     bool isSingleRegister(FPRegisterID reg)
    508     {
    509         // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
    510         return !(reg & ~31);
    511     }
    512 
    513     bool isDoubleRegister(FPRegisterID reg)
    514     {
    515         // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
    516         return !(reg & ~(31 << 1));
    517     }
    518 
    519     bool isQuadRegister(FPRegisterID reg)
    520     {
    521         return !(reg & ~(31 << 2));
    522     }
    523 
    524     uint32_t singleRegisterNum(FPRegisterID reg)
    525     {
    526         ASSERT(isSingleRegister(reg));
    527         return reg;
    528     }
    529 
    530     uint32_t doubleRegisterNum(FPRegisterID reg)
    531     {
    532         ASSERT(isDoubleRegister(reg));
    533         return reg >> 1;
    534     }
    535 
    536     uint32_t quadRegisterNum(FPRegisterID reg)
    537     {
    538         ASSERT(isQuadRegister(reg));
    539         return reg >> 2;
    540     }
    541 
    542     uint32_t singleRegisterMask(FPRegisterID rd, int highBitsShift, int lowBitShift)
    543     {
    544         uint32_t rdNum = singleRegisterNum(rd);
    545         uint32_t rdMask = (rdNum >> 1) << highBitsShift;
    546         if (rdNum & 1)
    547             rdMask |= 1 << lowBitShift;
    548         return rdMask;
    549     }
    550 
    551     uint32_t doubleRegisterMask(FPRegisterID rd, int highBitShift, int lowBitsShift)
    552     {
    553         uint32_t rdNum = doubleRegisterNum(rd);
    554         uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
    555         if (rdNum & 16)
    556             rdMask |= 1 << highBitShift;
    557         return rdMask;
    558     }
    559 
    560     typedef enum {
    561         OP_ADD_reg_T1       = 0x1800,
    562         OP_ADD_S_reg_T1     = 0x1800,
    563         OP_SUB_reg_T1       = 0x1A00,
    564         OP_SUB_S_reg_T1     = 0x1A00,
    565         OP_ADD_imm_T1       = 0x1C00,
    566         OP_ADD_S_imm_T1     = 0x1C00,
    567         OP_SUB_imm_T1       = 0x1E00,
    568         OP_SUB_S_imm_T1     = 0x1E00,
    569         OP_MOV_imm_T1       = 0x2000,
    570         OP_CMP_imm_T1       = 0x2800,
    571         OP_ADD_imm_T2       = 0x3000,
    572         OP_ADD_S_imm_T2     = 0x3000,
    573         OP_SUB_imm_T2       = 0x3800,
    574         OP_SUB_S_imm_T2     = 0x3800,
    575         OP_AND_reg_T1       = 0x4000,
    576         OP_EOR_reg_T1       = 0x4040,
    577         OP_TST_reg_T1       = 0x4200,
    578         OP_CMP_reg_T1       = 0x4280,
    579         OP_ORR_reg_T1       = 0x4300,
    580         OP_MVN_reg_T1       = 0x43C0,
    581         OP_ADD_reg_T2       = 0x4400,
    582         OP_MOV_reg_T1       = 0x4600,
    583         OP_BLX              = 0x4700,
    584         OP_BX               = 0x4700,
    585         OP_LDRH_reg_T1      = 0x5A00,
    586         OP_STR_reg_T1       = 0x5000,
    587         OP_LDR_reg_T1       = 0x5800,
    588         OP_STR_imm_T1       = 0x6000,
    589         OP_LDR_imm_T1       = 0x6800,
    590         OP_LDRH_imm_T1      = 0x8800,
    591         OP_STR_imm_T2       = 0x9000,
    592         OP_LDR_imm_T2       = 0x9800,
    593         OP_ADD_SP_imm_T1    = 0xA800,
    594         OP_ADD_SP_imm_T2    = 0xB000,
    595         OP_SUB_SP_imm_T1    = 0xB080,
    596         OP_BKPT             = 0xBE00,
    597         OP_IT               = 0xBF00,
    598         OP_NOP_T1           = 0xBF00,
    599     } OpcodeID;
    600 
    601     typedef enum {
    602         OP_AND_reg_T2   = 0xEA00,
    603         OP_TST_reg_T2   = 0xEA10,
    604         OP_ORR_reg_T2   = 0xEA40,
    605         OP_ASR_imm_T1   = 0xEA4F,
    606         OP_LSL_imm_T1   = 0xEA4F,
    607         OP_LSR_imm_T1   = 0xEA4F,
    608         OP_ROR_imm_T1   = 0xEA4F,
    609         OP_MVN_reg_T2   = 0xEA6F,
    610         OP_EOR_reg_T2   = 0xEA80,
    611         OP_ADD_reg_T3   = 0xEB00,
    612         OP_ADD_S_reg_T3 = 0xEB10,
    613         OP_SUB_reg_T2   = 0xEBA0,
    614         OP_SUB_S_reg_T2 = 0xEBB0,
    615         OP_CMP_reg_T2   = 0xEBB0,
    616         OP_B_T4a        = 0xF000,
    617         OP_AND_imm_T1   = 0xF000,
    618         OP_TST_imm      = 0xF010,
    619         OP_ORR_imm_T1   = 0xF040,
    620         OP_MOV_imm_T2   = 0xF040,
    621         OP_MVN_imm      = 0xF060,
    622         OP_EOR_imm_T1   = 0xF080,
    623         OP_ADD_imm_T3   = 0xF100,
    624         OP_ADD_S_imm_T3 = 0xF110,
    625         OP_CMN_imm      = 0xF110,
    626         OP_SUB_imm_T3   = 0xF1A0,
    627         OP_SUB_S_imm_T3 = 0xF1B0,
    628         OP_CMP_imm_T2   = 0xF1B0,
    629         OP_ADD_imm_T4   = 0xF200,
    630         OP_MOV_imm_T3   = 0xF240,
    631         OP_SUB_imm_T4   = 0xF2A0,
    632         OP_MOVT         = 0xF2C0,
    633         OP_NOP_T2a      = 0xF3AF,
    634         OP_LDRH_reg_T2  = 0xF830,
    635         OP_LDRH_imm_T3  = 0xF830,
    636         OP_STR_imm_T4   = 0xF840,
    637         OP_STR_reg_T2   = 0xF840,
    638         OP_LDR_imm_T4   = 0xF850,
    639         OP_LDR_reg_T2   = 0xF850,
    640         OP_LDRH_imm_T2  = 0xF8B0,
    641         OP_STR_imm_T3   = 0xF8C0,
    642         OP_LDR_imm_T3   = 0xF8D0,
    643         OP_LSL_reg_T2   = 0xFA00,
    644         OP_LSR_reg_T2   = 0xFA20,
    645         OP_ASR_reg_T2   = 0xFA40,
    646         OP_ROR_reg_T2   = 0xFA60,
    647         OP_SMULL_T1     = 0xFB80,
    648     } OpcodeID1;
    649 
    650     typedef enum {
    651         OP_B_T4b        = 0x9000,
    652         OP_NOP_T2b      = 0x8000,
    653     } OpcodeID2;
    654 
    655     struct FourFours {
    656         FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
    657         {
    658             m_u.f0 = f0;
    659             m_u.f1 = f1;
    660             m_u.f2 = f2;
    661             m_u.f3 = f3;
    662         }
    663 
    664         union {
    665             unsigned value;
    666             struct {
    667                 unsigned f0 : 4;
    668                 unsigned f1 : 4;
    669                 unsigned f2 : 4;
    670                 unsigned f3 : 4;
    671             };
    672         } m_u;
    673     };
    674 
    675     class ARMInstructionFormatter;
    676 
    677     // false means else!
    678     bool ifThenElseConditionBit(Condition condition, bool isIf)
    679     {
    680         return isIf ? (condition & 1) : !(condition & 1);
    681     }
    682     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
    683     {
    684         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
    685             | (ifThenElseConditionBit(condition, inst3if) << 2)
    686             | (ifThenElseConditionBit(condition, inst4if) << 1)
    687             | 1;
    688         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
    689         return (condition << 4) | mask;
    690     }
    691     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
    692     {
    693         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
    694             | (ifThenElseConditionBit(condition, inst3if) << 2)
    695             | 2;
    696         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
    697         return (condition << 4) | mask;
    698     }
    699     uint8_t ifThenElse(Condition condition, bool inst2if)
    700     {
    701         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
    702             | 4;
    703         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
    704         return (condition << 4) | mask;
    705     }
    706 
    707     uint8_t ifThenElse(Condition condition)
    708     {
    709         int mask = 8;
    710         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
    711         return (condition << 4) | mask;
    712     }
    713 
    714 public:
    715 
    716     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    717     {
    718         // Rd can only be SP if Rn is also SP.
    719         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
    720         ASSERT(rd != ARMRegisters::pc);
    721         ASSERT(rn != ARMRegisters::pc);
    722         ASSERT(imm.isValid());
    723 
    724         if (rn == ARMRegisters::sp) {
    725             if (!(rd & 8) && imm.isUInt10()) {
    726                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
    727                 return;
    728             } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
    729                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
    730                 return;
    731             }
    732         } else if (!((rd | rn) & 8)) {
    733             if (imm.isUInt3()) {
    734                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
    735                 return;
    736             } else if ((rd == rn) && imm.isUInt8()) {
    737                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
    738                 return;
    739             }
    740         }
    741 
    742         if (imm.isEncodedImm())
    743             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
    744         else {
    745             ASSERT(imm.isUInt12());
    746             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
    747         }
    748     }
    749 
    750     void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    751     {
    752         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
    753         ASSERT(rd != ARMRegisters::pc);
    754         ASSERT(rn != ARMRegisters::pc);
    755         ASSERT(!BadReg(rm));
    756         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    757     }
    758 
    759     // NOTE: In an IT block, add doesn't modify the flags register.
    760     void add(RegisterID rd, RegisterID rn, RegisterID rm)
    761     {
    762         if (rd == rn)
    763             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
    764         else if (rd == rm)
    765             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
    766         else if (!((rd | rn | rm) & 8))
    767             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
    768         else
    769             add(rd, rn, rm, ShiftTypeAndAmount());
    770     }
    771 
    772     // Not allowed in an IT (if then) block.
    773     void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    774     {
    775         // Rd can only be SP if Rn is also SP.
    776         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
    777         ASSERT(rd != ARMRegisters::pc);
    778         ASSERT(rn != ARMRegisters::pc);
    779         ASSERT(imm.isEncodedImm());
    780 
    781         if (!((rd | rn) & 8)) {
    782             if (imm.isUInt3()) {
    783                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
    784                 return;
    785             } else if ((rd == rn) && imm.isUInt8()) {
    786                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_S_imm_T2, rd, imm.getUInt8());
    787                 return;
    788             }
    789         }
    790 
    791         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
    792     }
    793 
    794     // Not allowed in an IT (if then) block?
    795     void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    796     {
    797         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
    798         ASSERT(rd != ARMRegisters::pc);
    799         ASSERT(rn != ARMRegisters::pc);
    800         ASSERT(!BadReg(rm));
    801         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    802     }
    803 
    804     // Not allowed in an IT (if then) block.
    805     void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
    806     {
    807         if (!((rd | rn | rm) & 8))
    808             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_reg_T1, rm, rn, rd);
    809         else
    810             add_S(rd, rn, rm, ShiftTypeAndAmount());
    811     }
    812 
    813     void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    814     {
    815         ASSERT(!BadReg(rd));
    816         ASSERT(!BadReg(rn));
    817         ASSERT(imm.isEncodedImm());
    818         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
    819     }
    820 
    821     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    822     {
    823         ASSERT(!BadReg(rd));
    824         ASSERT(!BadReg(rn));
    825         ASSERT(!BadReg(rm));
    826         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    827     }
    828 
    829     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
    830     {
    831         if ((rd == rn) && !((rd | rm) & 8))
    832             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
    833         else if ((rd == rm) && !((rd | rn) & 8))
    834             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
    835         else
    836             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
    837     }
    838 
    839     void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
    840     {
    841         ASSERT(!BadReg(rd));
    842         ASSERT(!BadReg(rm));
    843         ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
    844         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    845     }
    846 
    847     void asr(RegisterID rd, RegisterID rn, RegisterID rm)
    848     {
    849         ASSERT(!BadReg(rd));
    850         ASSERT(!BadReg(rn));
    851         ASSERT(!BadReg(rm));
    852         m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
    853     }
    854 
    855     // Only allowed in IT (if then) block if last instruction.
    856     JmpSrc b()
    857     {
    858         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
    859         return JmpSrc(m_formatter.size());
    860     }
    861 
    862     // Only allowed in IT (if then) block if last instruction.
    863     JmpSrc blx(RegisterID rm)
    864     {
    865         ASSERT(rm != ARMRegisters::pc);
    866         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
    867         return JmpSrc(m_formatter.size());
    868     }
    869 
    870     // Only allowed in IT (if then) block if last instruction.
    871     JmpSrc bx(RegisterID rm)
    872     {
    873         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
    874         return JmpSrc(m_formatter.size());
    875     }
    876 
    877     void bkpt(uint8_t imm=0)
    878     {
    879         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
    880     }
    881 
    882     void cmn(RegisterID rn, ARMThumbImmediate imm)
    883     {
    884         ASSERT(rn != ARMRegisters::pc);
    885         ASSERT(imm.isEncodedImm());
    886 
    887         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
    888     }
    889 
    890     void cmp(RegisterID rn, ARMThumbImmediate imm)
    891     {
    892         ASSERT(rn != ARMRegisters::pc);
    893         ASSERT(imm.isEncodedImm());
    894 
    895         if (!(rn & 8) && imm.isUInt8())
    896             m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
    897         else
    898             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
    899     }
    900 
    901     void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    902     {
    903         ASSERT(rn != ARMRegisters::pc);
    904         ASSERT(!BadReg(rm));
    905         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
    906     }
    907 
    908     void cmp(RegisterID rn, RegisterID rm)
    909     {
    910         if ((rn | rm) & 8)
    911             cmp(rn, rm, ShiftTypeAndAmount());
    912         else
    913             m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
    914     }
    915 
    916     // xor is not spelled with an 'e'. :-(
    917     void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    918     {
    919         ASSERT(!BadReg(rd));
    920         ASSERT(!BadReg(rn));
    921         ASSERT(imm.isEncodedImm());
    922         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
    923     }
    924 
    925     // xor is not spelled with an 'e'. :-(
    926     void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
    927     {
    928         ASSERT(!BadReg(rd));
    929         ASSERT(!BadReg(rn));
    930         ASSERT(!BadReg(rm));
    931         m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
    932     }
    933 
    934     // xor is not spelled with an 'e'. :-(
    935     void eor(RegisterID rd, RegisterID rn, RegisterID rm)
    936     {
    937         if ((rd == rn) && !((rd | rm) & 8))
    938             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
    939         else if ((rd == rm) && !((rd | rn) & 8))
    940             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
    941         else
    942             eor(rd, rn, rm, ShiftTypeAndAmount());
    943     }
    944 
    945     void it(Condition cond)
    946     {
    947         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
    948     }
    949 
    950     void it(Condition cond, bool inst2if)
    951     {
    952         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
    953     }
    954 
    955     void it(Condition cond, bool inst2if, bool inst3if)
    956     {
    957         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
    958     }
    959 
    960     void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
    961     {
    962         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
    963     }
    964 
    965     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
    966     void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
    967     {
    968         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
    969         ASSERT(imm.isUInt12());
    970 
    971         if (!((rt | rn) & 8) && imm.isUInt7())
    972             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
    973         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
    974             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
    975         else
    976             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
    977     }
    978 
    979     // If index is set, this is a regular offset or a pre-indexed load;
    980     // if index is not set then is is a post-index load.
    981     //
    982     // If wback is set rn is updated - this is a pre or post index load,
    983     // if wback is not set this is a regular offset memory access.
    984     //
    985     // (-255 <= offset <= 255)
    986     // _reg = REG[rn]
    987     // _tmp = _reg + offset
    988     // MEM[index ? _tmp : _reg] = REG[rt]
    989     // if (wback) REG[rn] = _tmp
    990     void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
    991     {
    992         ASSERT(rt != ARMRegisters::pc);
    993         ASSERT(rn != ARMRegisters::pc);
    994         ASSERT(index || wback);
    995         ASSERT(!wback | (rt != rn));
    996 
    997         bool add = true;
    998         if (offset < 0) {
    999             add = false;
   1000             offset = -offset;
   1001         }
   1002         ASSERT((offset & ~0xff) == 0);
   1003 
   1004         offset |= (wback << 8);
   1005         offset |= (add   << 9);
   1006         offset |= (index << 10);
   1007         offset |= (1 << 11);
   1008 
   1009         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
   1010     }
   1011 
   1012     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1013     void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
   1014     {
   1015         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
   1016         ASSERT(!BadReg(rm));
   1017         ASSERT(shift <= 3);
   1018 
   1019         if (!shift && !((rt | rn | rm) & 8))
   1020             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
   1021         else
   1022             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
   1023     }
   1024 
   1025     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1026     void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
   1027     {
   1028         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
   1029         ASSERT(imm.isUInt12());
   1030 
   1031         if (!((rt | rn) & 8) && imm.isUInt6())
   1032             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
   1033         else
   1034             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
   1035     }
   1036 
   1037     // If index is set, this is a regular offset or a pre-indexed load;
   1038     // if index is not set then is is a post-index load.
   1039     //
   1040     // If wback is set rn is updated - this is a pre or post index load,
   1041     // if wback is not set this is a regular offset memory access.
   1042     //
   1043     // (-255 <= offset <= 255)
   1044     // _reg = REG[rn]
   1045     // _tmp = _reg + offset
   1046     // MEM[index ? _tmp : _reg] = REG[rt]
   1047     // if (wback) REG[rn] = _tmp
   1048     void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
   1049     {
   1050         ASSERT(rt != ARMRegisters::pc);
   1051         ASSERT(rn != ARMRegisters::pc);
   1052         ASSERT(index || wback);
   1053         ASSERT(!wback | (rt != rn));
   1054 
   1055         bool add = true;
   1056         if (offset < 0) {
   1057             add = false;
   1058             offset = -offset;
   1059         }
   1060         ASSERT((offset & ~0xff) == 0);
   1061 
   1062         offset |= (wback << 8);
   1063         offset |= (add   << 9);
   1064         offset |= (index << 10);
   1065         offset |= (1 << 11);
   1066 
   1067         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
   1068     }
   1069 
   1070     void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
   1071     {
   1072         ASSERT(!BadReg(rt));   // Memory hint
   1073         ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
   1074         ASSERT(!BadReg(rm));
   1075         ASSERT(shift <= 3);
   1076 
   1077         if (!shift && !((rt | rn | rm) & 8))
   1078             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
   1079         else
   1080             m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
   1081     }
   1082 
   1083     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
   1084     {
   1085         ASSERT(!BadReg(rd));
   1086         ASSERT(!BadReg(rm));
   1087         ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
   1088         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1089     }
   1090 
   1091     void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
   1092     {
   1093         ASSERT(!BadReg(rd));
   1094         ASSERT(!BadReg(rn));
   1095         ASSERT(!BadReg(rm));
   1096         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
   1097     }
   1098 
   1099     void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
   1100     {
   1101         ASSERT(!BadReg(rd));
   1102         ASSERT(!BadReg(rm));
   1103         ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
   1104         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1105     }
   1106 
   1107     void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
   1108     {
   1109         ASSERT(!BadReg(rd));
   1110         ASSERT(!BadReg(rn));
   1111         ASSERT(!BadReg(rm));
   1112         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
   1113     }
   1114 
   1115     void movT3(RegisterID rd, ARMThumbImmediate imm)
   1116     {
   1117         ASSERT(imm.isValid());
   1118         ASSERT(!imm.isEncodedImm());
   1119         ASSERT(!BadReg(rd));
   1120 
   1121         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
   1122     }
   1123 
   1124      void mov(RegisterID rd, ARMThumbImmediate imm)
   1125     {
   1126         ASSERT(imm.isValid());
   1127         ASSERT(!BadReg(rd));
   1128 
   1129         if ((rd < 8) && imm.isUInt8())
   1130             m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
   1131         else if (imm.isEncodedImm())
   1132             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
   1133         else
   1134             movT3(rd, imm);
   1135     }
   1136 
   1137    void mov(RegisterID rd, RegisterID rm)
   1138     {
   1139         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
   1140     }
   1141 
   1142     void movt(RegisterID rd, ARMThumbImmediate imm)
   1143     {
   1144         ASSERT(imm.isUInt16());
   1145         ASSERT(!BadReg(rd));
   1146         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
   1147     }
   1148 
   1149     void mvn(RegisterID rd, ARMThumbImmediate imm)
   1150     {
   1151         ASSERT(imm.isEncodedImm());
   1152         ASSERT(!BadReg(rd));
   1153 
   1154         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
   1155     }
   1156 
   1157     void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
   1158     {
   1159         ASSERT(!BadReg(rd));
   1160         ASSERT(!BadReg(rm));
   1161         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1162     }
   1163 
   1164     void mvn(RegisterID rd, RegisterID rm)
   1165     {
   1166         if (!((rd | rm) & 8))
   1167             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
   1168         else
   1169             mvn(rd, rm, ShiftTypeAndAmount());
   1170     }
   1171 
   1172     void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
   1173     {
   1174         ASSERT(!BadReg(rd));
   1175         ASSERT(!BadReg(rn));
   1176         ASSERT(imm.isEncodedImm());
   1177         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
   1178     }
   1179 
   1180     void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1181     {
   1182         ASSERT(!BadReg(rd));
   1183         ASSERT(!BadReg(rn));
   1184         ASSERT(!BadReg(rm));
   1185         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1186     }
   1187 
   1188     void orr(RegisterID rd, RegisterID rn, RegisterID rm)
   1189     {
   1190         if ((rd == rn) && !((rd | rm) & 8))
   1191             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
   1192         else if ((rd == rm) && !((rd | rn) & 8))
   1193             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
   1194         else
   1195             orr(rd, rn, rm, ShiftTypeAndAmount());
   1196     }
   1197 
   1198     void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
   1199     {
   1200         ASSERT(!BadReg(rd));
   1201         ASSERT(!BadReg(rm));
   1202         ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
   1203         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1204     }
   1205 
   1206     void ror(RegisterID rd, RegisterID rn, RegisterID rm)
   1207     {
   1208         ASSERT(!BadReg(rd));
   1209         ASSERT(!BadReg(rn));
   1210         ASSERT(!BadReg(rm));
   1211         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
   1212     }
   1213 
   1214     void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
   1215     {
   1216         ASSERT(!BadReg(rdLo));
   1217         ASSERT(!BadReg(rdHi));
   1218         ASSERT(!BadReg(rn));
   1219         ASSERT(!BadReg(rm));
   1220         ASSERT(rdLo != rdHi);
   1221         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
   1222     }
   1223 
   1224     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1225     void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
   1226     {
   1227         ASSERT(rt != ARMRegisters::pc);
   1228         ASSERT(rn != ARMRegisters::pc);
   1229         ASSERT(imm.isUInt12());
   1230 
   1231         if (!((rt | rn) & 8) && imm.isUInt7())
   1232             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
   1233         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
   1234             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
   1235         else
   1236             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
   1237     }
   1238 
   1239     // If index is set, this is a regular offset or a pre-indexed store;
   1240     // if index is not set then is is a post-index store.
   1241     //
   1242     // If wback is set rn is updated - this is a pre or post index store,
   1243     // if wback is not set this is a regular offset memory access.
   1244     //
   1245     // (-255 <= offset <= 255)
   1246     // _reg = REG[rn]
   1247     // _tmp = _reg + offset
   1248     // MEM[index ? _tmp : _reg] = REG[rt]
   1249     // if (wback) REG[rn] = _tmp
   1250     void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
   1251     {
   1252         ASSERT(rt != ARMRegisters::pc);
   1253         ASSERT(rn != ARMRegisters::pc);
   1254         ASSERT(index || wback);
   1255         ASSERT(!wback | (rt != rn));
   1256 
   1257         bool add = true;
   1258         if (offset < 0) {
   1259             add = false;
   1260             offset = -offset;
   1261         }
   1262         ASSERT((offset & ~0xff) == 0);
   1263 
   1264         offset |= (wback << 8);
   1265         offset |= (add   << 9);
   1266         offset |= (index << 10);
   1267         offset |= (1 << 11);
   1268 
   1269         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
   1270     }
   1271 
   1272     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
   1273     void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
   1274     {
   1275         ASSERT(rn != ARMRegisters::pc);
   1276         ASSERT(!BadReg(rm));
   1277         ASSERT(shift <= 3);
   1278 
   1279         if (!shift && !((rt | rn | rm) & 8))
   1280             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
   1281         else
   1282             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
   1283     }
   1284 
   1285     void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
   1286     {
   1287         // Rd can only be SP if Rn is also SP.
   1288         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
   1289         ASSERT(rd != ARMRegisters::pc);
   1290         ASSERT(rn != ARMRegisters::pc);
   1291         ASSERT(imm.isValid());
   1292 
   1293         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
   1294             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
   1295             return;
   1296         } else if (!((rd | rn) & 8)) {
   1297             if (imm.isUInt3()) {
   1298                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
   1299                 return;
   1300             } else if ((rd == rn) && imm.isUInt8()) {
   1301                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
   1302                 return;
   1303             }
   1304         }
   1305 
   1306         if (imm.isEncodedImm())
   1307             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
   1308         else {
   1309             ASSERT(imm.isUInt12());
   1310             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
   1311         }
   1312     }
   1313 
   1314     void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1315     {
   1316         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
   1317         ASSERT(rd != ARMRegisters::pc);
   1318         ASSERT(rn != ARMRegisters::pc);
   1319         ASSERT(!BadReg(rm));
   1320         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1321     }
   1322 
   1323     // NOTE: In an IT block, add doesn't modify the flags register.
   1324     void sub(RegisterID rd, RegisterID rn, RegisterID rm)
   1325     {
   1326         if (!((rd | rn | rm) & 8))
   1327             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
   1328         else
   1329             sub(rd, rn, rm, ShiftTypeAndAmount());
   1330     }
   1331 
   1332     // Not allowed in an IT (if then) block.
   1333     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
   1334     {
   1335         // Rd can only be SP if Rn is also SP.
   1336         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
   1337         ASSERT(rd != ARMRegisters::pc);
   1338         ASSERT(rn != ARMRegisters::pc);
   1339         ASSERT(imm.isValid());
   1340 
   1341         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
   1342             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
   1343             return;
   1344         } else if (!((rd | rn) & 8)) {
   1345             if (imm.isUInt3()) {
   1346                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
   1347                 return;
   1348             } else if ((rd == rn) && imm.isUInt8()) {
   1349                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_S_imm_T2, rd, imm.getUInt8());
   1350                 return;
   1351             }
   1352         }
   1353 
   1354         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
   1355     }
   1356 
   1357     // Not allowed in an IT (if then) block?
   1358     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1359     {
   1360         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
   1361         ASSERT(rd != ARMRegisters::pc);
   1362         ASSERT(rn != ARMRegisters::pc);
   1363         ASSERT(!BadReg(rm));
   1364         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
   1365     }
   1366 
   1367     // Not allowed in an IT (if then) block.
   1368     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
   1369     {
   1370         if (!((rd | rn | rm) & 8))
   1371             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_reg_T1, rm, rn, rd);
   1372         else
   1373             sub_S(rd, rn, rm, ShiftTypeAndAmount());
   1374     }
   1375 
   1376     void tst(RegisterID rn, ARMThumbImmediate imm)
   1377     {
   1378         ASSERT(!BadReg(rn));
   1379         ASSERT(imm.isEncodedImm());
   1380 
   1381         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
   1382     }
   1383 
   1384     void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
   1385     {
   1386         ASSERT(!BadReg(rn));
   1387         ASSERT(!BadReg(rm));
   1388         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
   1389     }
   1390 
   1391     void tst(RegisterID rn, RegisterID rm)
   1392     {
   1393         if ((rn | rm) & 8)
   1394             tst(rn, rm, ShiftTypeAndAmount());
   1395         else
   1396             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
   1397     }
   1398 
   1399     void vadd_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
   1400     {
   1401         m_formatter.vfpOp(0x0b00ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
   1402     }
   1403 
   1404     void vcmp_F64(FPRegisterID rd, FPRegisterID rm)
   1405     {
   1406         m_formatter.vfpOp(0x0bc0eeb4 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rm, 21, 16));
   1407     }
   1408 
   1409     void vcvt_F64_S32(FPRegisterID fd, FPRegisterID sm)
   1410     {
   1411         m_formatter.vfpOp(0x0bc0eeb8 | doubleRegisterMask(fd, 6, 28) | singleRegisterMask(sm, 16, 21));
   1412     }
   1413 
   1414     void vcvt_S32_F64(FPRegisterID sd, FPRegisterID fm)
   1415     {
   1416         m_formatter.vfpOp(0x0bc0eebd | singleRegisterMask(sd, 28, 6) | doubleRegisterMask(fm, 21, 16));
   1417     }
   1418 
   1419     void vldr(FPRegisterID rd, RegisterID rn, int32_t imm)
   1420     {
   1421         vmem(rd, rn, imm, true);
   1422     }
   1423 
   1424     void vmov(RegisterID rd, FPRegisterID sn)
   1425     {
   1426         m_formatter.vfpOp(0x0a10ee10 | (rd << 28) | singleRegisterMask(sn, 0, 23));
   1427     }
   1428 
   1429     void vmov(FPRegisterID sn, RegisterID rd)
   1430     {
   1431         m_formatter.vfpOp(0x0a10ee00 | (rd << 28) | singleRegisterMask(sn, 0, 23));
   1432     }
   1433 
   1434     // move FPSCR flags to APSR.
   1435     void vmrs_APSR_nzcv_FPSCR()
   1436     {
   1437         m_formatter.vfpOp(0xfa10eef1);
   1438     }
   1439 
   1440     void vmul_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
   1441     {
   1442         m_formatter.vfpOp(0x0b00ee20 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
   1443     }
   1444 
   1445     void vstr(FPRegisterID rd, RegisterID rn, int32_t imm)
   1446     {
   1447         vmem(rd, rn, imm, false);
   1448     }
   1449 
   1450     void vsub_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
   1451     {
   1452         m_formatter.vfpOp(0x0b40ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
   1453     }
   1454 
   1455 
   1456     JmpDst label()
   1457     {
   1458         return JmpDst(m_formatter.size());
   1459     }
   1460 
   1461     JmpDst align(int alignment)
   1462     {
   1463         while (!m_formatter.isAligned(alignment))
   1464             bkpt();
   1465 
   1466         return label();
   1467     }
   1468 
   1469     static void* getRelocatedAddress(void* code, JmpSrc jump)
   1470     {
   1471         ASSERT(jump.m_offset != -1);
   1472 
   1473         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
   1474     }
   1475 
   1476     static void* getRelocatedAddress(void* code, JmpDst destination)
   1477     {
   1478         ASSERT(destination.m_offset != -1);
   1479 
   1480         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
   1481     }
   1482 
   1483     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
   1484     {
   1485         return dst.m_offset - src.m_offset;
   1486     }
   1487 
   1488     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
   1489     {
   1490         return dst.m_offset - src.m_offset;
   1491     }
   1492 
   1493     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
   1494     {
   1495         return dst.m_offset - src.m_offset;
   1496     }
   1497 
   1498     // Assembler admin methods:
   1499 
   1500     size_t size() const
   1501     {
   1502         return m_formatter.size();
   1503     }
   1504 
   1505     void* executableCopy(ExecutablePool* allocator)
   1506     {
   1507         void* copy = m_formatter.executableCopy(allocator);
   1508 
   1509         unsigned jumpCount = m_jumpsToLink.size();
   1510         for (unsigned i = 0; i < jumpCount; ++i) {
   1511             uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from);
   1512             uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to);
   1513             linkJumpAbsolute(location, target);
   1514         }
   1515         m_jumpsToLink.clear();
   1516 
   1517         ASSERT(copy);
   1518         return copy;
   1519     }
   1520 
   1521     static unsigned getCallReturnOffset(JmpSrc call)
   1522     {
   1523         ASSERT(call.m_offset >= 0);
   1524         return call.m_offset;
   1525     }
   1526 
   1527     // Linking & patching:
   1528     //
   1529     // 'link' and 'patch' methods are for use on unprotected code - such as the code
   1530     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
   1531     // code has been finalized it is (platform support permitting) within a non-
   1532     // writable region of memory; to modify the code in an execute-only execuable
   1533     // pool the 'repatch' and 'relink' methods should be used.
   1534 
   1535     void linkJump(JmpSrc from, JmpDst to)
   1536     {
   1537         ASSERT(to.m_offset != -1);
   1538         ASSERT(from.m_offset != -1);
   1539         m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset));
   1540     }
   1541 
   1542     static void linkJump(void* code, JmpSrc from, void* to)
   1543     {
   1544         ASSERT(from.m_offset != -1);
   1545 
   1546         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
   1547         linkJumpAbsolute(location, to);
   1548     }
   1549 
   1550     // bah, this mathod should really be static, since it is used by the LinkBuffer.
   1551     // return a bool saying whether the link was successful?
   1552     static void linkCall(void* code, JmpSrc from, void* to)
   1553     {
   1554         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
   1555         ASSERT(from.m_offset != -1);
   1556         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
   1557 
   1558         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
   1559     }
   1560 
   1561     static void linkPointer(void* code, JmpDst where, void* value)
   1562     {
   1563         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
   1564     }
   1565 
   1566     static void relinkJump(void* from, void* to)
   1567     {
   1568         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
   1569         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
   1570 
   1571         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
   1572 
   1573         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
   1574     }
   1575 
   1576     static void relinkCall(void* from, void* to)
   1577     {
   1578         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
   1579         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
   1580 
   1581         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
   1582 
   1583         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 4 * sizeof(uint16_t));
   1584     }
   1585 
   1586     static void repatchInt32(void* where, int32_t value)
   1587     {
   1588         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
   1589 
   1590         setInt32(where, value);
   1591 
   1592         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
   1593     }
   1594 
   1595     static void repatchPointer(void* where, void* value)
   1596     {
   1597         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
   1598 
   1599         setPointer(where, value);
   1600 
   1601         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
   1602     }
   1603 
   1604     static void repatchLoadPtrToLEA(void* where)
   1605     {
   1606         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
   1607 
   1608         uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
   1609         ASSERT((*loadOp & 0xfff0) == OP_LDR_reg_T2);
   1610 
   1611         *loadOp = OP_ADD_reg_T3 | (*loadOp & 0xf);
   1612         ExecutableAllocator::cacheFlush(loadOp, sizeof(uint16_t));
   1613     }
   1614 
   1615 private:
   1616 
   1617     // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
   1618     // (i.e. +/-(0..255) 32-bit words)
   1619     void vmem(FPRegisterID rd, RegisterID rn, int32_t imm, bool isLoad)
   1620     {
   1621         bool up;
   1622         uint32_t offset;
   1623         if (imm < 0) {
   1624             offset = -imm;
   1625             up = false;
   1626         } else {
   1627             offset = imm;
   1628             up = true;
   1629         }
   1630 
   1631         // offset is effectively leftshifted by 2 already (the bottom two bits are zero, and not
   1632         // reperesented in the instruction.  Left shift by 14, to mov it into position 0x00AA0000.
   1633         ASSERT((offset & ~(0xff << 2)) == 0);
   1634         offset <<= 14;
   1635 
   1636         m_formatter.vfpOp(0x0b00ed00 | offset | (up << 7) | (isLoad << 4) | doubleRegisterMask(rd, 6, 28) | rn);
   1637     }
   1638 
   1639     static void setInt32(void* code, uint32_t value)
   1640     {
   1641         uint16_t* location = reinterpret_cast<uint16_t*>(code);
   1642         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
   1643 
   1644         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
   1645         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
   1646         location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
   1647         location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
   1648         location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
   1649         location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
   1650 
   1651         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
   1652     }
   1653 
   1654     static void setPointer(void* code, void* value)
   1655     {
   1656         setInt32(code, reinterpret_cast<uint32_t>(value));
   1657     }
   1658 
   1659     static bool isB(void* address)
   1660     {
   1661         uint16_t* instruction = static_cast<uint16_t*>(address);
   1662         return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
   1663     }
   1664 
   1665     static bool isBX(void* address)
   1666     {
   1667         uint16_t* instruction = static_cast<uint16_t*>(address);
   1668         return (instruction[0] & 0xff87) == OP_BX;
   1669     }
   1670 
   1671     static bool isMOV_imm_T3(void* address)
   1672     {
   1673         uint16_t* instruction = static_cast<uint16_t*>(address);
   1674         return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
   1675     }
   1676 
   1677     static bool isMOVT(void* address)
   1678     {
   1679         uint16_t* instruction = static_cast<uint16_t*>(address);
   1680         return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
   1681     }
   1682 
   1683     static bool isNOP_T1(void* address)
   1684     {
   1685         uint16_t* instruction = static_cast<uint16_t*>(address);
   1686         return instruction[0] == OP_NOP_T1;
   1687     }
   1688 
   1689     static bool isNOP_T2(void* address)
   1690     {
   1691         uint16_t* instruction = static_cast<uint16_t*>(address);
   1692         return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
   1693     }
   1694 
   1695     static void linkJumpAbsolute(uint16_t* instruction, void* target)
   1696     {
   1697         // FIMXE: this should be up in the MacroAssembler layer. :-(
   1698         const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
   1699 
   1700         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
   1701         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
   1702 
   1703         ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
   1704             || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) );
   1705 
   1706         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
   1707         if (((relative << 7) >> 7) == relative) {
   1708             // ARM encoding for the top two bits below the sign bit is 'peculiar'.
   1709             if (relative >= 0)
   1710                 relative ^= 0xC00000;
   1711 
   1712             // All branch offsets should be an even distance.
   1713             ASSERT(!(relative & 1));
   1714             // There may be a better way to fix this, but right now put the NOPs first, since in the
   1715             // case of an conditional branch this will be coming after an ITTT predicating *three*
   1716             // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
   1717             // variable wdith encoding - the previous instruction might *look* like an ITTT but
   1718             // actually be the second half of a 2-word op.
   1719             instruction[-5] = OP_NOP_T1;
   1720             instruction[-4] = OP_NOP_T2a;
   1721             instruction[-3] = OP_NOP_T2b;
   1722             instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
   1723             instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
   1724         } else {
   1725             ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
   1726             ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
   1727             instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
   1728             instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
   1729             instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
   1730             instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
   1731             instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
   1732         }
   1733     }
   1734 
   1735     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
   1736     {
   1737         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
   1738     }
   1739     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
   1740     {
   1741         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
   1742     }
   1743 
   1744     class ARMInstructionFormatter {
   1745     public:
   1746         void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
   1747         {
   1748             m_buffer.putShort(op | (rd << 8) | imm);
   1749         }
   1750 
   1751         void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
   1752         {
   1753             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
   1754         }
   1755 
   1756         void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
   1757         {
   1758             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
   1759         }
   1760 
   1761         void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
   1762         {
   1763             m_buffer.putShort(op | imm);
   1764         }
   1765 
   1766         void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
   1767         {
   1768             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
   1769         }
   1770         void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
   1771         {
   1772             m_buffer.putShort(op | imm);
   1773         }
   1774 
   1775         void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
   1776         {
   1777             m_buffer.putShort(op | (reg1 << 3) | reg2);
   1778         }
   1779 
   1780         void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
   1781         {
   1782             m_buffer.putShort(op | reg);
   1783             m_buffer.putShort(ff.m_u.value);
   1784         }
   1785 
   1786         void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
   1787         {
   1788             m_buffer.putShort(op);
   1789             m_buffer.putShort(ff.m_u.value);
   1790         }
   1791 
   1792         void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
   1793         {
   1794             m_buffer.putShort(op1);
   1795             m_buffer.putShort(op2);
   1796         }
   1797 
   1798         void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
   1799         {
   1800             ARMThumbImmediate newImm = imm;
   1801             newImm.m_value.imm4 = imm4;
   1802 
   1803             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
   1804             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
   1805         }
   1806 
   1807         void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
   1808         {
   1809             m_buffer.putShort(op | reg1);
   1810             m_buffer.putShort((reg2 << 12) | imm);
   1811         }
   1812 
   1813         void vfpOp(int32_t op)
   1814         {
   1815             m_buffer.putInt(op);
   1816         }
   1817 
   1818 
   1819         // Administrative methods:
   1820 
   1821         size_t size() const { return m_buffer.size(); }
   1822         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
   1823         void* data() const { return m_buffer.data(); }
   1824         void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
   1825 
   1826     private:
   1827         AssemblerBuffer m_buffer;
   1828     } m_formatter;
   1829 
   1830     Vector<LinkRecord> m_jumpsToLink;
   1831 };
   1832 
   1833 } // namespace JSC
   1834 
   1835 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
   1836 
   1837 #endif // ARMAssembler_h
   1838