15f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian/*
2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2010 University of Szeged
45f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian *
55f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * Redistribution and use in source and binary forms, with or without
65f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * modification, are permitted provided that the following conditions
75f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * are met:
85f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * 1. Redistributions of source code must retain the above copyright
95f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian *    notice, this list of conditions and the following disclaimer.
105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * 2. Redistributions in binary form must reproduce the above copyright
115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian *    notice, this list of conditions and the following disclaimer in the
125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian *    documentation and/or other materials provided with the distribution.
135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian *
145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian */
265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#ifndef ARMAssembler_h
285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#define ARMAssembler_h
295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
30d0825bca7fe65beaee391d30da42e937db621564Steve Block#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "AssemblerBuffer.h"
335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include <wtf/Assertions.h>
345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include <wtf/Vector.h>
355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include <stdint.h>
365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qiannamespace JSC {
385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocknamespace ARMRegisters {
405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef enum {
415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r0,
425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r1,
435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r2,
445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r3,
455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r4,
465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r5,
475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r6,
485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r7, wr = r7,   // thumb work register
495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r8,
505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r9, sb = r9,   // static base
515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r10, sl = r10, // stack limit
525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r11, fp = r11, // frame pointer
535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r12, ip = r12,
545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r13, sp = r13,
555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r14, lr = r14,
565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        r15, pc = r15,
575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } RegisterID;
585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef enum {
60ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s0,
61ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s1,
62ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s2,
63ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s3,
64ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s4,
65ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s5,
66ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s6,
67ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s7,
68ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s8,
69ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s9,
70ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s10,
71ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s11,
72ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s12,
73ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s13,
74ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s14,
75ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s15,
76ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s16,
77ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s17,
78ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s18,
79ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s19,
80ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s20,
81ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s21,
82ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s22,
83ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s23,
84ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s24,
85ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s25,
86ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s26,
87ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s27,
88ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s28,
89ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s29,
90ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s30,
91ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        s31,
92ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    } FPSingleRegisterID;
93ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
94ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    typedef enum {
95ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d0,
96ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d1,
97ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d2,
98ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d3,
99ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d4,
100ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d5,
101ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d6,
102ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d7,
103ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d8,
104ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d9,
105ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d10,
106ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d11,
107ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d12,
108ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d13,
109ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d14,
110ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d15,
111ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d16,
112ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d17,
113ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d18,
114ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d19,
115ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d20,
116ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d21,
117ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d22,
118ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d23,
119ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d24,
120ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d25,
121ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d26,
122ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d27,
123ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d28,
124ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d29,
125ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d30,
126ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        d31,
127ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    } FPDoubleRegisterID;
128ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
129ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    typedef enum {
130ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q0,
131ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q1,
132ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q2,
133ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q3,
134ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q4,
135ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q5,
136ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q6,
137ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q7,
138ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q8,
139ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q9,
140ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q10,
141ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q11,
142ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q12,
143ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q13,
144ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q14,
145ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q15,
146ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q16,
147ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q17,
148ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q18,
149ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q19,
150ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q20,
151ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q21,
152ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q22,
153ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q23,
154ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q24,
155ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q25,
156ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q26,
157ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q27,
158ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q28,
159ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q29,
160ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q30,
161ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        q31,
162ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    } FPQuadRegisterID;
163ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
164ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    inline FPSingleRegisterID asSingle(FPDoubleRegisterID reg)
165ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
166ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(reg < d16);
167ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        return (FPSingleRegisterID)(reg << 1);
168ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
169ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
170ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    inline FPDoubleRegisterID asDouble(FPSingleRegisterID reg)
171ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
172ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(!(reg & 1));
173ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        return (FPDoubleRegisterID)(reg >> 1);
174ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
1755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianclass ARMv7Assembler;
1785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianclass ARMThumbImmediate {
1795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    friend class ARMv7Assembler;
1805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef uint8_t ThumbImmediateType;
1825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static const ThumbImmediateType TypeInvalid = 0;
1835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static const ThumbImmediateType TypeEncoded = 1;
1845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static const ThumbImmediateType TypeUInt16 = 2;
1855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef union {
1875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int16_t asInt;
1885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        struct {
1895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned imm8 : 8;
1905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned imm3 : 3;
1915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned i    : 1;
1925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned imm4 : 4;
1935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        };
1945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // If this is an encoded immediate, then it may describe a shift, or a pattern.
1955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        struct {
1965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned shiftValue7 : 7;
1975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned shiftAmount : 5;
1985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        };
1995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        struct {
2005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned immediate   : 8;
2015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned pattern     : 4;
2025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        };
2035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } ThumbImmediateValue;
2045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // byte0 contains least significant bit; not using an array to make client code endian agnostic.
2065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef union {
2075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int32_t asInt;
2085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        struct {
2095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            uint8_t byte0;
2105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            uint8_t byte1;
2115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            uint8_t byte2;
2125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            uint8_t byte3;
2135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        };
2145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } PatternBytes;
2155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
216231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
2175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
218d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
219d0825bca7fe65beaee391d30da42e937db621564Steve Block            value >>= N;             /* if any were set, lose the bottom N */
220d0825bca7fe65beaee391d30da42e937db621564Steve Block        else                         /* if none of the top N bits are set, */
221d0825bca7fe65beaee391d30da42e937db621564Steve Block            zeros += N;              /* then we have identified N leading zeros */
2225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static int32_t countLeadingZeros(uint32_t value)
2255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
2265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!value)
2275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return 32;
2285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int32_t zeros = 0;
2305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        countLeadingZerosPartial(value, zeros, 16);
2315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        countLeadingZerosPartial(value, zeros, 8);
2325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        countLeadingZerosPartial(value, zeros, 4);
2335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        countLeadingZerosPartial(value, zeros, 2);
2345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        countLeadingZerosPartial(value, zeros, 1);
2355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return zeros;
2365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ARMThumbImmediate()
2395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        : m_type(TypeInvalid)
2405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
2415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_value.asInt = 0;
2425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
2455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        : m_type(type)
2465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        , m_value(value)
2475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
2485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
2515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        : m_type(TypeUInt16)
2525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
253643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // Make sure this constructor is only reached with type TypeUInt16;
254643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // this extra parameter makes the code a little clearer by making it
255643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // explicit at call sites which type is being constructed
256643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        ASSERT_UNUSED(type, type == TypeUInt16);
257643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
2585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_value.asInt = value;
2595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
2605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianpublic:
2625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static ARMThumbImmediate makeEncodedImm(uint32_t value)
2635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
2645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ThumbImmediateValue encoding;
2655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        encoding.asInt = 0;
2665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // okay, these are easy.
2685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (value < 256) {
2695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.immediate = value;
2705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.pattern = 0;
2715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return ARMThumbImmediate(TypeEncoded, encoding);
2725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
2735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int32_t leadingZeros = countLeadingZeros(value);
2755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
2765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(leadingZeros < 24);
2775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
2795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
2805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // zero.  count(B) == 8, so the count of bits to be checked is 24 - count(Z).
2815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int32_t rightShiftAmount = 24 - leadingZeros;
2825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
2835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // Shift the value down to the low byte position.  The assign to
2845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // shiftValue7 drops the implicit top bit.
2855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.shiftValue7 = value >> rightShiftAmount;
2865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // The endoded shift amount is the magnitude of a right rotate.
2875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.shiftAmount = 8 + leadingZeros;
2885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return ARMThumbImmediate(TypeEncoded, encoding);
2895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
2905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        PatternBytes bytes;
2925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bytes.asInt = value;
2935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
2955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.immediate = bytes.byte0;
2965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.pattern = 3;
2975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return ARMThumbImmediate(TypeEncoded, encoding);
2985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
2995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
3015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.immediate = bytes.byte0;
3025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.pattern = 1;
3035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return ARMThumbImmediate(TypeEncoded, encoding);
3045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
3055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
307f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            encoding.immediate = bytes.byte1;
3085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            encoding.pattern = 2;
3095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return ARMThumbImmediate(TypeEncoded, encoding);
3105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
3115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return ARMThumbImmediate();
3135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static ARMThumbImmediate makeUInt12(int32_t value)
3165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
3175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return (!(value & 0xfffff000))
3185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
3195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            : ARMThumbImmediate();
3205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
3235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
3245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // If this is not a 12-bit unsigned it, try making an encoded immediate.
3255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return (!(value & 0xfffff000))
3265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
3275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            : makeEncodedImm(value);
3285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // The 'make' methods, above, return a !isValid() value if the argument
3315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // cannot be represented as the requested type.  This methods  is called
3325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // 'get' since the argument can always be represented.
3335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static ARMThumbImmediate makeUInt16(uint16_t value)
3345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
3355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return ARMThumbImmediate(TypeUInt16, value);
3365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isValid()
3395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
3405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_type != TypeInvalid;
3415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // These methods rely on the format of encoded byte values.
3445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt3() { return !(m_value.asInt & 0xfff8); }
3455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt4() { return !(m_value.asInt & 0xfff0); }
3465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt5() { return !(m_value.asInt & 0xffe0); }
3475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt6() { return !(m_value.asInt & 0xffc0); }
3485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt7() { return !(m_value.asInt & 0xff80); }
3495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt8() { return !(m_value.asInt & 0xff00); }
3505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
3515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
3525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
3535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isUInt16() { return m_type == TypeUInt16; }
3545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
3555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
3565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
3575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
3585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
3595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
3605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
3615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
3625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
3635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
3645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool isEncodedImm() { return m_type == TypeEncoded; }
3665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianprivate:
3685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ThumbImmediateType m_type;
3695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ThumbImmediateValue m_value;
3705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian};
3715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qiantypedef enum {
3735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    SRType_LSL,
3745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    SRType_LSR,
3755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    SRType_ASR,
3765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    SRType_ROR,
3775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    SRType_RRX = SRType_ROR
3795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} ARMShiftType;
3805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianclass ShiftTypeAndAmount {
3825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    friend class ARMv7Assembler;
3835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianpublic:
3855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ShiftTypeAndAmount()
3865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
3875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_u.type = (ARMShiftType)0;
3885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_u.amount = 0;
3895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
3925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
3935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_u.type = type;
3945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_u.amount = amount & 31;
3955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
3965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    unsigned lo4() { return m_u.lo4; }
3985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    unsigned hi4() { return m_u.hi4; }
3995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianprivate:
4015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    union {
4025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        struct {
4035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned lo4 : 4;
4045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned hi4 : 4;
4055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        };
4065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        struct {
4075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned type   : 2;
408a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            unsigned amount : 6;
4095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        };
4105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } m_u;
4115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian};
4125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianclass ARMv7Assembler {
4145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianpublic:
415cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    ~ARMv7Assembler()
416cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
417cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ASSERT(m_jumpsToLink.isEmpty());
418cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
419cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
420231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    typedef ARMRegisters::RegisterID RegisterID;
421ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
422ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
423ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    typedef ARMRegisters::FPQuadRegisterID FPQuadRegisterID;
4245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // (HS, LO, HI, LS) -> (AE, B, A, BE)
4265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // (VS, VC) -> (O, NO)
4275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef enum {
4285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionEQ,
4295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionNE,
430f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ConditionHS, ConditionCS = ConditionHS,
431f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ConditionLO, ConditionCC = ConditionLO,
4325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionMI,
4335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionPL,
4345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionVS,
4355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionVC,
4365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionHI,
4375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionLS,
4385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionGE,
4395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionLT,
4405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionGT,
4415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionLE,
4425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ConditionAL,
443f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        ConditionInvalid
4445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } Condition;
4455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
446a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    enum JumpType { JumpFixed, JumpNoCondition, JumpCondition, JumpNoConditionFixedSize, JumpConditionFixedSize, JumpTypeCount };
447a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    enum JumpLinkType { LinkInvalid, LinkJumpT1, LinkJumpT2, LinkJumpT3,
448a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        LinkJumpT4, LinkConditionalJumpT4, LinkBX, LinkConditionalBX, JumpLinkTypeCount };
449a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static const int JumpSizes[JumpLinkTypeCount];
450a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static const int JumpPaddingSizes[JumpTypeCount];
451dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    class LinkRecord {
452dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    public:
453dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
454dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            : m_from(from)
455dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            , m_to(to)
456dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            , m_type(type)
457dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            , m_linkType(LinkInvalid)
458dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            , m_condition(condition)
459dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        {
460dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        }
461dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        intptr_t from() const { return m_from; }
462dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        void setFrom(intptr_t from) { m_from = from; }
463dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        intptr_t to() const { return m_to; }
464dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        JumpType type() const { return m_type; }
465dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        JumpLinkType linkType() const { return m_linkType; }
466dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; }
467dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        Condition condition() const { return m_condition; }
468dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    private:
469dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        intptr_t m_from : 31;
470dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        intptr_t m_to : 31;
471a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        JumpType m_type : 3;
472a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        JumpLinkType m_linkType : 4;
473dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        Condition m_condition : 16;
474dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    };
475dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
4765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    class JmpSrc {
4775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        friend class ARMv7Assembler;
4785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        friend class ARMInstructionFormatter;
479dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        friend class LinkBuffer;
4805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    public:
4815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        JmpSrc()
4825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            : m_offset(-1)
4835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
4845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
4855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    private:
487dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        JmpSrc(int offset, JumpType type)
4885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            : m_offset(offset)
489f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            , m_condition(ConditionInvalid)
490dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            , m_type(type)
4915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
492a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT(m_type == JumpFixed || m_type == JumpNoCondition || m_type == JumpNoConditionFixedSize);
493dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        }
494dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
495dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        JmpSrc(int offset, JumpType type, Condition condition)
496dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            : m_offset(offset)
497dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            , m_condition(condition)
498dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            , m_type(type)
499dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        {
500a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT(m_type == JumpFixed || m_type == JumpCondition || m_type == JumpConditionFixedSize);
5015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
5025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int m_offset;
504dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        Condition m_condition : 16;
505dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        JumpType m_type : 16;
506dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
5075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    };
5085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    class JmpDst {
5105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        friend class ARMv7Assembler;
5115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        friend class ARMInstructionFormatter;
512dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        friend class LinkBuffer;
5135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    public:
5145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        JmpDst()
5155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            : m_offset(-1)
5165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            , m_used(false)
5175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
5185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
5195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bool isUsed() const { return m_used; }
521f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        bool isSet() const { return (m_offset != -1); }
5225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void used() { m_used = true; }
5235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    private:
5245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        JmpDst(int offset)
5255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            : m_offset(offset)
5265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            , m_used(false)
5275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
5285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            ASSERT(m_offset == offset);
5295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
5305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
53181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        signed int m_offset : 31;
5325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int m_used : 1;
5335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    };
5345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianprivate:
5365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // ARMv7, Appx-A.6.3
5385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool BadReg(RegisterID reg)
5395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
540231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
5415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
5425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
543ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    uint32_t singleRegisterMask(FPSingleRegisterID rdNum, int highBitsShift, int lowBitShift)
5445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
5455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        uint32_t rdMask = (rdNum >> 1) << highBitsShift;
5465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (rdNum & 1)
5475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            rdMask |= 1 << lowBitShift;
5485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return rdMask;
5495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
5505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
551ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    uint32_t doubleRegisterMask(FPDoubleRegisterID rdNum, int highBitShift, int lowBitsShift)
5525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
5535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
5545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (rdNum & 16)
5555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            rdMask |= 1 << highBitShift;
5565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return rdMask;
5575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
5585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef enum {
5605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_reg_T1       = 0x1800,
5615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_reg_T1       = 0x1A00,
5625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_imm_T1       = 0x1C00,
5635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_imm_T1       = 0x1E00,
5645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_MOV_imm_T1       = 0x2000,
5655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_CMP_imm_T1       = 0x2800,
5665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_imm_T2       = 0x3000,
5675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_imm_T2       = 0x3800,
5685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_AND_reg_T1       = 0x4000,
5695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_EOR_reg_T1       = 0x4040,
5705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_TST_reg_T1       = 0x4200,
571ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_RSB_imm_T1       = 0x4240,
5725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_CMP_reg_T1       = 0x4280,
5735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ORR_reg_T1       = 0x4300,
5745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_MVN_reg_T1       = 0x43C0,
5755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_reg_T2       = 0x4400,
5765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_MOV_reg_T1       = 0x4600,
5775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_BLX              = 0x4700,
5785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_BX               = 0x4700,
5795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_STR_reg_T1       = 0x5000,
5805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDR_reg_T1       = 0x5800,
581dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        OP_LDRH_reg_T1      = 0x5A00,
582dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        OP_LDRB_reg_T1      = 0x5C00,
5835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_STR_imm_T1       = 0x6000,
5845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDR_imm_T1       = 0x6800,
585dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        OP_LDRB_imm_T1      = 0x7800,
5865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDRH_imm_T1      = 0x8800,
5875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_STR_imm_T2       = 0x9000,
5885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDR_imm_T2       = 0x9800,
5895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_SP_imm_T1    = 0xA800,
5905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_SP_imm_T2    = 0xB000,
5915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_SP_imm_T1    = 0xB080,
5925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_BKPT             = 0xBE00,
5935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_IT               = 0xBF00,
594cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        OP_NOP_T1           = 0xBF00,
5955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } OpcodeID;
5965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef enum {
598a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        OP_B_T1         = 0xD000,
599a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        OP_B_T2         = 0xE000,
6005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_AND_reg_T2   = 0xEA00,
6015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_TST_reg_T2   = 0xEA10,
6025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ORR_reg_T2   = 0xEA40,
603ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_ORR_S_reg_T2 = 0xEA50,
6045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ASR_imm_T1   = 0xEA4F,
6055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LSL_imm_T1   = 0xEA4F,
6065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LSR_imm_T1   = 0xEA4F,
6075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ROR_imm_T1   = 0xEA4F,
6085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_MVN_reg_T2   = 0xEA6F,
6095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_EOR_reg_T2   = 0xEA80,
6105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_reg_T3   = 0xEB00,
6115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_S_reg_T3 = 0xEB10,
6125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_reg_T2   = 0xEBA0,
6135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_S_reg_T2 = 0xEBB0,
6145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_CMP_reg_T2   = 0xEBB0,
615ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VSTR         = 0xED00,
616ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VLDR         = 0xED10,
617ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMOV_StoC    = 0xEE00,
618ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMOV_CtoS    = 0xEE10,
619ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMUL_T2      = 0xEE20,
620ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VADD_T2      = 0xEE30,
621ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VSUB_T2      = 0xEE30,
622ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VDIV         = 0xEE80,
623cad810f21b803229eb11403f9209855525a25d57Steve Block        OP_VCMP         = 0xEEB0,
624ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VCVT_FPIVFP  = 0xEEB0,
625ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMOV_IMM_T2  = 0xEEB0,
626ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMRS         = 0xEEB0,
627a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        OP_B_T3a        = 0xF000,
6285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_B_T4a        = 0xF000,
6295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_AND_imm_T1   = 0xF000,
6305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_TST_imm      = 0xF010,
6315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ORR_imm_T1   = 0xF040,
6325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_MOV_imm_T2   = 0xF040,
6335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_MVN_imm      = 0xF060,
6345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_EOR_imm_T1   = 0xF080,
6355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_imm_T3   = 0xF100,
6365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_S_imm_T3 = 0xF110,
6375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_CMN_imm      = 0xF110,
6385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_imm_T3   = 0xF1A0,
6395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_S_imm_T3 = 0xF1B0,
6405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_CMP_imm_T2   = 0xF1B0,
641ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_RSB_imm_T2   = 0xF1C0,
6425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ADD_imm_T4   = 0xF200,
6435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_MOV_imm_T3   = 0xF240,
6445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SUB_imm_T4   = 0xF2A0,
6455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_MOVT         = 0xF2C0,
646cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        OP_NOP_T2a      = 0xF3AF,
647dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        OP_LDRB_imm_T3  = 0xF810,
648dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        OP_LDRB_reg_T2  = 0xF810,
6495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDRH_reg_T2  = 0xF830,
6505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDRH_imm_T3  = 0xF830,
6515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_STR_imm_T4   = 0xF840,
6525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_STR_reg_T2   = 0xF840,
6535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDR_imm_T4   = 0xF850,
6545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDR_reg_T2   = 0xF850,
655dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        OP_LDRB_imm_T2  = 0xF890,
6565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDRH_imm_T2  = 0xF8B0,
6575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_STR_imm_T3   = 0xF8C0,
6585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LDR_imm_T3   = 0xF8D0,
6595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LSL_reg_T2   = 0xFA00,
6605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_LSR_reg_T2   = 0xFA20,
6615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ASR_reg_T2   = 0xFA40,
6625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_ROR_reg_T2   = 0xFA60,
6634576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        OP_CLZ          = 0xFAB0,
6645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        OP_SMULL_T1     = 0xFB80,
6655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } OpcodeID1;
6665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
6675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    typedef enum {
668ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VADD_T2b     = 0x0A00,
669ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VDIVb        = 0x0A00,
670ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VLDRb        = 0x0A00,
671ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMOV_IMM_T2b = 0x0A00,
672ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMUL_T2b     = 0x0A00,
673ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VSTRb        = 0x0A00,
674ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMOV_CtoSb   = 0x0A10,
675ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMOV_StoCb   = 0x0A10,
676ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VMRSb        = 0x0A10,
677cad810f21b803229eb11403f9209855525a25d57Steve Block        OP_VCMPb        = 0x0A40,
678ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VCVT_FPIVFPb = 0x0A40,
679ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_VSUB_T2b     = 0x0A40,
680cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        OP_NOP_T2b      = 0x8000,
681a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        OP_B_T3b        = 0x8000,
682ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        OP_B_T4b        = 0x9000,
6835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } OpcodeID2;
6845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
6855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    struct FourFours {
6865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
6875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
6885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_u.f0 = f0;
6895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_u.f1 = f1;
6905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_u.f2 = f2;
6915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_u.f3 = f3;
6925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
6935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
6945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        union {
6955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            unsigned value;
6965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            struct {
6975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                unsigned f0 : 4;
6985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                unsigned f1 : 4;
6995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                unsigned f2 : 4;
7005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                unsigned f3 : 4;
7015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            };
7025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        } m_u;
7035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    };
7045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    class ARMInstructionFormatter;
7065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // false means else!
7085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    bool ifThenElseConditionBit(Condition condition, bool isIf)
7095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
7105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return isIf ? (condition & 1) : !(condition & 1);
7115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
7125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
7135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
7145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
7155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            | (ifThenElseConditionBit(condition, inst3if) << 2)
7165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            | (ifThenElseConditionBit(condition, inst4if) << 1)
7175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            | 1;
718a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
7195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return (condition << 4) | mask;
7205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
7215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
7225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
7235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
7245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            | (ifThenElseConditionBit(condition, inst3if) << 2)
7255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            | 2;
726a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
7275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return (condition << 4) | mask;
7285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
7295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t ifThenElse(Condition condition, bool inst2if)
7305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
7315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
7325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            | 4;
733a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
7345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return (condition << 4) | mask;
7355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
7365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    uint8_t ifThenElse(Condition condition)
7385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
7395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        int mask = 8;
7405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return (condition << 4) | mask;
7415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
7425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianpublic:
744dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
7455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
7465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
7475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Rd can only be SP if Rn is also SP.
748231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
749231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rd != ARMRegisters::pc);
750231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
7515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isValid());
7525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
753231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (rn == ARMRegisters::sp) {
7545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (!(rd & 8) && imm.isUInt10()) {
7555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
7565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
757231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
7585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
7595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
7605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
7615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        } else if (!((rd | rn) & 8)) {
7625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (imm.isUInt3()) {
7635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
7645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
7655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            } else if ((rd == rn) && imm.isUInt8()) {
7665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
7675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
7685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
7695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
7705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (imm.isEncodedImm())
7725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
7735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else {
7745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            ASSERT(imm.isUInt12());
7755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
7765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
7775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
7785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
7805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
781231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
782231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rd != ARMRegisters::pc);
783231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
7845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
7855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
7865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
7875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // NOTE: In an IT block, add doesn't modify the flags register.
7895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void add(RegisterID rd, RegisterID rn, RegisterID rm)
7905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
7915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (rd == rn)
7925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
7935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else if (rd == rm)
7945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
7955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else if (!((rd | rn | rm) & 8))
7965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
7975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
7985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            add(rd, rn, rm, ShiftTypeAndAmount());
7995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Not allowed in an IT (if then) block.
8025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
8035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
8045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Rd can only be SP if Rn is also SP.
805231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
806231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rd != ARMRegisters::pc);
807231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
8085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isEncodedImm());
8095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!((rd | rn) & 8)) {
8115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (imm.isUInt3()) {
812ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
8135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
8145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            } else if ((rd == rn) && imm.isUInt8()) {
815ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
8165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
8175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
8185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
8195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
8215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Not allowed in an IT (if then) block?
8245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
8255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
826231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
827231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rd != ARMRegisters::pc);
828231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
8295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
8305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
8315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Not allowed in an IT (if then) block.
8345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
8355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
8365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!((rd | rn | rm) & 8))
837ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
8385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
8395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            add_S(rd, rn, rm, ShiftTypeAndAmount());
8405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
8435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
8445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
8455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
8465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isEncodedImm());
8475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
8485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
8515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
8525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
8535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
8545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
8555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
8565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
8595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
8605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((rd == rn) && !((rd | rm) & 8))
8615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
8625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else if ((rd == rm) && !((rd | rn) & 8))
8635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
8645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
8655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            ARM_and(rd, rn, rm, ShiftTypeAndAmount());
8665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
8695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
8705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
8715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
8725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
8735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
8745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void asr(RegisterID rd, RegisterID rn, RegisterID rm)
8775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
8785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
8795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
8805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
8815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
8825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
883dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
8845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Only allowed in IT (if then) block if last instruction.
885dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    JmpSrc b(JumpType type)
8865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
8875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
888dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return JmpSrc(m_formatter.size(), type);
8895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Only allowed in IT (if then) block if last instruction.
892dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    JmpSrc blx(RegisterID rm, JumpType type)
8935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
894231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rm != ARMRegisters::pc);
8955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
896dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return JmpSrc(m_formatter.size(), type);
8975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
8985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Only allowed in IT (if then) block if last instruction.
900dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    JmpSrc bx(RegisterID rm, JumpType type, Condition condition)
901dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
902dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
903dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return JmpSrc(m_formatter.size(), type, condition);
904dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
905dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
906dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    JmpSrc bx(RegisterID rm, JumpType type)
9075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
909dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return JmpSrc(m_formatter.size(), type);
9105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void bkpt(uint8_t imm=0)
9135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
9155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9174576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    void clz(RegisterID rd, RegisterID rm)
9184576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    {
9194576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        ASSERT(!BadReg(rd));
9204576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        ASSERT(!BadReg(rm));
9214576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        m_formatter.twoWordOp12Reg4FourFours(OP_CLZ, rm, FourFours(0xf, rd, 8, rm));
9224576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
9234576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
9245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void cmn(RegisterID rn, ARMThumbImmediate imm)
9255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
926231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
9275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isEncodedImm());
9285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
9305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void cmp(RegisterID rn, ARMThumbImmediate imm)
9335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
934231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
9355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isEncodedImm());
9365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!(rn & 8) && imm.isUInt8())
9385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
9395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
9405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
9415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
9445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
945231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
9465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
9475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
9485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void cmp(RegisterID rn, RegisterID rm)
9515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((rn | rm) & 8)
9535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            cmp(rn, rm, ShiftTypeAndAmount());
9545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
9555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
9565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // xor is not spelled with an 'e'. :-(
9595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
9605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
9625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
9635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isEncodedImm());
9645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
9655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // xor is not spelled with an 'e'. :-(
9685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
9695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
9715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
9725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
9735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
9745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // xor is not spelled with an 'e'. :-(
9775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void eor(RegisterID rd, RegisterID rn, RegisterID rm)
9785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((rd == rn) && !((rd | rm) & 8))
9805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
9815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else if ((rd == rm) && !((rd | rn) & 8))
9825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
9835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
9845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            eor(rd, rn, rm, ShiftTypeAndAmount());
9855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void it(Condition cond)
9885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
9905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void it(Condition cond, bool inst2if)
9935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
9955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
9965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void it(Condition cond, bool inst2if, bool inst3if)
9985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
9995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
10005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
10035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
10045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
10055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1007231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
10085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
10095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1010231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
10115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isUInt12());
10125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!((rt | rn) & 8) && imm.isUInt7())
10145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1015231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
10165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
10175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
10185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
10195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If index is set, this is a regular offset or a pre-indexed load;
10225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if index is not set then is is a post-index load.
10235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //
10245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If wback is set rn is updated - this is a pre or post index load,
10255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if wback is not set this is a regular offset memory access.
10265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //
10275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // (-255 <= offset <= 255)
10285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // _reg = REG[rn]
10295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // _tmp = _reg + offset
10305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // MEM[index ? _tmp : _reg] = REG[rt]
10315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if (wback) REG[rn] = _tmp
10325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
10335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1034231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rt != ARMRegisters::pc);
1035231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
10365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(index || wback);
10375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!wback | (rt != rn));
10385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bool add = true;
10405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (offset < 0) {
10415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            add = false;
10425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            offset = -offset;
10435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
10445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT((offset & ~0xff) == 0);
10455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (wback << 8);
10475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (add   << 9);
10485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (index << 10);
10495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (1 << 11);
10505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
10525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1054231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
10555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
10565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1057231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
10585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
10595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(shift <= 3);
10605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!shift && !((rt | rn | rm) & 8))
10625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
10635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
10645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
10655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1067231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
10685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
10695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1070231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
10715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isUInt12());
10725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!((rt | rn) & 8) && imm.isUInt6())
10745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
10755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
10765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
10775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If index is set, this is a regular offset or a pre-indexed load;
10805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if index is not set then is is a post-index load.
10815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //
10825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If wback is set rn is updated - this is a pre or post index load,
10835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if wback is not set this is a regular offset memory access.
10845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //
10855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // (-255 <= offset <= 255)
10865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // _reg = REG[rn]
10875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // _tmp = _reg + offset
10885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // MEM[index ? _tmp : _reg] = REG[rt]
10895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if (wback) REG[rn] = _tmp
10905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
10915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1092231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rt != ARMRegisters::pc);
1093231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
10945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(index || wback);
10955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!wback | (rt != rn));
10965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bool add = true;
10985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (offset < 0) {
10995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            add = false;
11005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            offset = -offset;
11015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
11025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT((offset & ~0xff) == 0);
11035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (wback << 8);
11055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (add   << 9);
11065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (index << 10);
11075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (1 << 11);
11085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
11105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
11115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
11135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
11145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rt));   // Memory hint
1115231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
11165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
11175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(shift <= 3);
11185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!shift && !((rt | rn | rm) & 8))
11205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
11215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
11225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
11235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
11245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(imm.isUInt12());
1129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!((rt | rn) & 8) && imm.isUInt5())
1131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
1132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        else
1133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
1134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(rt != ARMRegisters::pc);
1139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(rn != ARMRegisters::pc);
1140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(index || wback);
1141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(!wback | (rt != rn));
1142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        bool add = true;
1144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (offset < 0) {
1145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            add = false;
1146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            offset = -offset;
1147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(!(offset & ~0xff));
1150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        offset |= (wback << 8);
1152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        offset |= (add   << 9);
1153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        offset |= (index << 10);
1154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        offset |= (1 << 11);
1155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
1157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1160dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1161dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(!BadReg(rm));
1163dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ASSERT(shift <= 3);
1164dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1165dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!shift && !((rt | rn | rm) & 8))
1166dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
1167dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        else
1168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
11715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
11725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
11735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
11745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
11755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
11765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
11775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
11785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
11805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
11815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
11825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
11835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
11845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
11855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
11865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
11885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
11895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
11905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
11915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
11925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
11935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
11945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
11965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
11975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
11985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
11995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
12005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
12015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void movT3(RegisterID rd, ARMThumbImmediate imm)
12045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isValid());
12065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!imm.isEncodedImm());
12075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
12085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
12105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian     void mov(RegisterID rd, ARMThumbImmediate imm)
12135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isValid());
12155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
12165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((rd < 8) && imm.isUInt8())
12185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
12195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else if (imm.isEncodedImm())
12205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
12215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
12225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            movT3(rd, imm);
12235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian   void mov(RegisterID rd, RegisterID rm)
12265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
12285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void movt(RegisterID rd, ARMThumbImmediate imm)
12315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isUInt16());
12335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
12345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
12355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void mvn(RegisterID rd, ARMThumbImmediate imm)
12385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isEncodedImm());
12405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
12415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
12435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
12465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
12485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
12495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
12505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void mvn(RegisterID rd, RegisterID rm)
12535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!((rd | rm) & 8))
12555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
12565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
12575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            mvn(rd, rm, ShiftTypeAndAmount());
12585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1260ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void neg(RegisterID rd, RegisterID rm)
1261ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
1262ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
1263ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        sub(rd, zero, rm);
1264ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
1265ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
12665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
12675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
12695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
12705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isEncodedImm());
12715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
12725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
12755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
12775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
12785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
12795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
12805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void orr(RegisterID rd, RegisterID rn, RegisterID rm)
12835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
12845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((rd == rn) && !((rd | rm) & 8))
12855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
12865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else if ((rd == rm) && !((rd | rn) & 8))
12875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
12885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
12895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            orr(rd, rn, rm, ShiftTypeAndAmount());
12905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
12915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1292ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1293ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
1294ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(!BadReg(rd));
1295ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(!BadReg(rn));
1296ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(!BadReg(rm));
1297ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.twoWordOp12Reg4FourFours(OP_ORR_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1298ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
1299ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
1300ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void orr_S(RegisterID rd, RegisterID rn, RegisterID rm)
1301ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
1302ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        if ((rd == rn) && !((rd | rm) & 8))
1303ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1304ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        else if ((rd == rm) && !((rd | rn) & 8))
1305ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1306ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        else
1307ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            orr_S(rd, rn, rm, ShiftTypeAndAmount());
1308ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
1309ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
13105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
13115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
13125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
13135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
13145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
13155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
13165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
13175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void ror(RegisterID rd, RegisterID rn, RegisterID rm)
13195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
13205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rd));
13215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
13225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
13235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
13245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
13255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
13275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
13285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rdLo));
13295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rdHi));
13305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
13315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
13325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(rdLo != rdHi);
13335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
13345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
13355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1336231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
13375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
13385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1339231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rt != ARMRegisters::pc);
1340231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
13415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isUInt12());
13425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!((rt | rn) & 8) && imm.isUInt7())
13445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1345231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
13465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
13475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
13485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
13495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
13505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If index is set, this is a regular offset or a pre-indexed store;
13525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if index is not set then is is a post-index store.
13535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //
13545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If wback is set rn is updated - this is a pre or post index store,
13555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if wback is not set this is a regular offset memory access.
13565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //
13575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // (-255 <= offset <= 255)
13585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // _reg = REG[rn]
13595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // _tmp = _reg + offset
13605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // MEM[index ? _tmp : _reg] = REG[rt]
13615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // if (wback) REG[rn] = _tmp
13625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
13635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1364231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rt != ARMRegisters::pc);
1365231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
13665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(index || wback);
13675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!wback | (rt != rn));
13685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bool add = true;
13705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (offset < 0) {
13715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            add = false;
13725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            offset = -offset;
13735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
13745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT((offset & ~0xff) == 0);
13755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (wback << 8);
13775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (add   << 9);
13785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (index << 10);
13795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        offset |= (1 << 11);
13805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
13825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
13835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1384231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
13855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
13865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1387231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
13885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
13895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(shift <= 3);
13905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!shift && !((rt | rn | rm) & 8))
13925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
13935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
13945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
13955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
13965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
13985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
13995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Rd can only be SP if Rn is also SP.
1400231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1401231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rd != ARMRegisters::pc);
1402231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
14035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isValid());
14045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1405231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
14065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
14075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return;
14085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        } else if (!((rd | rn) & 8)) {
14095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (imm.isUInt3()) {
14105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
14115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
14125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            } else if ((rd == rn) && imm.isUInt8()) {
14135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
14145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
14155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
14165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
14175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (imm.isEncodedImm())
14195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
14205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else {
14215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            ASSERT(imm.isUInt12());
14225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
14235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
14245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
14255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1426ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
1427ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
1428ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(rd != ARMRegisters::pc);
1429ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(rn != ARMRegisters::pc);
1430ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(imm.isValid());
1431ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(imm.isUInt12());
1432ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
1433ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        if (!((rd | rn) & 8) && !imm.getUInt12())
1434ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_formatter.oneWordOp10Reg3Reg3(OP_RSB_imm_T1, rn, rd);
1435ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        else
1436ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
1437ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
1438ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
14395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
14405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1441231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1442231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rd != ARMRegisters::pc);
1443231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
14445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
14455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
14465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
14475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // NOTE: In an IT block, add doesn't modify the flags register.
14495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void sub(RegisterID rd, RegisterID rn, RegisterID rm)
14505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
14515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!((rd | rn | rm) & 8))
14525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
14535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
14545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            sub(rd, rn, rm, ShiftTypeAndAmount());
14555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
14565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Not allowed in an IT (if then) block.
14585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
14595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
14605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Rd can only be SP if Rn is also SP.
1461231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1462231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rd != ARMRegisters::pc);
1463231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
14645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isValid());
14655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1466231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
14675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
14685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return;
14695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        } else if (!((rd | rn) & 8)) {
14705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (imm.isUInt3()) {
1471ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
14725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
14735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            } else if ((rd == rn) && imm.isUInt8()) {
1474ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
14755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
14765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
14775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
14785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
14805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
14815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Not allowed in an IT (if then) block?
14835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
14845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1485231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1486231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rd != ARMRegisters::pc);
1487231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(rn != ARMRegisters::pc);
14885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
14895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
14905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
14915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Not allowed in an IT (if then) block.
14935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
14945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
14955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!((rd | rn | rm) & 8))
1496ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
14975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
14985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            sub_S(rd, rn, rm, ShiftTypeAndAmount());
14995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void tst(RegisterID rn, ARMThumbImmediate imm)
15025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
15035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
15045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(imm.isEncodedImm());
15055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
15075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
15105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
15115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rn));
15125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!BadReg(rm));
15135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
15145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void tst(RegisterID rn, RegisterID rm)
15175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
15185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if ((rn | rm) & 8)
15195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            tst(rn, rm, ShiftTypeAndAmount());
15205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        else
15215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
15225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1524ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1525ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
1526ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
1527ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
1528ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
1529ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
15305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1531cad810f21b803229eb11403f9209855525a25d57Steve Block        m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
1532cad810f21b803229eb11403f9209855525a25d57Steve Block    }
1533cad810f21b803229eb11403f9209855525a25d57Steve Block
1534cad810f21b803229eb11403f9209855525a25d57Steve Block    void vcmpz_F64(FPDoubleRegisterID rd)
1535cad810f21b803229eb11403f9209855525a25d57Steve Block    {
1536cad810f21b803229eb11403f9209855525a25d57Steve Block        m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
15375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1539ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)
15405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1541ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        // boolean values are 64bit (toInt, unsigned, roundZero)
1542ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
15435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1545ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)
15465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1547ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        // boolean values are 64bit (toInt, unsigned, roundZero)
1548ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
15495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1551ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
15525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1553ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
15545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1556ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
15575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1558ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
15595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1561ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vmov(RegisterID rd, FPSingleRegisterID rn)
15625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1563ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(!BadReg(rd));
1564ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));
15655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1567ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vmov(FPSingleRegisterID rd, RegisterID rn)
15685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1569ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(!BadReg(rn));
1570ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0));
15715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1573ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vmrs(RegisterID reg = ARMRegisters::pc)
15745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1575ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(reg != ARMRegisters::sp);
1576ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
15775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1579ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
15805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1581ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
15825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1584ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
15855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1586ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
15875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1589ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1590ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
1591ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
1592ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    }
15935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JmpDst label()
15955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
15965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return JmpDst(m_formatter.size());
15975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
15985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JmpDst align(int alignment)
16005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
16015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        while (!m_formatter.isAligned(alignment))
16025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            bkpt();
16035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return label();
16055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
16065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static void* getRelocatedAddress(void* code, JmpSrc jump)
16085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
16095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(jump.m_offset != -1);
16105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
16125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
16135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static void* getRelocatedAddress(void* code, JmpDst destination)
16155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
16165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(destination.m_offset != -1);
16175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
16195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
16205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
16225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
16235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return dst.m_offset - src.m_offset;
16245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
16255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
16275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
16285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return dst.m_offset - src.m_offset;
16295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
16305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
16325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
16335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return dst.m_offset - src.m_offset;
16345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1635dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
1636dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    int executableOffsetFor(int location)
1637dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
1638dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (!location)
1639dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            return 0;
1640dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1];
1641dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
1642dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
1643a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JumpPaddingSizes[jumpType] - JumpSizes[jumpLinkType]; }
16445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Assembler admin methods:
16465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
16475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    size_t size() const
16485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
16495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return m_formatter.size();
16505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
16515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1652dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    static bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
16535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1654dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return a.from() < b.from();
1655dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
1656cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1657a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool canCompact(JumpType jumpType)
1658dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
1659a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // The following cannot be compacted:
1660a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        //   JumpFixed: represents custom jump sequence
1661a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        //   JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size
1662a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        //   JumpConditionFixedSize: represents conditional jump that must remain a fixed size
1663a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return (jumpType == JumpNoCondition) || (jumpType == JumpCondition);
1664a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
1665a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1666a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
1667a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
1668a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (jumpType == JumpFixed)
1669a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return LinkInvalid;
1670a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1671a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // for patchable jump we must leave space for the longest code sequence
1672a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (jumpType == JumpNoConditionFixedSize)
1673a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return LinkBX;
1674a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (jumpType == JumpConditionFixedSize)
1675a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return LinkConditionalBX;
1676a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1677a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        const int paddingSize = JumpPaddingSizes[jumpType];
1678dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        bool mayTriggerErrata = false;
1679a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1680a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (jumpType == JumpCondition) {
1681a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // 2-byte conditional T1
1682a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT1]));
1683a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (canBeJumpT1(jumpT1Location, to))
1684a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                return LinkJumpT1;
1685a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // 4-byte conditional T3
1686a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT3]));
1687a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) {
1688a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                if (!mayTriggerErrata)
1689a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    return LinkJumpT3;
1690a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            }
1691a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // 4-byte conditional T4 with IT
1692a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const uint16_t* conditionalJumpT4Location =
1693a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkConditionalJumpT4]));
1694a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) {
1695a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                if (!mayTriggerErrata)
1696a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    return LinkConditionalJumpT4;
1697a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            }
1698a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        } else {
1699a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // 2-byte unconditional T2
1700a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT2]));
1701a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (canBeJumpT2(jumpT2Location, to))
1702a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                return LinkJumpT2;
1703a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // 4-byte unconditional T4
1704a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT4]));
1705a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) {
1706a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                if (!mayTriggerErrata)
1707a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    return LinkJumpT4;
1708a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            }
1709a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // use long jump sequence
1710a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return LinkBX;
1711dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        }
1712a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1713a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(jumpType == JumpCondition);
1714a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return LinkConditionalBX;
1715dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
1716a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1717a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
1718a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
1719a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        JumpLinkType linkType = computeJumpType(record.type(), from, to);
1720a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        record.setLinkType(linkType);
1721a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return linkType;
1722a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
1723a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1724dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
1725dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
1726dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        int32_t ptr = regionStart / sizeof(int32_t);
1727dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        const int32_t end = regionEnd / sizeof(int32_t);
1728dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        int32_t* offsets = static_cast<int32_t*>(m_formatter.data());
1729dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        while (ptr < end)
1730dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            offsets[ptr++] = offset;
1731dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
1732dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
1733dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Vector<LinkRecord>& jumpsToLink()
1734dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
1735dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
1736dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return m_jumpsToLink;
1737dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
1738dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
1739dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    void link(LinkRecord& record, uint8_t* from, uint8_t* to)
1740dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
1741a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        switch (record.linkType()) {
1742a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        case LinkJumpT1:
1743a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1744a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
1745a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        case LinkJumpT2:
1746a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            linkJumpT2(reinterpret_cast<uint16_t*>(from), to);
1747a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
1748a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        case LinkJumpT3:
1749a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1750a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
1751a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        case LinkJumpT4:
1752a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            linkJumpT4(reinterpret_cast<uint16_t*>(from), to);
1753a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
1754a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        case LinkConditionalJumpT4:
1755a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1756a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
1757a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        case LinkConditionalBX:
1758a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1759a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
1760a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        case LinkBX:
1761a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            linkBX(reinterpret_cast<uint16_t*>(from), to);
1762a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
1763a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        default:
1764a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT_NOT_REACHED();
1765a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
1766dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        }
17675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
17685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1769dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    void* unlinkedCode() { return m_formatter.data(); }
1770dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
17715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static unsigned getCallReturnOffset(JmpSrc call)
17725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
17735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(call.m_offset >= 0);
17745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return call.m_offset;
17755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
17765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
17775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Linking & patching:
17785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //
17795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // 'link' and 'patch' methods are for use on unprotected code - such as the code
17805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
17815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // code has been finalized it is (platform support permitting) within a non-
17825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // writable region of memory; to modify the code in an execute-only execuable
17835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // pool the 'repatch' and 'relink' methods should be used.
17845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
17855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    void linkJump(JmpSrc from, JmpDst to)
17865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
17875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(to.m_offset != -1);
17885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(from.m_offset != -1);
1789dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, from.m_type, from.m_condition));
17905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
17915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
17925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static void linkJump(void* code, JmpSrc from, void* to)
17935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
17945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(from.m_offset != -1);
17955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
17965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
1797cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        linkJumpAbsolute(location, to);
17985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
17995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // bah, this mathod should really be static, since it is used by the LinkBuffer.
18015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // return a bool saying whether the link was successful?
18025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static void linkCall(void* code, JmpSrc from, void* to)
18035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
18045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
18055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(from.m_offset != -1);
18065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(reinterpret_cast<intptr_t>(to) & 1);
18075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
18095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
18105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static void linkPointer(void* code, JmpDst where, void* value)
18125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
18130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
18145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
18155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static void relinkJump(void* from, void* to)
18175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
18185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
18195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
18205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1821cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
18220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1823cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
18245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
18255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static void relinkCall(void* from, void* to)
18275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
18285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
18295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(reinterpret_cast<intptr_t>(to) & 1);
18305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
18325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
18335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static void repatchInt32(void* where, int32_t value)
18355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
18365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
18375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        setInt32(where, value);
18395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
18405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static void repatchPointer(void* where, void* value)
18425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
18435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
18445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        setPointer(where, value);
18465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
18475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
18485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianprivate:
1849ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // VFP operations commonly take one or more 5-bit operands, typically representing a
1850ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // floating point register number.  This will commonly be encoded in the instruction
1851ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // in two parts, with one single bit field, and one 4-bit field.  In the case of
1852ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // double precision operands the high bit of the register number will be encoded
1853ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // separately, and for single precision operands the high bit of the register number
1854ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // will be encoded individually.
1855ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit
1856ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // field to be encoded together in the instruction (the low 4-bits of a double
1857ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // register number, or the high 4-bits of a single register number), and bit 4
1858ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    // contains the bit value to be encoded individually.
1859ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    struct VFPOperand {
1860ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        explicit VFPOperand(uint32_t value)
1861ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            : m_value(value)
1862ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        {
1863ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            ASSERT(!(m_value & ~0x1f));
1864ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        }
18655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1866ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        VFPOperand(FPDoubleRegisterID reg)
1867ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            : m_value(reg)
1868ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        {
1869ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        }
1870ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
1871ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        VFPOperand(RegisterID reg)
1872ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            : m_value(reg)
1873ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        {
18745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
18755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1876ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        VFPOperand(FPSingleRegisterID reg)
1877ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top.
1878ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        {
1879ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        }
1880ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
1881ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        uint32_t bits1()
1882ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        {
1883ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            return m_value >> 4;
1884ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        }
18855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1886ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        uint32_t bits4()
1887ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        {
1888ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            return m_value & 0xf;
1889ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        }
1890ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
1891ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        uint32_t m_value;
1892ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    };
1893ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
1894ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero)
1895ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    {
1896ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        // Cannot specify rounding when converting to float.
1897ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        ASSERT(toInteger || !isRoundZero);
1898ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
1899ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        uint32_t op = 0x8;
1900ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        if (toInteger) {
1901ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            // opc2 indicates both toInteger & isUnsigned.
1902ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            op |= isUnsigned ? 0x4 : 0x5;
1903ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            // 'op' field in instruction is isRoundZero
1904ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            if (isRoundZero)
1905ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                op |= 0x10;
1906ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        } else {
1907ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            // 'op' field in instruction is isUnsigned
1908ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            if (!isUnsigned)
1909ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                op |= 0x10;
1910ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        }
1911ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        return VFPOperand(op);
19125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
19135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
19140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static void setInt32(void* code, uint32_t value)
19155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
19165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        uint16_t* location = reinterpret_cast<uint16_t*>(code);
1917cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
19185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1919cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
1920cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
1921cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
1922cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
1923cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
1924cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
19250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
19260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
19275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
19285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
19290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    static void setPointer(void* code, void* value)
19305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
19310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        setInt32(code, reinterpret_cast<uint32_t>(value));
19325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
19335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1934cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    static bool isB(void* address)
1935cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
1936cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        uint16_t* instruction = static_cast<uint16_t*>(address);
1937cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
1938cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
1939cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1940cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    static bool isBX(void* address)
1941cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
1942cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        uint16_t* instruction = static_cast<uint16_t*>(address);
1943cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return (instruction[0] & 0xff87) == OP_BX;
1944cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
19455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1946cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    static bool isMOV_imm_T3(void* address)
1947cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
1948cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        uint16_t* instruction = static_cast<uint16_t*>(address);
1949cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
1950cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
19515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1952cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    static bool isMOVT(void* address)
1953cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
1954cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        uint16_t* instruction = static_cast<uint16_t*>(address);
1955cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
1956cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
19575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1958cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    static bool isNOP_T1(void* address)
1959cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
1960cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        uint16_t* instruction = static_cast<uint16_t*>(address);
1961cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return instruction[0] == OP_NOP_T1;
19625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
19635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1964cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    static bool isNOP_T2(void* address)
19655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
1966cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        uint16_t* instruction = static_cast<uint16_t*>(address);
1967cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
19685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
1969cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1970a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static bool canBeJumpT1(const uint16_t* instruction, const void* target)
1971a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
1972a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1973a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1974a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1975a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1976a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // It does not appear to be documented in the ARM ARM (big surprise), but
1977a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // for OP_B_T1 the branch displacement encoded in the instruction is 2
1978a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // less than the actual displacement.
1979a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        relative -= 2;
1980a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return ((relative << 23) >> 23) == relative;
1981a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
1982a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1983a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static bool canBeJumpT2(const uint16_t* instruction, const void* target)
1984a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
1985a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1986a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1987a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1988a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1989a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // It does not appear to be documented in the ARM ARM (big surprise), but
1990a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // for OP_B_T2 the branch displacement encoded in the instruction is 2
1991a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // less than the actual displacement.
1992a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        relative -= 2;
1993a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return ((relative << 20) >> 20) == relative;
1994a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
1995a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1996a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static bool canBeJumpT3(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
1997a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
1998a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1999a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2000a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2001a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2002a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // From Cortex-A8 errata:
2003a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
2004a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // the target of the branch falls within the first region it is
2005a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // possible for the processor to incorrectly determine the branch
2006a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // instruction, and it is also possible in some cases for the processor
2007a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // to enter a deadlock state.
2008a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // The instruction is spanning two pages if it ends at an address ending 0x002
2009a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
2010a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        mayTriggerErrata = spansTwo4K;
2011a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // The target is in the first page if the jump branch back by [3..0x1002] bytes
2012a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
2013a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
2014a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return ((relative << 11) >> 11) == relative && !wouldTriggerA8Errata;
2015a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
2016a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2017a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static bool canBeJumpT4(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
20185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    {
2019cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2020cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2021dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
2022cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
20236c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        // From Cortex-A8 errata:
20246c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
20256c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        // the target of the branch falls within the first region it is
20266c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        // possible for the processor to incorrectly determine the branch
20276c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        // instruction, and it is also possible in some cases for the processor
20286c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        // to enter a deadlock state.
20296c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        // The instruction is spanning two pages if it ends at an address ending 0x002
20306c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
2031dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        mayTriggerErrata = spansTwo4K;
20326c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        // The target is in the first page if the jump branch back by [3..0x1002] bytes
20336c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
20346c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
2035dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata;
2036dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
2037a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2038a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    void linkJumpT1(Condition cond, uint16_t* instruction, void* target)
2039dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
2040a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // FIMXE: this should be up in the MacroAssembler layer. :-(
2041a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2042a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2043a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(canBeJumpT1(instruction, target));
2044a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2045a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2046a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // It does not appear to be documented in the ARM ARM (big surprise), but
2047a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // for OP_B_T1 the branch displacement encoded in the instruction is 2
2048a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // less than the actual displacement.
2049a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        relative -= 2;
2050a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2051a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // All branch offsets should be an even distance.
2052a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(relative & 1));
2053a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1);
2054dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
2055dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
2056a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static void linkJumpT2(uint16_t* instruction, void* target)
2057dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
2058dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        // FIMXE: this should be up in the MacroAssembler layer. :-(
2059dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2060dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2061a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(canBeJumpT2(instruction, target));
2062dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
2063dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2064a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // It does not appear to be documented in the ARM ARM (big surprise), but
2065a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // for OP_B_T2 the branch displacement encoded in the instruction is 2
2066a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // less than the actual displacement.
2067a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        relative -= 2;
2068a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2069a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // All branch offsets should be an even distance.
2070a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(relative & 1));
2071a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1);
2072a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
2073a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2074a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    void linkJumpT3(Condition cond, uint16_t* instruction, void* target)
2075a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
2076a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // FIMXE: this should be up in the MacroAssembler layer. :-(
2077a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2078a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2079dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        bool scratch;
2080dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        UNUSED_PARAM(scratch);
2081a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(canBeJumpT3(instruction, target, scratch));
2082a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2083a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2084a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2085a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // All branch offsets should be an even distance.
2086a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(relative & 1));
2087a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12);
2088a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1);
2089a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
2090a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2091a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static void linkJumpT4(uint16_t* instruction, void* target)
2092a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
2093a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // FIMXE: this should be up in the MacroAssembler layer. :-(
2094a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2095a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2096a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        bool scratch;
2097a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        UNUSED_PARAM(scratch);
2098a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(canBeJumpT4(instruction, target, scratch));
2099a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2101dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        // ARM encoding for the top two bits below the sign bit is 'peculiar'.
2102dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        if (relative >= 0)
2103dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            relative ^= 0xC00000;
2104a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2105dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        // All branch offsets should be an even distance.
2106dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        ASSERT(!(relative & 1));
2107dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
2108dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
2109dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    }
2110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2111a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target)
2112a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
2113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // FIMXE: this should be up in the MacroAssembler layer. :-(
2114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-3] = ifThenElse(cond) | OP_IT;
2118a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        linkJumpT4(instruction, target);
2119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
2120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    static void linkBX(uint16_t* instruction, void* target)
2122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
2123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // FIMXE: this should be up in the MacroAssembler layer. :-(
2124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
2136a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2137a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
2138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    {
2139a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // FIMXE: this should be up in the MacroAssembler layer. :-(
2140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2141a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2143a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        linkBX(instruction, target);
2144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        instruction[-6] = ifThenElse(cond, true, true) | OP_IT;
2145a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
2146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2147dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    static void linkJumpAbsolute(uint16_t* instruction, void* target)
2148dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    {
2149dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        // FIMXE: this should be up in the MacroAssembler layer. :-(
2150dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2151dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2152a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2153dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
2154a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch               || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
2155a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2156dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        bool scratch;
2157a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (canBeJumpT4(instruction, target, scratch)) {
2158cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            // There may be a better way to fix this, but right now put the NOPs first, since in the
2159cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            // case of an conditional branch this will be coming after an ITTT predicating *three*
2160cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
2161cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            // variable wdith encoding - the previous instruction might *look* like an ITTT but
2162cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            // actually be the second half of a 2-word op.
2163cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            instruction[-5] = OP_NOP_T1;
2164cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            instruction[-4] = OP_NOP_T2a;
2165cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            instruction[-3] = OP_NOP_T2b;
2166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            linkJumpT4(instruction, target);
2167cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        } else {
2168dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2169cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2170cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2171cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2172cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2173cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2174cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2175cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2176cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
2177cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
2178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2179cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
2180cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
2181cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return op | (imm.m_value.i << 10) | imm.m_value.imm4;
2182cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
2183dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
2184cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
2185cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
2186cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
21875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
21885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
21895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    class ARMInstructionFormatter {
21905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    public:
21915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
21925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
21935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | (rd << 8) | imm);
21945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
21955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
21965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
21975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
21985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
21995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
22025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
22045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
22075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | imm);
22095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
22125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
22145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
22165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | imm);
22185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
22215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | (reg1 << 3) | reg2);
22235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
22265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | reg);
22285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(ff.m_u.value);
22295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
22325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op);
22345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(ff.m_u.value);
22355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
22385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op1);
22405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op2);
22415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
22445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
2245cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            ARMThumbImmediate newImm = imm;
2246cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            newImm.m_value.imm4 = imm4;
2247cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
2248cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
2249cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
22505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
22535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
22545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort(op | reg1);
22555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            m_buffer.putShort((reg2 << 12) | imm);
22565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2258ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        // Formats up instructions of the pattern:
2259ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        //    111111111B11aaaa:bbbb222SA2C2cccc
2260ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
2261ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
2262ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
22635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        {
2264ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            ASSERT(!(op1 & 0x004f));
2265ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            ASSERT(!(op2 & 0xf1af));
2266ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4());
2267ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4());
22685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
22695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2270ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
2271ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        // (i.e. +/-(0..255) 32-bit words)
2272ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
2273ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        {
2274ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            bool up = true;
2275ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            if (imm < 0) {
2276ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                imm = -imm;
2277ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block                up = false;
2278ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            }
2279ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
2280ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            uint32_t offset = imm;
2281ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            ASSERT(!(offset & ~0x3fc));
2282ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            offset >>= 2;
2283ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
2284ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn);
2285ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block            m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset);
2286ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        }
22875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Administrative methods:
22895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        size_t size() const { return m_buffer.size(); }
22915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
22925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void* data() const { return m_buffer.data(); }
22935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
22945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
22952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#ifndef NDEBUG
22962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        unsigned debugOffset() { return m_formatter.debugOffset(); }
22972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif
22982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
22995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    private:
23005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        AssemblerBuffer m_buffer;
23015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    } m_formatter;
2302cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
2303cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    Vector<LinkRecord> m_jumpsToLink;
2304dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    Vector<int32_t> m_offsets;
23055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian};
23065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
23075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} // namespace JSC
23085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2309d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
23105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
23115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#endif // ARMAssembler_h
2312