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