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
38namespace JSC {
39
40namespace 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
163class ARMv7Assembler;
164class 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
247public:
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
353private:
354    ThumbImmediateType m_type;
355    ThumbImmediateValue m_value;
356};
357
358
359typedef enum {
360    SRType_LSL,
361    SRType_LSR,
362    SRType_ASR,
363    SRType_ROR,
364
365    SRType_RRX = SRType_ROR
366} ARMShiftType;
367
368class ARMv7Assembler;
369class ShiftTypeAndAmount {
370    friend class ARMv7Assembler;
371
372public:
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
388private:
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/*
403Some features of the Thumb instruction set are deprecated in ARMv7. Deprecated features affecting
404instructions 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
410register writeback
411*/
412
413class ARMv7Assembler {
414public:
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
488private:
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
714public:
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
1615private:
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