91e73af28a7b131138c96c87e68781c7ac0938d4
[WebKit-https.git] / Source / JavaScriptCore / assembler / ARMv7Assembler.h
1 /*
2  * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 University of Szeged
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #pragma once
28
29 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
30
31 #include "AssemblerBuffer.h"
32 #include "AssemblerCommon.h"
33 #include "RegisterInfo.h"
34 #include <limits.h>
35 #include <wtf/Assertions.h>
36 #include <wtf/Vector.h>
37 #include <stdint.h>
38
39 namespace JSC {
40
41 namespace RegisterNames {
42
43     typedef enum : int8_t {
44 #define REGISTER_ID(id, name, r, cs) id,
45         FOR_EACH_GP_REGISTER(REGISTER_ID)
46 #undef REGISTER_ID
47
48 #define REGISTER_ALIAS(id, name, alias) id = alias,
49         FOR_EACH_REGISTER_ALIAS(REGISTER_ALIAS)
50 #undef REGISTER_ALIAS
51         InvalidGPRReg = -1,
52     } RegisterID;
53
54     typedef enum : int8_t {
55 #define REGISTER_ID(id, name) id,
56         FOR_EACH_SP_REGISTER(REGISTER_ID)
57 #undef REGISTER_ID
58     } SPRegisterID;
59
60     typedef enum : int8_t {
61 #define REGISTER_ID(id, name, r, cs) id,
62         FOR_EACH_FP_SINGLE_REGISTER(REGISTER_ID)
63 #undef REGISTER_ID
64     } FPSingleRegisterID;
65
66     typedef enum : int8_t {
67 #define REGISTER_ID(id, name, r, cs) id,
68         FOR_EACH_FP_DOUBLE_REGISTER(REGISTER_ID)
69 #undef REGISTER_ID
70         InvalidFPRReg = -1,
71     } FPDoubleRegisterID;
72
73 #if CPU(ARM_NEON)
74     typedef enum : int8_t {
75 #define REGISTER_ID(id, name, r, cs) id,
76         FOR_EACH_FP_QUAD_REGISTER(REGISTER_ID)
77 #undef REGISTER_ID
78     } FPQuadRegisterID;
79 #endif // CPU(ARM_NEON)
80
81     inline FPSingleRegisterID asSingle(FPDoubleRegisterID reg)
82     {
83         ASSERT(reg < d16);
84         return (FPSingleRegisterID)(reg << 1);
85     }
86
87     inline FPSingleRegisterID asSingleUpper(FPDoubleRegisterID reg)
88     {
89         ASSERT(reg < d16);
90         return (FPSingleRegisterID)((reg << 1) + 1);
91     }
92
93     inline FPDoubleRegisterID asDouble(FPSingleRegisterID reg)
94     {
95         ASSERT(!(reg & 1));
96         return (FPDoubleRegisterID)(reg >> 1);
97     }
98
99 } // namespace ARMRegisters
100
101 class ARMv7Assembler;
102 class ARMThumbImmediate {
103     friend class ARMv7Assembler;
104
105     typedef uint8_t ThumbImmediateType;
106     static const ThumbImmediateType TypeInvalid = 0;
107     static const ThumbImmediateType TypeEncoded = 1;
108     static const ThumbImmediateType TypeUInt16 = 2;
109
110     typedef union {
111         int16_t asInt;
112         struct {
113             unsigned imm8 : 8;
114             unsigned imm3 : 3;
115             unsigned i    : 1;
116             unsigned imm4 : 4;
117         };
118         // If this is an encoded immediate, then it may describe a shift, or a pattern.
119         struct {
120             unsigned shiftValue7 : 7;
121             unsigned shiftAmount : 5;
122         };
123         struct {
124             unsigned immediate   : 8;
125             unsigned pattern     : 4;
126         };
127     } ThumbImmediateValue;
128
129     // byte0 contains least significant bit; not using an array to make client code endian agnostic.
130     typedef union {
131         int32_t asInt;
132         struct {
133             uint8_t byte0;
134             uint8_t byte1;
135             uint8_t byte2;
136             uint8_t byte3;
137         };
138     } PatternBytes;
139
140     ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
141     {
142         if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
143             value >>= N;             /* if any were set, lose the bottom N */
144         else                         /* if none of the top N bits are set, */
145             zeros += N;              /* then we have identified N leading zeros */
146     }
147
148     static int32_t countLeadingZeros(uint32_t value)
149     {
150         if (!value)
151             return 32;
152
153         int32_t zeros = 0;
154         countLeadingZerosPartial(value, zeros, 16);
155         countLeadingZerosPartial(value, zeros, 8);
156         countLeadingZerosPartial(value, zeros, 4);
157         countLeadingZerosPartial(value, zeros, 2);
158         countLeadingZerosPartial(value, zeros, 1);
159         return zeros;
160     }
161
162     ARMThumbImmediate()
163         : m_type(TypeInvalid)
164     {
165         m_value.asInt = 0;
166     }
167         
168     ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
169         : m_type(type)
170         , m_value(value)
171     {
172     }
173
174     ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
175         : m_type(TypeUInt16)
176     {
177         // Make sure this constructor is only reached with type TypeUInt16;
178         // this extra parameter makes the code a little clearer by making it
179         // explicit at call sites which type is being constructed
180         ASSERT_UNUSED(type, type == TypeUInt16);
181
182         m_value.asInt = value;
183     }
184
185 public:
186     static ARMThumbImmediate makeEncodedImm(uint32_t value)
187     {
188         ThumbImmediateValue encoding;
189         encoding.asInt = 0;
190
191         // okay, these are easy.
192         if (value < 256) {
193             encoding.immediate = value;
194             encoding.pattern = 0;
195             return ARMThumbImmediate(TypeEncoded, encoding);
196         }
197
198         int32_t leadingZeros = countLeadingZeros(value);
199         // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
200         ASSERT(leadingZeros < 24);
201
202         // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
203         // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
204         // zero.  count(B) == 8, so the count of bits to be checked is 24 - count(Z).
205         int32_t rightShiftAmount = 24 - leadingZeros;
206         if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
207             // Shift the value down to the low byte position.  The assign to 
208             // shiftValue7 drops the implicit top bit.
209             encoding.shiftValue7 = value >> rightShiftAmount;
210             // The endoded shift amount is the magnitude of a right rotate.
211             encoding.shiftAmount = 8 + leadingZeros;
212             return ARMThumbImmediate(TypeEncoded, encoding);
213         }
214         
215         PatternBytes bytes;
216         bytes.asInt = value;
217
218         if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
219             encoding.immediate = bytes.byte0;
220             encoding.pattern = 3;
221             return ARMThumbImmediate(TypeEncoded, encoding);
222         }
223
224         if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
225             encoding.immediate = bytes.byte0;
226             encoding.pattern = 1;
227             return ARMThumbImmediate(TypeEncoded, encoding);
228         }
229
230         if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
231             encoding.immediate = bytes.byte1;
232             encoding.pattern = 2;
233             return ARMThumbImmediate(TypeEncoded, encoding);
234         }
235
236         return ARMThumbImmediate();
237     }
238
239     static ARMThumbImmediate makeUInt12(int32_t value)
240     {
241         return (!(value & 0xfffff000))
242             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
243             : ARMThumbImmediate();
244     }
245
246     static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
247     {
248         // If this is not a 12-bit unsigned it, try making an encoded immediate.
249         return (!(value & 0xfffff000))
250             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
251             : makeEncodedImm(value);
252     }
253
254     // The 'make' methods, above, return a !isValid() value if the argument
255     // cannot be represented as the requested type.  This methods  is called
256     // 'get' since the argument can always be represented.
257     static ARMThumbImmediate makeUInt16(uint16_t value)
258     {
259         return ARMThumbImmediate(TypeUInt16, value);
260     }
261     
262     bool isValid()
263     {
264         return m_type != TypeInvalid;
265     }
266
267     uint16_t asUInt16() const { return m_value.asInt; }
268
269     // These methods rely on the format of encoded byte values.
270     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
271     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
272     bool isUInt5() { return !(m_value.asInt & 0xffe0); }
273     bool isUInt6() { return !(m_value.asInt & 0xffc0); }
274     bool isUInt7() { return !(m_value.asInt & 0xff80); }
275     bool isUInt8() { return !(m_value.asInt & 0xff00); }
276     bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
277     bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
278     bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
279     bool isUInt16() { return m_type == TypeUInt16; }
280     uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
281     uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
282     uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
283     uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
284     uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
285     uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
286     uint16_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
287     uint16_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
288     uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
289     uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
290
291     bool isEncodedImm() { return m_type == TypeEncoded; }
292
293 private:
294     ThumbImmediateType m_type;
295     ThumbImmediateValue m_value;
296 };
297
298 typedef enum {
299     SRType_LSL,
300     SRType_LSR,
301     SRType_ASR,
302     SRType_ROR,
303
304     SRType_RRX = SRType_ROR
305 } ARMShiftType;
306
307 class ShiftTypeAndAmount {
308     friend class ARMv7Assembler;
309
310 public:
311     ShiftTypeAndAmount()
312     {
313         m_u.type = (ARMShiftType)0;
314         m_u.amount = 0;
315     }
316     
317     ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
318     {
319         m_u.type = type;
320         m_u.amount = amount & 31;
321     }
322     
323     unsigned lo4() { return m_u.lo4; }
324     unsigned hi4() { return m_u.hi4; }
325     
326 private:
327     union {
328         struct {
329             unsigned lo4 : 4;
330             unsigned hi4 : 4;
331         };
332         struct {
333             unsigned type   : 2;
334             unsigned amount : 6;
335         };
336     } m_u;
337 };
338
339 class ARMv7Assembler {
340 public:
341     typedef ARMRegisters::RegisterID RegisterID;
342     typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
343     typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
344 #if CPU(ARM_NEON)
345     typedef ARMRegisters::FPQuadRegisterID FPQuadRegisterID;
346 #endif
347     typedef ARMRegisters::SPRegisterID SPRegisterID;
348     typedef FPDoubleRegisterID FPRegisterID;
349     
350     static constexpr RegisterID firstRegister() { return ARMRegisters::r0; }
351     static constexpr RegisterID lastRegister() { return ARMRegisters::r15; }
352     static constexpr unsigned numberOfRegisters() { return lastRegister() - firstRegister() + 1; }
353
354     static constexpr SPRegisterID firstSPRegister() { return ARMRegisters::apsr; }
355     static constexpr SPRegisterID lastSPRegister() { return ARMRegisters::fpscr; }
356     static constexpr unsigned numberOfSPRegisters() { return lastSPRegister() - firstSPRegister() + 1; }
357
358     static constexpr FPRegisterID firstFPRegister() { return ARMRegisters::d0; }
359 #if CPU(ARM_NEON) || CPU(ARM_VFP_V3_D32)
360     static constexpr FPRegisterID lastFPRegister() { return ARMRegisters::d31; }
361 #else
362     static constexpr FPRegisterID lastFPRegister() { return ARMRegisters::d15; }
363 #endif
364     static constexpr unsigned numberOfFPRegisters() { return lastFPRegister() - firstFPRegister() + 1; }
365
366     static const char* gprName(RegisterID id)
367     {
368         ASSERT(id >= firstRegister() && id <= lastRegister());
369         static const char* const nameForRegister[numberOfRegisters()] = {
370 #define REGISTER_NAME(id, name, r, cs) name,
371         FOR_EACH_GP_REGISTER(REGISTER_NAME)
372 #undef REGISTER_NAME        
373         };
374         return nameForRegister[id];
375     }
376
377     static const char* sprName(SPRegisterID id)
378     {
379         ASSERT(id >= firstSPRegister() && id <= lastSPRegister());
380         static const char* const nameForRegister[numberOfSPRegisters()] = {
381 #define REGISTER_NAME(id, name) name,
382         FOR_EACH_SP_REGISTER(REGISTER_NAME)
383 #undef REGISTER_NAME
384         };
385         return nameForRegister[id];
386     }
387
388     static const char* fprName(FPRegisterID id)
389     {
390         ASSERT(id >= firstFPRegister() && id <= lastFPRegister());
391         static const char* const nameForRegister[numberOfFPRegisters()] = {
392 #define REGISTER_NAME(id, name, r, cs) name,
393         FOR_EACH_FP_DOUBLE_REGISTER(REGISTER_NAME)
394 #undef REGISTER_NAME
395         };
396         return nameForRegister[id];
397     }
398
399     // (HS, LO, HI, LS) -> (AE, B, A, BE)
400     // (VS, VC) -> (O, NO)
401     typedef enum {
402         ConditionEQ, // Zero / Equal.
403         ConditionNE, // Non-zero / Not equal.
404         ConditionHS, ConditionCS = ConditionHS, // Unsigned higher or same.
405         ConditionLO, ConditionCC = ConditionLO, // Unsigned lower.
406         ConditionMI, // Negative.
407         ConditionPL, // Positive or zero.
408         ConditionVS, // Overflowed.
409         ConditionVC, // Not overflowed.
410         ConditionHI, // Unsigned higher.
411         ConditionLS, // Unsigned lower or same.
412         ConditionGE, // Signed greater than or equal.
413         ConditionLT, // Signed less than.
414         ConditionGT, // Signed greater than.
415         ConditionLE, // Signed less than or equal.
416         ConditionAL, // Unconditional / Always execute.
417         ConditionInvalid
418     } Condition;
419
420 #define JUMP_ENUM_WITH_SIZE(index, value) (((value) << 3) | (index))
421 #define JUMP_ENUM_SIZE(jump) ((jump) >> 3) 
422     enum JumpType { JumpFixed = JUMP_ENUM_WITH_SIZE(0, 0), 
423                     JumpNoCondition = JUMP_ENUM_WITH_SIZE(1, 5 * sizeof(uint16_t)),
424                     JumpCondition = JUMP_ENUM_WITH_SIZE(2, 6 * sizeof(uint16_t)),
425                     JumpNoConditionFixedSize = JUMP_ENUM_WITH_SIZE(3, 5 * sizeof(uint16_t)),
426                     JumpConditionFixedSize = JUMP_ENUM_WITH_SIZE(4, 6 * sizeof(uint16_t))
427     };
428     enum JumpLinkType { 
429         LinkInvalid = JUMP_ENUM_WITH_SIZE(0, 0),
430         LinkJumpT1 = JUMP_ENUM_WITH_SIZE(1, sizeof(uint16_t)),
431         LinkJumpT2 = JUMP_ENUM_WITH_SIZE(2, sizeof(uint16_t)),
432         LinkJumpT3 = JUMP_ENUM_WITH_SIZE(3, 2 * sizeof(uint16_t)),
433         LinkJumpT4 = JUMP_ENUM_WITH_SIZE(4, 2 * sizeof(uint16_t)),
434         LinkConditionalJumpT4 = JUMP_ENUM_WITH_SIZE(5, 3 * sizeof(uint16_t)),
435         LinkBX = JUMP_ENUM_WITH_SIZE(6, 5 * sizeof(uint16_t)),
436         LinkConditionalBX = JUMP_ENUM_WITH_SIZE(7, 6 * sizeof(uint16_t))
437     };
438
439     class LinkRecord {
440     public:
441         LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
442         {
443             data.realTypes.m_from = from;
444             data.realTypes.m_to = to;
445             data.realTypes.m_type = type;
446             data.realTypes.m_linkType = LinkInvalid;
447             data.realTypes.m_condition = condition;
448         }
449         void operator=(const LinkRecord& other)
450         {
451             data.copyTypes.content[0] = other.data.copyTypes.content[0];
452             data.copyTypes.content[1] = other.data.copyTypes.content[1];
453             data.copyTypes.content[2] = other.data.copyTypes.content[2];
454         }
455         intptr_t from() const { return data.realTypes.m_from; }
456         void setFrom(intptr_t from) { data.realTypes.m_from = from; }
457         intptr_t to() const { return data.realTypes.m_to; }
458         JumpType type() const { return data.realTypes.m_type; }
459         JumpLinkType linkType() const { return data.realTypes.m_linkType; }
460         void setLinkType(JumpLinkType linkType) { ASSERT(data.realTypes.m_linkType == LinkInvalid); data.realTypes.m_linkType = linkType; }
461         Condition condition() const { return data.realTypes.m_condition; }
462     private:
463         union {
464             struct RealTypes {
465                 intptr_t m_from : 31;
466                 intptr_t m_to : 31;
467                 JumpType m_type : 8;
468                 JumpLinkType m_linkType : 8;
469                 Condition m_condition : 16;
470             } realTypes;
471             struct CopyTypes {
472                 uint32_t content[3];
473             } copyTypes;
474             COMPILE_ASSERT(sizeof(RealTypes) == sizeof(CopyTypes), LinkRecordCopyStructSizeEqualsRealStruct);
475         } data;
476     };
477
478     ARMv7Assembler()
479         : m_indexOfLastWatchpoint(INT_MIN)
480         , m_indexOfTailOfLastWatchpoint(INT_MIN)
481     {
482     }
483
484     AssemblerBuffer& buffer() { return m_formatter.m_buffer; }
485
486 private:
487
488     // ARMv7, Appx-A.6.3
489     static bool BadReg(RegisterID reg)
490     {
491         return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
492     }
493
494     uint32_t singleRegisterMask(FPSingleRegisterID rdNum, int highBitsShift, int lowBitShift)
495     {
496         uint32_t rdMask = (rdNum >> 1) << highBitsShift;
497         if (rdNum & 1)
498             rdMask |= 1 << lowBitShift;
499         return rdMask;
500     }
501
502     uint32_t doubleRegisterMask(FPDoubleRegisterID rdNum, int highBitShift, int lowBitsShift)
503     {
504         uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
505         if (rdNum & 16)
506             rdMask |= 1 << highBitShift;
507         return rdMask;
508     }
509
510     typedef enum {
511         OP_ADD_reg_T1       = 0x1800,
512         OP_SUB_reg_T1       = 0x1A00,
513         OP_ADD_imm_T1       = 0x1C00,
514         OP_SUB_imm_T1       = 0x1E00,
515         OP_MOV_imm_T1       = 0x2000,
516         OP_CMP_imm_T1       = 0x2800,
517         OP_ADD_imm_T2       = 0x3000,
518         OP_SUB_imm_T2       = 0x3800,
519         OP_AND_reg_T1       = 0x4000,
520         OP_EOR_reg_T1       = 0x4040,
521         OP_TST_reg_T1       = 0x4200,
522         OP_RSB_imm_T1       = 0x4240,
523         OP_CMP_reg_T1       = 0x4280,
524         OP_ORR_reg_T1       = 0x4300,
525         OP_MVN_reg_T1       = 0x43C0,
526         OP_ADD_reg_T2       = 0x4400,
527         OP_MOV_reg_T1       = 0x4600,
528         OP_BLX              = 0x4700,
529         OP_BX               = 0x4700,
530         OP_STR_reg_T1       = 0x5000,
531         OP_STRH_reg_T1      = 0x5200,
532         OP_STRB_reg_T1      = 0x5400,
533         OP_LDRSB_reg_T1     = 0x5600,
534         OP_LDR_reg_T1       = 0x5800,
535         OP_LDRH_reg_T1      = 0x5A00,
536         OP_LDRB_reg_T1      = 0x5C00,
537         OP_LDRSH_reg_T1     = 0x5E00,
538         OP_STR_imm_T1       = 0x6000,
539         OP_LDR_imm_T1       = 0x6800,
540         OP_STRB_imm_T1      = 0x7000,
541         OP_LDRB_imm_T1      = 0x7800,
542         OP_STRH_imm_T1      = 0x8000,
543         OP_LDRH_imm_T1      = 0x8800,
544         OP_STR_imm_T2       = 0x9000,
545         OP_LDR_imm_T2       = 0x9800,
546         OP_ADD_SP_imm_T1    = 0xA800,
547         OP_ADD_SP_imm_T2    = 0xB000,
548         OP_SUB_SP_imm_T1    = 0xB080,
549         OP_PUSH_T1          = 0xB400,
550         OP_POP_T1           = 0xBC00,
551         OP_BKPT             = 0xBE00,
552         OP_IT               = 0xBF00,
553         OP_NOP_T1           = 0xBF00,
554     } OpcodeID;
555
556     typedef enum {
557         OP_B_T1         = 0xD000,
558         OP_B_T2         = 0xE000,
559         OP_POP_T2       = 0xE8BD,
560         OP_PUSH_T2      = 0xE92D,
561         OP_AND_reg_T2   = 0xEA00,
562         OP_TST_reg_T2   = 0xEA10,
563         OP_ORR_reg_T2   = 0xEA40,
564         OP_ORR_S_reg_T2 = 0xEA50,
565         OP_ASR_imm_T1   = 0xEA4F,
566         OP_LSL_imm_T1   = 0xEA4F,
567         OP_LSR_imm_T1   = 0xEA4F,
568         OP_ROR_imm_T1   = 0xEA4F,
569         OP_MVN_reg_T2   = 0xEA6F,
570         OP_EOR_reg_T2   = 0xEA80,
571         OP_ADD_reg_T3   = 0xEB00,
572         OP_ADD_S_reg_T3 = 0xEB10,
573         OP_SUB_reg_T2   = 0xEBA0,
574         OP_SUB_S_reg_T2 = 0xEBB0,
575         OP_CMP_reg_T2   = 0xEBB0,
576         OP_VMOV_CtoD    = 0xEC00,
577         OP_VMOV_DtoC    = 0xEC10,
578         OP_FSTS         = 0xED00,
579         OP_VSTR         = 0xED00,
580         OP_FLDS         = 0xED10,
581         OP_VLDR         = 0xED10,
582         OP_VMOV_CtoS    = 0xEE00,
583         OP_VMOV_StoC    = 0xEE10,
584         OP_VMUL_T2      = 0xEE20,
585         OP_VADD_T2      = 0xEE30,
586         OP_VSUB_T2      = 0xEE30,
587         OP_VDIV         = 0xEE80,
588         OP_VABS_T2      = 0xEEB0,
589         OP_VCMP         = 0xEEB0,
590         OP_VCVT_FPIVFP  = 0xEEB0,
591         OP_VMOV_T2      = 0xEEB0,
592         OP_VMOV_IMM_T2  = 0xEEB0,
593         OP_VMRS         = 0xEEB0,
594         OP_VNEG_T2      = 0xEEB0,
595         OP_VSQRT_T1     = 0xEEB0,
596         OP_VCVTSD_T1    = 0xEEB0,
597         OP_VCVTDS_T1    = 0xEEB0,
598         OP_B_T3a        = 0xF000,
599         OP_B_T4a        = 0xF000,
600         OP_AND_imm_T1   = 0xF000,
601         OP_TST_imm      = 0xF010,
602         OP_ORR_imm_T1   = 0xF040,
603         OP_MOV_imm_T2   = 0xF040,
604         OP_MVN_imm      = 0xF060,
605         OP_EOR_imm_T1   = 0xF080,
606         OP_ADD_imm_T3   = 0xF100,
607         OP_ADD_S_imm_T3 = 0xF110,
608         OP_CMN_imm      = 0xF110,
609         OP_ADC_imm      = 0xF140,
610         OP_SUB_imm_T3   = 0xF1A0,
611         OP_SUB_S_imm_T3 = 0xF1B0,
612         OP_CMP_imm_T2   = 0xF1B0,
613         OP_RSB_imm_T2   = 0xF1C0,
614         OP_RSB_S_imm_T2 = 0xF1D0,
615         OP_ADD_imm_T4   = 0xF200,
616         OP_MOV_imm_T3   = 0xF240,
617         OP_SUB_imm_T4   = 0xF2A0,
618         OP_MOVT         = 0xF2C0,
619         OP_UBFX_T1      = 0xF3C0,
620         OP_NOP_T2a      = 0xF3AF,
621         OP_DMB_T1a      = 0xF3BF,
622         OP_STRB_imm_T3  = 0xF800,
623         OP_STRB_reg_T2  = 0xF800,
624         OP_LDRB_imm_T3  = 0xF810,
625         OP_LDRB_reg_T2  = 0xF810,
626         OP_STRH_imm_T3  = 0xF820,
627         OP_STRH_reg_T2  = 0xF820,
628         OP_LDRH_reg_T2  = 0xF830,
629         OP_LDRH_imm_T3  = 0xF830,
630         OP_STR_imm_T4   = 0xF840,
631         OP_STR_reg_T2   = 0xF840,
632         OP_LDR_imm_T4   = 0xF850,
633         OP_LDR_reg_T2   = 0xF850,
634         OP_STRB_imm_T2  = 0xF880,
635         OP_LDRB_imm_T2  = 0xF890,
636         OP_STRH_imm_T2  = 0xF8A0,
637         OP_LDRH_imm_T2  = 0xF8B0,
638         OP_STR_imm_T3   = 0xF8C0,
639         OP_LDR_imm_T3   = 0xF8D0,
640         OP_LDRSB_reg_T2 = 0xF910,
641         OP_LDRSH_reg_T2 = 0xF930,
642         OP_LSL_reg_T2   = 0xFA00,
643         OP_LSR_reg_T2   = 0xFA20,
644         OP_ASR_reg_T2   = 0xFA40,
645         OP_ROR_reg_T2   = 0xFA60,
646         OP_CLZ          = 0xFAB0,
647         OP_SMULL_T1     = 0xFB80,
648 #if HAVE(ARM_IDIV_INSTRUCTIONS)
649         OP_SDIV_T1      = 0xFB90,
650         OP_UDIV_T1      = 0xFBB0,
651 #endif
652         OP_MRS_T1       = 0xF3EF,
653     } OpcodeID1;
654
655     typedef enum {
656         OP_VADD_T2b      = 0x0A00,
657         OP_VDIVb         = 0x0A00,
658         OP_FLDSb         = 0x0A00,
659         OP_VLDRb         = 0x0A00,
660         OP_VMOV_IMM_T2b  = 0x0A00,
661         OP_VMOV_T2b      = 0x0A40,
662         OP_VMUL_T2b      = 0x0A00,
663         OP_FSTSb         = 0x0A00,
664         OP_VSTRb         = 0x0A00,
665         OP_VMOV_StoCb    = 0x0A10,
666         OP_VMOV_CtoSb    = 0x0A10,
667         OP_VMOV_DtoCb    = 0x0A10,
668         OP_VMOV_CtoDb    = 0x0A10,
669         OP_VMRSb         = 0x0A10,
670         OP_VABS_T2b      = 0x0A40,
671         OP_VCMPb         = 0x0A40,
672         OP_VCVT_FPIVFPb  = 0x0A40,
673         OP_VNEG_T2b      = 0x0A40,
674         OP_VSUB_T2b      = 0x0A40,
675         OP_VSQRT_T1b     = 0x0A40,
676         OP_VCVTSD_T1b    = 0x0A40,
677         OP_VCVTDS_T1b    = 0x0A40,
678         OP_NOP_T2b       = 0x8000,
679         OP_DMB_SY_T1b    = 0x8F5F,
680         OP_DMB_ISHST_T1b = 0x8F5A,
681         OP_B_T3b         = 0x8000,
682         OP_B_T4b         = 0x9000,
683     } OpcodeID2;
684
685     struct FourFours {
686         FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
687         {
688             m_u.f0 = f0;
689             m_u.f1 = f1;
690             m_u.f2 = f2;
691             m_u.f3 = f3;
692         }
693
694         union {
695             unsigned value;
696             struct {
697                 unsigned f0 : 4;
698                 unsigned f1 : 4;
699                 unsigned f2 : 4;
700                 unsigned f3 : 4;
701             };
702         } m_u;
703     };
704
705     class ARMInstructionFormatter;
706
707     // false means else!
708     static bool ifThenElseConditionBit(Condition condition, bool isIf)
709     {
710         return isIf ? (condition & 1) : !(condition & 1);
711     }
712     static uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
713     {
714         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
715             | (ifThenElseConditionBit(condition, inst3if) << 2)
716             | (ifThenElseConditionBit(condition, inst4if) << 1)
717             | 1;
718         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
719         return (condition << 4) | mask;
720     }
721     static uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
722     {
723         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
724             | (ifThenElseConditionBit(condition, inst3if) << 2)
725             | 2;
726         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
727         return (condition << 4) | mask;
728     }
729     static uint8_t ifThenElse(Condition condition, bool inst2if)
730     {
731         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
732             | 4;
733         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
734         return (condition << 4) | mask;
735     }
736
737     static uint8_t ifThenElse(Condition condition)
738     {
739         int mask = 8;
740         return (condition << 4) | mask;
741     }
742
743 public:
744     
745     void adc(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
746     {
747         // Rd can only be SP if Rn is also SP.
748         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
749         ASSERT(rd != ARMRegisters::pc);
750         ASSERT(rn != ARMRegisters::pc);
751         ASSERT(imm.isEncodedImm());
752
753         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADC_imm, rn, rd, imm);
754     }
755
756     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
757     {
758         // Rd can only be SP if Rn is also SP.
759         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
760         ASSERT(rd != ARMRegisters::pc);
761         ASSERT(rn != ARMRegisters::pc);
762         ASSERT(imm.isValid());
763
764         if (rn == ARMRegisters::sp && imm.isUInt16()) {
765             ASSERT(!(imm.getUInt16() & 3));
766             if (!(rd & 8) && imm.isUInt10()) {
767                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, static_cast<uint8_t>(imm.getUInt10() >> 2));
768                 return;
769             } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
770                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, static_cast<uint8_t>(imm.getUInt9() >> 2));
771                 return;
772             }
773         } else if (!((rd | rn) & 8)) {
774             if (imm.isUInt3()) {
775                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
776                 return;
777             } else if ((rd == rn) && imm.isUInt8()) {
778                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
779                 return;
780             }
781         }
782
783         if (imm.isEncodedImm())
784             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
785         else {
786             ASSERT(imm.isUInt12());
787             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
788         }
789     }
790
791     ALWAYS_INLINE void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
792     {
793         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
794         ASSERT(rd != ARMRegisters::pc);
795         ASSERT(rn != ARMRegisters::pc);
796         ASSERT(!BadReg(rm));
797         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
798     }
799
800     // NOTE: In an IT block, add doesn't modify the flags register.
801     ALWAYS_INLINE void add(RegisterID rd, RegisterID rn, RegisterID rm)
802     {
803         if (rd == ARMRegisters::sp) {
804             mov(rd, rn);
805             rn = rd;
806         }
807
808         if (rd == rn)
809             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
810         else if (rd == rm)
811             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
812         else if (!((rd | rn | rm) & 8))
813             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
814         else
815             add(rd, rn, rm, ShiftTypeAndAmount());
816     }
817
818     // Not allowed in an IT (if then) block.
819     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
820     {
821         // Rd can only be SP if Rn is also SP.
822         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
823         ASSERT(rd != ARMRegisters::pc);
824         ASSERT(rn != ARMRegisters::pc);
825         ASSERT(imm.isEncodedImm());
826
827         if (!((rd | rn) & 8)) {
828             if (imm.isUInt3()) {
829                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
830                 return;
831             } else if ((rd == rn) && imm.isUInt8()) {
832                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
833                 return;
834             }
835         }
836
837         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
838     }
839
840     // Not allowed in an IT (if then) block?
841     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
842     {
843         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
844         ASSERT(rd != ARMRegisters::pc);
845         ASSERT(rn != ARMRegisters::pc);
846         ASSERT(!BadReg(rm));
847         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
848     }
849
850     // Not allowed in an IT (if then) block.
851     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
852     {
853         if (!((rd | rn | rm) & 8))
854             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
855         else
856             add_S(rd, rn, rm, ShiftTypeAndAmount());
857     }
858
859     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
860     {
861         ASSERT(!BadReg(rd));
862         ASSERT(!BadReg(rn));
863         ASSERT(imm.isEncodedImm());
864         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
865     }
866
867     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
868     {
869         ASSERT(!BadReg(rd));
870         ASSERT(!BadReg(rn));
871         ASSERT(!BadReg(rm));
872         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
873     }
874
875     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
876     {
877         if ((rd == rn) && !((rd | rm) & 8))
878             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
879         else if ((rd == rm) && !((rd | rn) & 8))
880             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
881         else
882             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
883     }
884
885     ALWAYS_INLINE void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
886     {
887         ASSERT(!BadReg(rd));
888         ASSERT(!BadReg(rm));
889         ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
890         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
891     }
892
893     ALWAYS_INLINE void asr(RegisterID rd, RegisterID rn, RegisterID rm)
894     {
895         ASSERT(!BadReg(rd));
896         ASSERT(!BadReg(rn));
897         ASSERT(!BadReg(rm));
898         m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
899     }
900     
901     // Only allowed in IT (if then) block if last instruction.
902     ALWAYS_INLINE AssemblerLabel b()
903     {
904         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
905         return m_formatter.label();
906     }
907     
908     // Only allowed in IT (if then) block if last instruction.
909     ALWAYS_INLINE AssemblerLabel blx(RegisterID rm)
910     {
911         ASSERT(rm != ARMRegisters::pc);
912         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
913         return m_formatter.label();
914     }
915
916     // Only allowed in IT (if then) block if last instruction.
917     ALWAYS_INLINE AssemblerLabel bx(RegisterID rm)
918     {
919         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
920         return m_formatter.label();
921     }
922
923     void bkpt(uint8_t imm = 0)
924     {
925         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
926     }
927
928     static bool isBkpt(void* address)
929     {
930         unsigned short expected = OP_BKPT;
931         unsigned short immediateMask = 0xff;
932         unsigned short candidateInstruction = *reinterpret_cast<unsigned short*>(address);
933         return (candidateInstruction & ~immediateMask) == expected;
934     }
935
936     ALWAYS_INLINE void clz(RegisterID rd, RegisterID rm)
937     {
938         ASSERT(!BadReg(rd));
939         ASSERT(!BadReg(rm));
940         m_formatter.twoWordOp12Reg4FourFours(OP_CLZ, rm, FourFours(0xf, rd, 8, rm));
941     }
942
943     ALWAYS_INLINE void cmn(RegisterID rn, ARMThumbImmediate imm)
944     {
945         ASSERT(rn != ARMRegisters::pc);
946         ASSERT(imm.isEncodedImm());
947
948         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
949     }
950
951     ALWAYS_INLINE void cmp(RegisterID rn, ARMThumbImmediate imm)
952     {
953         ASSERT(rn != ARMRegisters::pc);
954         ASSERT(imm.isEncodedImm());
955
956         if (!(rn & 8) && imm.isUInt8())
957             m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
958         else
959             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
960     }
961
962     ALWAYS_INLINE void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
963     {
964         ASSERT(rn != ARMRegisters::pc);
965         ASSERT(!BadReg(rm));
966         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
967     }
968
969     ALWAYS_INLINE void cmp(RegisterID rn, RegisterID rm)
970     {
971         if ((rn | rm) & 8)
972             cmp(rn, rm, ShiftTypeAndAmount());
973         else
974             m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
975     }
976
977     // xor is not spelled with an 'e'. :-(
978     ALWAYS_INLINE void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
979     {
980         ASSERT(!BadReg(rd));
981         ASSERT(!BadReg(rn));
982         ASSERT(imm.isEncodedImm());
983         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
984     }
985
986     // xor is not spelled with an 'e'. :-(
987     ALWAYS_INLINE void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
988     {
989         ASSERT(!BadReg(rd));
990         ASSERT(!BadReg(rn));
991         ASSERT(!BadReg(rm));
992         m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
993     }
994
995     // xor is not spelled with an 'e'. :-(
996     void eor(RegisterID rd, RegisterID rn, RegisterID rm)
997     {
998         if ((rd == rn) && !((rd | rm) & 8))
999             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
1000         else if ((rd == rm) && !((rd | rn) & 8))
1001             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
1002         else
1003             eor(rd, rn, rm, ShiftTypeAndAmount());
1004     }
1005
1006     ALWAYS_INLINE void it(Condition cond)
1007     {
1008         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
1009     }
1010
1011     ALWAYS_INLINE void it(Condition cond, bool inst2if)
1012     {
1013         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
1014     }
1015
1016     ALWAYS_INLINE void it(Condition cond, bool inst2if, bool inst3if)
1017     {
1018         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
1019     }
1020
1021     ALWAYS_INLINE void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
1022     {
1023         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
1024     }
1025
1026     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1027     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1028     {
1029         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1030         ASSERT(imm.isUInt12());
1031
1032         if (!((rt | rn) & 8) && imm.isUInt7())
1033             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1034         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1035             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, static_cast<uint8_t>(imm.getUInt10() >> 2));
1036         else
1037             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
1038     }
1039     
1040     ALWAYS_INLINE void ldrWide8BitImmediate(RegisterID rt, RegisterID rn, uint8_t immediate)
1041     {
1042         ASSERT(rn != ARMRegisters::pc);
1043         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, immediate);
1044     }
1045
1046     ALWAYS_INLINE void ldrCompact(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1047     {
1048         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1049         ASSERT(imm.isUInt7());
1050         ASSERT(!((rt | rn) & 8));
1051         m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1052     }
1053
1054     // If index is set, this is a regular offset or a pre-indexed load;
1055     // if index is not set then is is a post-index load.
1056     //
1057     // If wback is set rn is updated - this is a pre or post index load,
1058     // if wback is not set this is a regular offset memory access.
1059     //
1060     // (-255 <= offset <= 255)
1061     // _reg = REG[rn]
1062     // _tmp = _reg + offset
1063     // MEM[index ? _tmp : _reg] = REG[rt]
1064     // if (wback) REG[rn] = _tmp
1065     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1066     {
1067         ASSERT(rt != ARMRegisters::pc);
1068         ASSERT(rn != ARMRegisters::pc);
1069         ASSERT(index || wback);
1070         ASSERT(!wback | (rt != rn));
1071     
1072         bool add = true;
1073         if (offset < 0) {
1074             add = false;
1075             offset = -offset;
1076         }
1077         ASSERT((offset & ~0xff) == 0);
1078         
1079         offset |= (wback << 8);
1080         offset |= (add   << 9);
1081         offset |= (index << 10);
1082         offset |= (1 << 11);
1083         
1084         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
1085     }
1086
1087     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1088     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1089     {
1090         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1091         ASSERT(!BadReg(rm));
1092         ASSERT(shift <= 3);
1093
1094         if (!shift && !((rt | rn | rm) & 8))
1095             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
1096         else
1097             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1098     }
1099
1100     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1101     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1102     {
1103         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1104         ASSERT(imm.isUInt12());
1105         ASSERT(!(imm.getUInt12() & 1));
1106
1107         if (!((rt | rn) & 8) && imm.isUInt6())
1108             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 1, rn, rt);
1109         else
1110             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
1111     }
1112
1113     // If index is set, this is a regular offset or a pre-indexed load;
1114     // if index is not set then is is a post-index load.
1115     //
1116     // If wback is set rn is updated - this is a pre or post index load,
1117     // if wback is not set this is a regular offset memory access.
1118     //
1119     // (-255 <= offset <= 255)
1120     // _reg = REG[rn]
1121     // _tmp = _reg + offset
1122     // MEM[index ? _tmp : _reg] = REG[rt]
1123     // if (wback) REG[rn] = _tmp
1124     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1125     {
1126         ASSERT(rt != ARMRegisters::pc);
1127         ASSERT(rn != ARMRegisters::pc);
1128         ASSERT(index || wback);
1129         ASSERT(!wback | (rt != rn));
1130     
1131         bool add = true;
1132         if (offset < 0) {
1133             add = false;
1134             offset = -offset;
1135         }
1136         ASSERT((offset & ~0xff) == 0);
1137         
1138         offset |= (wback << 8);
1139         offset |= (add   << 9);
1140         offset |= (index << 10);
1141         offset |= (1 << 11);
1142         
1143         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
1144     }
1145
1146     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1147     {
1148         ASSERT(!BadReg(rt));   // Memory hint
1149         ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
1150         ASSERT(!BadReg(rm));
1151         ASSERT(shift <= 3);
1152
1153         if (!shift && !((rt | rn | rm) & 8))
1154             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
1155         else
1156             m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1157     }
1158
1159     void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1160     {
1161         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1162         ASSERT(imm.isUInt12());
1163
1164         if (!((rt | rn) & 8) && imm.isUInt5())
1165             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
1166         else
1167             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
1168     }
1169
1170     void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1171     {
1172         ASSERT(rt != ARMRegisters::pc);
1173         ASSERT(rn != ARMRegisters::pc);
1174         ASSERT(index || wback);
1175         ASSERT(!wback | (rt != rn));
1176
1177         bool add = true;
1178         if (offset < 0) {
1179             add = false;
1180             offset = -offset;
1181         }
1182
1183         ASSERT(!(offset & ~0xff));
1184
1185         offset |= (wback << 8);
1186         offset |= (add   << 9);
1187         offset |= (index << 10);
1188         offset |= (1 << 11);
1189
1190         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
1191     }
1192
1193     ALWAYS_INLINE void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1194     {
1195         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1196         ASSERT(!BadReg(rm));
1197         ASSERT(shift <= 3);
1198
1199         if (!shift && !((rt | rn | rm) & 8))
1200             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
1201         else
1202             m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1203     }
1204     
1205     void ldrsb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1206     {
1207         ASSERT(rn != ARMRegisters::pc);
1208         ASSERT(!BadReg(rm));
1209         ASSERT(shift <= 3);
1210         
1211         if (!shift && !((rt | rn | rm) & 8))
1212             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSB_reg_T1, rm, rn, rt);
1213         else
1214             m_formatter.twoWordOp12Reg4FourFours(OP_LDRSB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1215     }
1216
1217     void ldrsh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1218     {
1219         ASSERT(rn != ARMRegisters::pc);
1220         ASSERT(!BadReg(rm));
1221         ASSERT(shift <= 3);
1222         
1223         if (!shift && !((rt | rn | rm) & 8))
1224             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSH_reg_T1, rm, rn, rt);
1225         else
1226             m_formatter.twoWordOp12Reg4FourFours(OP_LDRSH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1227     }
1228
1229     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1230     {
1231         ASSERT(!BadReg(rd));
1232         ASSERT(!BadReg(rm));
1233         ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
1234         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1235     }
1236
1237     ALWAYS_INLINE void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
1238     {
1239         ASSERT(!BadReg(rd));
1240         ASSERT(!BadReg(rn));
1241         ASSERT(!BadReg(rm));
1242         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1243     }
1244
1245     ALWAYS_INLINE void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1246     {
1247         ASSERT(!BadReg(rd));
1248         ASSERT(!BadReg(rm));
1249         ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
1250         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1251     }
1252
1253     ALWAYS_INLINE void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
1254     {
1255         ASSERT(!BadReg(rd));
1256         ASSERT(!BadReg(rn));
1257         ASSERT(!BadReg(rm));
1258         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1259     }
1260
1261     ALWAYS_INLINE void movT3(RegisterID rd, ARMThumbImmediate imm)
1262     {
1263         ASSERT(imm.isValid());
1264         ASSERT(!imm.isEncodedImm());
1265         ASSERT(!BadReg(rd));
1266         
1267         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
1268     }
1269     
1270 #if OS(LINUX)
1271     static void revertJumpTo_movT3movtcmpT2(void* instructionStart, RegisterID left, RegisterID right, uintptr_t imm)
1272     {
1273         uint16_t* address = static_cast<uint16_t*>(instructionStart);
1274         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(imm));
1275         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(imm >> 16));
1276         uint16_t instruction[] = {
1277             twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16),
1278             twoWordOp5i6Imm4Reg4EncodedImmSecond(right, lo16),
1279             twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16),
1280             twoWordOp5i6Imm4Reg4EncodedImmSecond(right, hi16),
1281             static_cast<uint16_t>(OP_CMP_reg_T2 | left)
1282         };
1283         performJITMemcpy(address, instruction, sizeof(uint16_t) * 5);
1284         cacheFlush(address, sizeof(uint16_t) * 5);
1285     }
1286 #else
1287     static void revertJumpTo_movT3(void* instructionStart, RegisterID rd, ARMThumbImmediate imm)
1288     {
1289         ASSERT(imm.isValid());
1290         ASSERT(!imm.isEncodedImm());
1291         ASSERT(!BadReg(rd));
1292         
1293         uint16_t* address = static_cast<uint16_t*>(instructionStart);
1294         uint16_t instruction[] = {
1295             twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, imm),
1296             twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, imm)
1297         };
1298         performJITMemcpy(address, instruction, sizeof(uint16_t) * 2);
1299         cacheFlush(address, sizeof(uint16_t) * 2);
1300     }
1301 #endif
1302
1303     ALWAYS_INLINE void mov(RegisterID rd, ARMThumbImmediate imm)
1304     {
1305         ASSERT(imm.isValid());
1306         ASSERT(!BadReg(rd));
1307         
1308         if ((rd < 8) && imm.isUInt8())
1309             m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
1310         else if (imm.isEncodedImm())
1311             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
1312         else
1313             movT3(rd, imm);
1314     }
1315
1316     ALWAYS_INLINE void mov(RegisterID rd, RegisterID rm)
1317     {
1318         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
1319     }
1320
1321     ALWAYS_INLINE void movt(RegisterID rd, ARMThumbImmediate imm)
1322     {
1323         ASSERT(imm.isUInt16());
1324         ASSERT(!BadReg(rd));
1325         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
1326     }
1327
1328     ALWAYS_INLINE void mvn(RegisterID rd, ARMThumbImmediate imm)
1329     {
1330         ASSERT(imm.isEncodedImm());
1331         ASSERT(!BadReg(rd));
1332         
1333         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
1334     }
1335
1336     ALWAYS_INLINE void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
1337     {
1338         ASSERT(!BadReg(rd));
1339         ASSERT(!BadReg(rm));
1340         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1341     }
1342
1343     ALWAYS_INLINE void mvn(RegisterID rd, RegisterID rm)
1344     {
1345         if (!((rd | rm) & 8))
1346             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
1347         else
1348             mvn(rd, rm, ShiftTypeAndAmount());
1349     }
1350
1351     ALWAYS_INLINE void mrs(RegisterID rd, SPRegisterID specReg)
1352     {
1353         ASSERT(specReg == ARMRegisters::apsr);
1354         ASSERT(!BadReg(rd));
1355         unsigned short specialRegisterBit = (specReg == ARMRegisters::apsr) ? 0 : (1 << 4);
1356         OpcodeID1 mrsOp = static_cast<OpcodeID1>(OP_MRS_T1 | specialRegisterBit);
1357         m_formatter.twoWordOp16FourFours(mrsOp, FourFours(0x8, rd, 0, 0));
1358     }
1359
1360     ALWAYS_INLINE void neg(RegisterID rd, RegisterID rm)
1361     {
1362         ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
1363         sub(rd, zero, rm);
1364     }
1365
1366     ALWAYS_INLINE void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1367     {
1368         ASSERT(!BadReg(rd));
1369         ASSERT(!BadReg(rn));
1370         ASSERT(imm.isEncodedImm());
1371         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
1372     }
1373
1374     ALWAYS_INLINE void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1375     {
1376         ASSERT(!BadReg(rd));
1377         ASSERT(!BadReg(rn));
1378         ASSERT(!BadReg(rm));
1379         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1380     }
1381
1382     void orr(RegisterID rd, RegisterID rn, RegisterID rm)
1383     {
1384         if ((rd == rn) && !((rd | rm) & 8))
1385             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1386         else if ((rd == rm) && !((rd | rn) & 8))
1387             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1388         else
1389             orr(rd, rn, rm, ShiftTypeAndAmount());
1390     }
1391
1392     ALWAYS_INLINE void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1393     {
1394         ASSERT(!BadReg(rd));
1395         ASSERT(!BadReg(rn));
1396         ASSERT(!BadReg(rm));
1397         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1398     }
1399
1400     void orr_S(RegisterID rd, RegisterID rn, RegisterID rm)
1401     {
1402         if ((rd == rn) && !((rd | rm) & 8))
1403             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1404         else if ((rd == rm) && !((rd | rn) & 8))
1405             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1406         else
1407             orr_S(rd, rn, rm, ShiftTypeAndAmount());
1408     }
1409
1410     ALWAYS_INLINE void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1411     {
1412         ASSERT(!BadReg(rd));
1413         ASSERT(!BadReg(rm));
1414         ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
1415         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1416     }
1417
1418     ALWAYS_INLINE void ror(RegisterID rd, RegisterID rn, RegisterID rm)
1419     {
1420         ASSERT(!BadReg(rd));
1421         ASSERT(!BadReg(rn));
1422         ASSERT(!BadReg(rm));
1423         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1424     }
1425
1426     ALWAYS_INLINE void pop(RegisterID dest)
1427     {
1428         if (dest < ARMRegisters::r8)
1429             m_formatter.oneWordOp7Imm9(OP_POP_T1, 1 << dest);
1430         else {
1431             // Load postindexed with writeback.
1432             ldr(dest, ARMRegisters::sp, sizeof(void*), false, true);
1433         }
1434     }
1435
1436     ALWAYS_INLINE void pop(uint32_t registerList)
1437     {
1438         ASSERT(WTF::bitCount(registerList) > 1);
1439         ASSERT(!((1 << ARMRegisters::pc) & registerList) || !((1 << ARMRegisters::lr) & registerList));
1440         ASSERT(!((1 << ARMRegisters::sp) & registerList));
1441         m_formatter.twoWordOp16Imm16(OP_POP_T2, registerList);
1442     }
1443
1444     ALWAYS_INLINE void push(RegisterID src)
1445     {
1446         if (src < ARMRegisters::r8)
1447             m_formatter.oneWordOp7Imm9(OP_PUSH_T1, 1 << src);
1448         else if (src == ARMRegisters::lr)
1449             m_formatter.oneWordOp7Imm9(OP_PUSH_T1, 0x100);
1450         else {
1451             // Store preindexed with writeback.
1452             str(src, ARMRegisters::sp, -sizeof(void*), true, true);
1453         }
1454     }
1455
1456     ALWAYS_INLINE void push(uint32_t registerList)
1457     {
1458         ASSERT(WTF::bitCount(registerList) > 1);
1459         ASSERT(!((1 << ARMRegisters::pc) & registerList));
1460         ASSERT(!((1 << ARMRegisters::sp) & registerList));
1461         m_formatter.twoWordOp16Imm16(OP_PUSH_T2, registerList);
1462     }
1463
1464 #if HAVE(ARM_IDIV_INSTRUCTIONS)
1465     template<int datasize>
1466     ALWAYS_INLINE void sdiv(RegisterID rd, RegisterID rn, RegisterID rm)
1467     {
1468         static_assert(datasize == 32, "sdiv datasize must be 32 for armv7s");        
1469         ASSERT(!BadReg(rd));
1470         ASSERT(!BadReg(rn));
1471         ASSERT(!BadReg(rm));
1472         m_formatter.twoWordOp12Reg4FourFours(OP_SDIV_T1, rn, FourFours(0xf, rd, 0xf, rm));
1473     }
1474 #endif
1475
1476     ALWAYS_INLINE void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
1477     {
1478         ASSERT(!BadReg(rdLo));
1479         ASSERT(!BadReg(rdHi));
1480         ASSERT(!BadReg(rn));
1481         ASSERT(!BadReg(rm));
1482         ASSERT(rdLo != rdHi);
1483         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
1484     }
1485
1486     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1487     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1488     {
1489         ASSERT(rt != ARMRegisters::pc);
1490         ASSERT(rn != ARMRegisters::pc);
1491         ASSERT(imm.isUInt12());
1492
1493         if (!((rt | rn) & 8) && imm.isUInt7())
1494             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1495         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1496             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, static_cast<uint8_t>(imm.getUInt10() >> 2));
1497         else
1498             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
1499     }
1500
1501     // If index is set, this is a regular offset or a pre-indexed store;
1502     // if index is not set then is is a post-index store.
1503     //
1504     // If wback is set rn is updated - this is a pre or post index store,
1505     // if wback is not set this is a regular offset memory access.
1506     //
1507     // (-255 <= offset <= 255)
1508     // _reg = REG[rn]
1509     // _tmp = _reg + offset
1510     // MEM[index ? _tmp : _reg] = REG[rt]
1511     // if (wback) REG[rn] = _tmp
1512     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1513     {
1514         ASSERT(rt != ARMRegisters::pc);
1515         ASSERT(rn != ARMRegisters::pc);
1516         ASSERT(index || wback);
1517         ASSERT(!wback | (rt != rn));
1518     
1519         bool add = true;
1520         if (offset < 0) {
1521             add = false;
1522             offset = -offset;
1523         }
1524         ASSERT((offset & ~0xff) == 0);
1525         
1526         offset |= (wback << 8);
1527         offset |= (add   << 9);
1528         offset |= (index << 10);
1529         offset |= (1 << 11);
1530         
1531         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
1532     }
1533
1534     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1535     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1536     {
1537         ASSERT(rn != ARMRegisters::pc);
1538         ASSERT(!BadReg(rm));
1539         ASSERT(shift <= 3);
1540
1541         if (!shift && !((rt | rn | rm) & 8))
1542             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
1543         else
1544             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1545     }
1546
1547     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1548     ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1549     {
1550         ASSERT(rt != ARMRegisters::pc);
1551         ASSERT(rn != ARMRegisters::pc);
1552         ASSERT(imm.isUInt12());
1553
1554         if (!((rt | rn) & 8) && imm.isUInt7())
1555             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STRB_imm_T1, imm.getUInt7() >> 2, rn, rt);
1556         else
1557             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T2, rn, rt, imm.getUInt12());
1558     }
1559
1560     // If index is set, this is a regular offset or a pre-indexed store;
1561     // if index is not set then is is a post-index store.
1562     //
1563     // If wback is set rn is updated - this is a pre or post index store,
1564     // if wback is not set this is a regular offset memory access.
1565     //
1566     // (-255 <= offset <= 255)
1567     // _reg = REG[rn]
1568     // _tmp = _reg + offset
1569     // MEM[index ? _tmp : _reg] = REG[rt]
1570     // if (wback) REG[rn] = _tmp
1571     ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1572     {
1573         ASSERT(rt != ARMRegisters::pc);
1574         ASSERT(rn != ARMRegisters::pc);
1575         ASSERT(index || wback);
1576         ASSERT(!wback | (rt != rn));
1577     
1578         bool add = true;
1579         if (offset < 0) {
1580             add = false;
1581             offset = -offset;
1582         }
1583         ASSERT((offset & ~0xff) == 0);
1584         
1585         offset |= (wback << 8);
1586         offset |= (add   << 9);
1587         offset |= (index << 10);
1588         offset |= (1 << 11);
1589         
1590         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T3, rn, rt, offset);
1591     }
1592
1593     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1594     ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1595     {
1596         ASSERT(rn != ARMRegisters::pc);
1597         ASSERT(!BadReg(rm));
1598         ASSERT(shift <= 3);
1599
1600         if (!shift && !((rt | rn | rm) & 8))
1601             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STRB_reg_T1, rm, rn, rt);
1602         else
1603             m_formatter.twoWordOp12Reg4FourFours(OP_STRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1604     }
1605     
1606     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1607     ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1608     {
1609         ASSERT(rt != ARMRegisters::pc);
1610         ASSERT(rn != ARMRegisters::pc);
1611         ASSERT(imm.isUInt12());
1612         
1613         if (!((rt | rn) & 8) && imm.isUInt6())
1614             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STRH_imm_T1, imm.getUInt6() >> 1, rn, rt);
1615         else
1616             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRH_imm_T2, rn, rt, imm.getUInt12());
1617     }
1618     
1619     // If index is set, this is a regular offset or a pre-indexed store;
1620     // if index is not set then is is a post-index store.
1621     //
1622     // If wback is set rn is updated - this is a pre or post index store,
1623     // if wback is not set this is a regular offset memory access.
1624     //
1625     // (-255 <= offset <= 255)
1626     // _reg = REG[rn]
1627     // _tmp = _reg + offset
1628     // MEM[index ? _tmp : _reg] = REG[rt]
1629     // if (wback) REG[rn] = _tmp
1630     ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1631     {
1632         ASSERT(rt != ARMRegisters::pc);
1633         ASSERT(rn != ARMRegisters::pc);
1634         ASSERT(index || wback);
1635         ASSERT(!wback | (rt != rn));
1636         
1637         bool add = true;
1638         if (offset < 0) {
1639             add = false;
1640             offset = -offset;
1641         }
1642         ASSERT(!(offset & ~0xff));
1643         
1644         offset |= (wback << 8);
1645         offset |= (add   << 9);
1646         offset |= (index << 10);
1647         offset |= (1 << 11);
1648         
1649         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRH_imm_T3, rn, rt, offset);
1650     }
1651     
1652     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1653     ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1654     {
1655         ASSERT(rn != ARMRegisters::pc);
1656         ASSERT(!BadReg(rm));
1657         ASSERT(shift <= 3);
1658         
1659         if (!shift && !((rt | rn | rm) & 8))
1660             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STRH_reg_T1, rm, rn, rt);
1661         else
1662             m_formatter.twoWordOp12Reg4FourFours(OP_STRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1663     }
1664
1665     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1666     {
1667         // Rd can only be SP if Rn is also SP.
1668         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1669         ASSERT(rd != ARMRegisters::pc);
1670         ASSERT(rn != ARMRegisters::pc);
1671         ASSERT(imm.isValid());
1672
1673         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1674             ASSERT(!(imm.getUInt16() & 3));
1675             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
1676             return;
1677         } else if (!((rd | rn) & 8)) {
1678             if (imm.isUInt3()) {
1679                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1680                 return;
1681             } else if ((rd == rn) && imm.isUInt8()) {
1682                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1683                 return;
1684             }
1685         }
1686
1687         if (imm.isEncodedImm())
1688             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
1689         else {
1690             ASSERT(imm.isUInt12());
1691             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
1692         }
1693     }
1694
1695     ALWAYS_INLINE void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
1696     {
1697         ASSERT(rd != ARMRegisters::pc);
1698         ASSERT(rn != ARMRegisters::pc);
1699         ASSERT(imm.isValid());
1700         ASSERT(imm.isUInt12());
1701
1702         if (!((rd | rn) & 8) && !imm.getUInt12())
1703             m_formatter.oneWordOp10Reg3Reg3(OP_RSB_imm_T1, rn, rd);
1704         else
1705             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
1706     }
1707
1708     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1709     {
1710         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1711         ASSERT(rd != ARMRegisters::pc);
1712         ASSERT(rn != ARMRegisters::pc);
1713         ASSERT(!BadReg(rm));
1714         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1715     }
1716
1717     // NOTE: In an IT block, add doesn't modify the flags register.
1718     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, RegisterID rm)
1719     {
1720         if (!((rd | rn | rm) & 8))
1721             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1722         else
1723             sub(rd, rn, rm, ShiftTypeAndAmount());
1724     }
1725
1726     // Not allowed in an IT (if then) block.
1727     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1728     {
1729         // Rd can only be SP if Rn is also SP.
1730         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1731         ASSERT(rd != ARMRegisters::pc);
1732         ASSERT(rn != ARMRegisters::pc);
1733         ASSERT(imm.isValid());
1734
1735         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1736             ASSERT(!(imm.getUInt16() & 3));
1737             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
1738             return;
1739         } else if (!((rd | rn) & 8)) {
1740             if (imm.isUInt3()) {
1741                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1742                 return;
1743             } else if ((rd == rn) && imm.isUInt8()) {
1744                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1745                 return;
1746             }
1747         }
1748
1749         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
1750     }
1751
1752     ALWAYS_INLINE void sub_S(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
1753     {
1754         ASSERT(rd != ARMRegisters::pc);
1755         ASSERT(rn != ARMRegisters::pc);
1756         ASSERT(imm.isValid());
1757         ASSERT(imm.isUInt12());
1758
1759         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_S_imm_T2, rn, rd, imm);
1760     }
1761
1762     // Not allowed in an IT (if then) block?
1763     ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1764     {
1765         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1766         ASSERT(rd != ARMRegisters::pc);
1767         ASSERT(rn != ARMRegisters::pc);
1768         ASSERT(!BadReg(rm));
1769         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1770     }
1771
1772     // Not allowed in an IT (if then) block.
1773     ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
1774     {
1775         if (!((rd | rn | rm) & 8))
1776             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1777         else
1778             sub_S(rd, rn, rm, ShiftTypeAndAmount());
1779     }
1780
1781     ALWAYS_INLINE void tst(RegisterID rn, ARMThumbImmediate imm)
1782     {
1783         ASSERT(!BadReg(rn));
1784         ASSERT(imm.isEncodedImm());
1785
1786         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
1787     }
1788
1789     ALWAYS_INLINE void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1790     {
1791         ASSERT(!BadReg(rn));
1792         ASSERT(!BadReg(rm));
1793         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1794     }
1795
1796     ALWAYS_INLINE void tst(RegisterID rn, RegisterID rm)
1797     {
1798         if ((rn | rm) & 8)
1799             tst(rn, rm, ShiftTypeAndAmount());
1800         else
1801             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
1802     }
1803
1804     ALWAYS_INLINE void ubfx(RegisterID rd, RegisterID rn, unsigned lsb, unsigned width)
1805     {
1806         ASSERT(lsb < 32);
1807         ASSERT((width >= 1) && (width <= 32));
1808         ASSERT((lsb + width) <= 32);
1809         m_formatter.twoWordOp12Reg40Imm3Reg4Imm20Imm5(OP_UBFX_T1, rd, rn, (lsb & 0x1c) << 10, (lsb & 0x3) << 6, (width - 1) & 0x1f);
1810     }
1811
1812 #if HAVE(ARM_IDIV_INSTRUCTIONS)
1813     ALWAYS_INLINE void udiv(RegisterID rd, RegisterID rn, RegisterID rm)
1814     {
1815         ASSERT(!BadReg(rd));
1816         ASSERT(!BadReg(rn));
1817         ASSERT(!BadReg(rm));
1818         m_formatter.twoWordOp12Reg4FourFours(OP_UDIV_T1, rn, FourFours(0xf, rd, 0xf, rm));
1819     }
1820 #endif
1821
1822     void vadd(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1823     {
1824         m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
1825     }
1826
1827     void vcmp(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1828     {
1829         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
1830     }
1831
1832     void vcmpz(FPDoubleRegisterID rd)
1833     {
1834         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
1835     }
1836
1837     void vcvt_signedToFloatingPoint(FPDoubleRegisterID rd, FPSingleRegisterID rm)
1838     {
1839         // boolean values are 64bit (toInt, unsigned, roundZero)
1840         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
1841     }
1842
1843     void vcvt_floatingPointToSigned(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1844     {
1845         // boolean values are 64bit (toInt, unsigned, roundZero)
1846         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
1847     }
1848     
1849     void vcvt_floatingPointToUnsigned(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1850     {
1851         // boolean values are 64bit (toInt, unsigned, roundZero)
1852         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, true, true), rd, rm);
1853     }
1854
1855     void vdiv(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1856     {
1857         m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
1858     }
1859
1860     void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1861     {
1862         m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
1863     }
1864     
1865     void flds(FPSingleRegisterID rd, RegisterID rn, int32_t imm)
1866     {
1867         m_formatter.vfpMemOp(OP_FLDS, OP_FLDSb, false, rn, rd, imm);
1868     }
1869
1870     void vmov(RegisterID rd, FPSingleRegisterID rn)
1871     {
1872         ASSERT(!BadReg(rd));
1873         m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rn, rd, VFPOperand(0));
1874     }
1875
1876     void vmov(FPSingleRegisterID rd, RegisterID rn)
1877     {
1878         ASSERT(!BadReg(rn));
1879         m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rd, rn, VFPOperand(0));
1880     }
1881
1882     void vmov(RegisterID rd1, RegisterID rd2, FPDoubleRegisterID rn)
1883     {
1884         ASSERT(!BadReg(rd1));
1885         ASSERT(!BadReg(rd2));
1886         m_formatter.vfpOp(OP_VMOV_DtoC, OP_VMOV_DtoCb, true, rd2, VFPOperand(rd1 | 16), rn);
1887     }
1888
1889     void vmov(FPDoubleRegisterID rd, RegisterID rn1, RegisterID rn2)
1890     {
1891         ASSERT(!BadReg(rn1));
1892         ASSERT(!BadReg(rn2));
1893         m_formatter.vfpOp(OP_VMOV_CtoD, OP_VMOV_CtoDb, true, rn2, VFPOperand(rn1 | 16), rd);
1894     }
1895
1896     void vmov(FPDoubleRegisterID rd, FPDoubleRegisterID rn)
1897     {
1898         m_formatter.vfpOp(OP_VMOV_T2, OP_VMOV_T2b, true, VFPOperand(0), rd, rn);
1899     }
1900
1901     void vmrs(RegisterID reg = ARMRegisters::pc)
1902     {
1903         ASSERT(reg != ARMRegisters::sp);
1904         m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
1905     }
1906
1907     void vmul(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1908     {
1909         m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
1910     }
1911
1912     void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1913     {
1914         m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
1915     }
1916
1917     void fsts(FPSingleRegisterID rd, RegisterID rn, int32_t imm)
1918     {
1919         m_formatter.vfpMemOp(OP_FSTS, OP_FSTSb, false, rn, rd, imm);
1920     }
1921
1922     void vsub(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1923     {
1924         m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
1925     }
1926
1927     void vabs(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1928     {
1929         m_formatter.vfpOp(OP_VABS_T2, OP_VABS_T2b, true, VFPOperand(16), rd, rm);
1930     }
1931
1932     void vneg(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1933     {
1934         m_formatter.vfpOp(OP_VNEG_T2, OP_VNEG_T2b, true, VFPOperand(1), rd, rm);
1935     }
1936
1937     void vsqrt(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1938     {
1939         m_formatter.vfpOp(OP_VSQRT_T1, OP_VSQRT_T1b, true, VFPOperand(17), rd, rm);
1940     }
1941     
1942     void vcvtds(FPDoubleRegisterID rd, FPSingleRegisterID rm)
1943     {
1944         m_formatter.vfpOp(OP_VCVTDS_T1, OP_VCVTDS_T1b, false, VFPOperand(23), rd, rm);
1945     }
1946
1947     void vcvtsd(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1948     {
1949         m_formatter.vfpOp(OP_VCVTSD_T1, OP_VCVTSD_T1b, true, VFPOperand(23), rd, rm);
1950     }
1951
1952     void nop()
1953     {
1954         m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0);
1955     }
1956
1957     void nopw()
1958     {
1959         m_formatter.twoWordOp16Op16(OP_NOP_T2a, OP_NOP_T2b);
1960     }
1961     
1962     static constexpr int16_t nopPseudo16()
1963     {
1964         return OP_NOP_T1;
1965     }
1966
1967     static constexpr int32_t nopPseudo32()
1968     {
1969         return OP_NOP_T2a | (OP_NOP_T2b << 16);
1970     }
1971
1972     template <typename CopyFunction>
1973     static void fillNops(void* base, size_t size, CopyFunction copy)
1974     {
1975         RELEASE_ASSERT(!(size % sizeof(int16_t)));
1976
1977         char* ptr = static_cast<char*>(base);
1978         const size_t num32s = size / sizeof(int32_t);
1979         for (size_t i = 0; i < num32s; i++) {
1980             const int32_t insn = nopPseudo32();
1981             copy(ptr, &insn, sizeof(int32_t));
1982             ptr += sizeof(int32_t);
1983         }
1984
1985         const size_t num16s = (size % sizeof(int32_t)) / sizeof(int16_t);
1986         ASSERT(num16s == 0 || num16s == 1);
1987         ASSERT(num16s * sizeof(int16_t) + num32s * sizeof(int32_t) == size);
1988         if (num16s) {
1989             const int16_t insn = nopPseudo16();
1990             copy(ptr, &insn, sizeof(int16_t));
1991         }
1992     }
1993
1994     void dmbSY()
1995     {
1996         m_formatter.twoWordOp16Op16(OP_DMB_T1a, OP_DMB_SY_T1b);
1997     }
1998
1999     void dmbISHST()
2000     {
2001         m_formatter.twoWordOp16Op16(OP_DMB_T1a, OP_DMB_ISHST_T1b);
2002     }
2003
2004     AssemblerLabel labelIgnoringWatchpoints()
2005     {
2006         return m_formatter.label();
2007     }
2008
2009     AssemblerLabel labelForWatchpoint()
2010     {
2011         AssemblerLabel result = m_formatter.label();
2012         if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint)
2013             result = label();
2014         m_indexOfLastWatchpoint = result.m_offset;
2015         m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize();
2016         return result;
2017     }
2018
2019     AssemblerLabel label()
2020     {
2021         AssemblerLabel result = m_formatter.label();
2022         while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) {
2023             if (UNLIKELY(static_cast<int>(result.m_offset) + 4 <= m_indexOfTailOfLastWatchpoint))
2024                 nopw();
2025             else
2026                 nop();
2027             result = m_formatter.label();
2028         }
2029         return result;
2030     }
2031     
2032     AssemblerLabel align(int alignment)
2033     {
2034         while (!m_formatter.isAligned(alignment))
2035             bkpt();
2036
2037         return label();
2038     }
2039     
2040     static void* getRelocatedAddress(void* code, AssemblerLabel label)
2041     {
2042         ASSERT(label.isSet());
2043         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + label.m_offset);
2044     }
2045     
2046     static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
2047     {
2048         return b.m_offset - a.m_offset;
2049     }
2050
2051     static int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JUMP_ENUM_SIZE(jumpType) - JUMP_ENUM_SIZE(jumpLinkType); }
2052     
2053     // Assembler admin methods:
2054
2055     static ALWAYS_INLINE bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
2056     {
2057         return a.from() < b.from();
2058     }
2059
2060     static bool canCompact(JumpType jumpType)
2061     {
2062         // The following cannot be compacted:
2063         //   JumpFixed: represents custom jump sequence
2064         //   JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size
2065         //   JumpConditionFixedSize: represents conditional jump that must remain a fixed size
2066         return (jumpType == JumpNoCondition) || (jumpType == JumpCondition);
2067     }
2068     
2069     static JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
2070     {
2071         if (jumpType == JumpFixed)
2072             return LinkInvalid;
2073         
2074         // for patchable jump we must leave space for the longest code sequence
2075         if (jumpType == JumpNoConditionFixedSize)
2076             return LinkBX;
2077         if (jumpType == JumpConditionFixedSize)
2078             return LinkConditionalBX;
2079         
2080         const int paddingSize = JUMP_ENUM_SIZE(jumpType);
2081         
2082         if (jumpType == JumpCondition) {
2083             // 2-byte conditional T1
2084             const uint16_t* jumpT1Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1)));
2085             if (canBeJumpT1(jumpT1Location, to))
2086                 return LinkJumpT1;
2087             // 4-byte conditional T3
2088             const uint16_t* jumpT3Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3)));
2089             if (canBeJumpT3(jumpT3Location, to))
2090                 return LinkJumpT3;
2091             // 4-byte conditional T4 with IT
2092             const uint16_t* conditionalJumpT4Location = 
2093             reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4)));
2094             if (canBeJumpT4(conditionalJumpT4Location, to))
2095                 return LinkConditionalJumpT4;
2096         } else {
2097             // 2-byte unconditional T2
2098             const uint16_t* jumpT2Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2)));
2099             if (canBeJumpT2(jumpT2Location, to))
2100                 return LinkJumpT2;
2101             // 4-byte unconditional T4
2102             const uint16_t* jumpT4Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4)));
2103             if (canBeJumpT4(jumpT4Location, to))
2104                 return LinkJumpT4;
2105             // use long jump sequence
2106             return LinkBX;
2107         }
2108         
2109         ASSERT(jumpType == JumpCondition);
2110         return LinkConditionalBX;
2111     }
2112     
2113     static JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
2114     {
2115         JumpLinkType linkType = computeJumpType(record.type(), from, to);
2116         record.setLinkType(linkType);
2117         return linkType;
2118     }
2119     
2120     Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink()
2121     {
2122         std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
2123         return m_jumpsToLink;
2124     }
2125
2126     typedef void* (*CopyFunction)(void*, const void*, size_t);
2127
2128     static void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, const uint8_t* fromInstruction8, uint8_t* to, CopyFunction copy)
2129     {
2130         const uint16_t* fromInstruction = reinterpret_cast_ptr<const uint16_t*>(fromInstruction8);
2131         switch (record.linkType()) {
2132         case LinkJumpT1:
2133             linkJumpT1(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to, copy);
2134             break;
2135         case LinkJumpT2:
2136             linkJumpT2(reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to, copy);
2137             break;
2138         case LinkJumpT3:
2139             linkJumpT3(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to, copy);
2140             break;
2141         case LinkJumpT4:
2142             linkJumpT4(reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to, copy);
2143             break;
2144         case LinkConditionalJumpT4:
2145             linkConditionalJumpT4(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to, copy);
2146             break;
2147         case LinkConditionalBX:
2148             linkConditionalBX(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to, copy);
2149             break;
2150         case LinkBX:
2151             linkBX(reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to, copy);
2152             break;
2153         default:
2154             RELEASE_ASSERT_NOT_REACHED();
2155             break;
2156         }
2157     }
2158
2159     size_t codeSize() const { return m_formatter.codeSize(); }
2160
2161     static unsigned getCallReturnOffset(AssemblerLabel call)
2162     {
2163         ASSERT(call.isSet());
2164         return call.m_offset;
2165     }
2166
2167     // Linking & patching:
2168     //
2169     // 'link' and 'patch' methods are for use on unprotected code - such as the code
2170     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
2171     // code has been finalized it is (platform support permitting) within a non-
2172     // writable region of memory; to modify the code in an execute-only execuable
2173     // pool the 'repatch' and 'relink' methods should be used.
2174
2175     void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type, Condition condition)
2176     {
2177         ASSERT(to.isSet());
2178         ASSERT(from.isSet());
2179         m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, type, condition));
2180     }
2181
2182     static void linkJump(void* code, AssemblerLabel from, void* to)
2183     {
2184         ASSERT(from.isSet());
2185         
2186         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
2187         linkJumpAbsolute(location, location, to);
2188     }
2189
2190     static void linkCall(void* code, AssemblerLabel from, void* to)
2191     {
2192         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
2193         ASSERT(from.isSet());
2194
2195         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to, false);
2196     }
2197
2198     static void linkPointer(void* code, AssemblerLabel where, void* value)
2199     {
2200         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value, false);
2201     }
2202
2203     // The static relink and replace methods can use can use |from| for both
2204     // the write and executable address for call and jump patching
2205     // as they're modifying existing (linked) code, so the address being
2206     // provided is correct for relative address computation.
2207     static void relinkJump(void* from, void* to)
2208     {
2209         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
2210         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
2211
2212         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), reinterpret_cast<uint16_t*>(from), to);
2213
2214         cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
2215     }
2216
2217     static void relinkJumpToNop(void* from)
2218     {
2219         relinkJump(from, from);
2220     }
2221     
2222     static void relinkCall(void* from, void* to)
2223     {
2224         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
2225
2226         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to, true);
2227     }
2228     
2229     static void* readCallTarget(void* from)
2230     {
2231         return readPointer(reinterpret_cast<uint16_t*>(from) - 1);
2232     }
2233
2234     static void repatchInt32(void* where, int32_t value)
2235     {
2236         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
2237         
2238         setInt32(where, value, true);
2239     }
2240     
2241     static void repatchCompact(void* where, int32_t offset)
2242     {
2243         ASSERT(offset >= -255 && offset <= 255);
2244
2245         bool add = true;
2246         if (offset < 0) {
2247             add = false;
2248             offset = -offset;
2249         }
2250         
2251         offset |= (add << 9);
2252         offset |= (1 << 10);
2253         offset |= (1 << 11);
2254
2255         uint16_t* location = reinterpret_cast<uint16_t*>(where);
2256         uint16_t instruction = location[1] & ~((1 << 12) - 1);
2257         instruction |= offset;
2258         performJITMemcpy(location + 1, &instruction, sizeof(uint16_t));
2259         cacheFlush(location, sizeof(uint16_t) * 2);
2260     }
2261
2262     static void repatchPointer(void* where, void* value)
2263     {
2264         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
2265         
2266         setPointer(where, value, true);
2267     }
2268
2269     static void* readPointer(void* where)
2270     {
2271         return reinterpret_cast<void*>(readInt32(where));
2272     }
2273
2274     static void replaceWithJump(void* instructionStart, void* to)
2275     {
2276         ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));
2277         ASSERT(!(bitwise_cast<uintptr_t>(to) & 1));
2278
2279 #if OS(LINUX)
2280         if (canBeJumpT4(reinterpret_cast<uint16_t*>(instructionStart), to)) {
2281             uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2;
2282             linkJumpT4(ptr, ptr, to);
2283             cacheFlush(ptr - 2, sizeof(uint16_t) * 2);
2284         } else {
2285             uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 5;
2286             linkBX(ptr, ptr, to);
2287             cacheFlush(ptr - 5, sizeof(uint16_t) * 5);
2288         }
2289 #else
2290         uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2;
2291         linkJumpT4(ptr, ptr, to);
2292         cacheFlush(ptr - 2, sizeof(uint16_t) * 2);
2293 #endif
2294     }
2295     
2296     static ptrdiff_t maxJumpReplacementSize()
2297     {
2298 #if OS(LINUX)
2299         return 10;
2300 #else
2301         return 4;
2302 #endif
2303     }
2304
2305     static constexpr ptrdiff_t patchableJumpSize()
2306     {
2307         return 10;
2308     }
2309     
2310     static void replaceWithLoad(void* instructionStart)
2311     {
2312         ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));
2313         uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart);
2314         switch (ptr[0] & 0xFFF0) {
2315         case OP_LDR_imm_T3:
2316             break;
2317         case OP_ADD_imm_T3: {
2318             ASSERT(!(ptr[1] & 0xF000));
2319             uint16_t instructions[2];
2320             instructions[0] = ptr[0] & 0x000F;
2321             instructions[0] |= OP_LDR_imm_T3;
2322             instructions[1] = ptr[1] | (ptr[1] & 0x0F00) << 4;
2323             instructions[1] &= 0xF0FF;
2324             performJITMemcpy(ptr, instructions, sizeof(uint16_t) * 2);
2325             cacheFlush(ptr, sizeof(uint16_t) * 2);
2326             break;
2327         }
2328         default:
2329             RELEASE_ASSERT_NOT_REACHED();
2330         }
2331     }
2332
2333     static void replaceWithAddressComputation(void* instructionStart)
2334     {
2335         ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));
2336         uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart);
2337         switch (ptr[0] & 0xFFF0) {
2338         case OP_LDR_imm_T3: {
2339             ASSERT(!(ptr[1] & 0x0F00));
2340             uint16_t instructions[2];
2341             instructions[0] = ptr[0] & 0x000F;
2342             instructions[0] |= OP_ADD_imm_T3;
2343             instructions[1] = ptr[1] | (ptr[1] & 0xF000) >> 4;
2344             instructions[1] &= 0x0FFF;
2345             performJITMemcpy(ptr, instructions, sizeof(uint16_t) * 2);
2346             cacheFlush(ptr, sizeof(uint16_t) * 2);
2347             break;
2348         }
2349         case OP_ADD_imm_T3:
2350             break;
2351         default:
2352             RELEASE_ASSERT_NOT_REACHED();
2353         }
2354     }
2355
2356     unsigned debugOffset() { return m_formatter.debugOffset(); }
2357
2358 #if OS(LINUX)
2359     static inline void linuxPageFlush(uintptr_t begin, uintptr_t end)
2360     {
2361         asm volatile(
2362             "push    {r7}\n"
2363             "mov     r0, %0\n"
2364             "mov     r1, %1\n"
2365             "movw    r7, #0x2\n"
2366             "movt    r7, #0xf\n"
2367             "movs    r2, #0x0\n"
2368             "svc     0x0\n"
2369             "pop     {r7}\n"
2370             :
2371             : "r" (begin), "r" (end)
2372             : "r0", "r1", "r2");
2373     }
2374 #endif
2375
2376     static void cacheFlush(void* code, size_t size)
2377     {
2378 #if OS(IOS_FAMILY)
2379         sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
2380 #elif OS(LINUX)
2381         size_t page = pageSize();
2382         uintptr_t current = reinterpret_cast<uintptr_t>(code);
2383         uintptr_t end = current + size;
2384         uintptr_t firstPageEnd = (current & ~(page - 1)) + page;
2385
2386         if (end <= firstPageEnd) {
2387             linuxPageFlush(current, end);
2388             return;
2389         }
2390
2391         linuxPageFlush(current, firstPageEnd);
2392
2393         for (current = firstPageEnd; current + page < end; current += page)
2394             linuxPageFlush(current, current + page);
2395
2396         linuxPageFlush(current, end);
2397 #else
2398 #error "The cacheFlush support is missing on this platform."
2399 #endif
2400     }
2401
2402 private:
2403     // VFP operations commonly take one or more 5-bit operands, typically representing a
2404     // floating point register number.  This will commonly be encoded in the instruction
2405     // in two parts, with one single bit field, and one 4-bit field.  In the case of
2406     // double precision operands the high bit of the register number will be encoded
2407     // separately, and for single precision operands the high bit of the register number
2408     // will be encoded individually.
2409     // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit
2410     // field to be encoded together in the instruction (the low 4-bits of a double
2411     // register number, or the high 4-bits of a single register number), and bit 4
2412     // contains the bit value to be encoded individually.
2413     struct VFPOperand {
2414         explicit VFPOperand(uint32_t value)
2415             : m_value(value)
2416         {
2417             ASSERT(!(m_value & ~0x1f));
2418         }
2419
2420         VFPOperand(FPDoubleRegisterID reg)
2421             : m_value(reg)
2422         {
2423         }
2424
2425         VFPOperand(RegisterID reg)
2426             : m_value(reg)
2427         {
2428         }
2429
2430         VFPOperand(FPSingleRegisterID reg)
2431             : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top.
2432         {
2433         }
2434
2435         uint32_t bits1()
2436         {
2437             return m_value >> 4;
2438         }
2439
2440         uint32_t bits4()
2441         {
2442             return m_value & 0xf;
2443         }
2444
2445         uint32_t m_value;
2446     };
2447
2448     VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero)
2449     {
2450         // Cannot specify rounding when converting to float.
2451         ASSERT(toInteger || !isRoundZero);
2452
2453         uint32_t op = 0x8;
2454         if (toInteger) {
2455             // opc2 indicates both toInteger & isUnsigned.
2456             op |= isUnsigned ? 0x4 : 0x5;
2457             // 'op' field in instruction is isRoundZero
2458             if (isRoundZero)
2459                 op |= 0x10;
2460         } else {
2461             ASSERT(!isRoundZero);
2462             // 'op' field in instruction is isUnsigned
2463             if (!isUnsigned)
2464                 op |= 0x10;
2465         }
2466         return VFPOperand(op);
2467     }
2468
2469     static void setInt32(void* code, uint32_t value, bool flush)
2470     {
2471         uint16_t* location = reinterpret_cast<uint16_t*>(code);
2472         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
2473
2474         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
2475         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
2476         uint16_t instructions[4];
2477         instructions[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2478         instructions[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
2479         instructions[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2480         instructions[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
2481
2482         performJITMemcpy(location - 4, instructions, 4 * sizeof(uint16_t));
2483         if (flush)
2484             cacheFlush(location - 4, 4 * sizeof(uint16_t));
2485     }
2486     
2487     static int32_t readInt32(void* code)
2488     {
2489         uint16_t* location = reinterpret_cast<uint16_t*>(code);
2490         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
2491         
2492         ARMThumbImmediate lo16;
2493         ARMThumbImmediate hi16;
2494         decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(lo16, location[-4]);
2495         decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(lo16, location[-3]);
2496         decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(hi16, location[-2]);
2497         decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(hi16, location[-1]);
2498         uint32_t result = hi16.asUInt16();
2499         result <<= 16;
2500         result |= lo16.asUInt16();
2501         return static_cast<int32_t>(result);
2502     }
2503
2504     static void setUInt7ForLoad(void* code, ARMThumbImmediate imm)
2505     {
2506         // Requires us to have planted a LDR_imm_T1
2507         ASSERT(imm.isValid());
2508         ASSERT(imm.isUInt7());
2509         uint16_t* location = reinterpret_cast<uint16_t*>(code);
2510         uint16_t instruction;
2511         instruction = location[0] & ~((static_cast<uint16_t>(0x7f) >> 2) << 6);
2512         instruction |= (imm.getUInt7() >> 2) << 6;
2513         performJITMemcpy(location, &instruction, sizeof(uint16_t));
2514         cacheFlush(location, sizeof(uint16_t));
2515     }
2516
2517     static void setPointer(void* code, void* value, bool flush)
2518     {
2519         setInt32(code, reinterpret_cast<uint32_t>(value), flush);
2520     }
2521
2522     static bool isB(const void* address)
2523     {
2524         const uint16_t* instruction = static_cast<const uint16_t*>(address);
2525         return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
2526     }
2527
2528     static bool isBX(const void* address)
2529     {
2530         const uint16_t* instruction = static_cast<const uint16_t*>(address);
2531         return (instruction[0] & 0xff87) == OP_BX;
2532     }
2533
2534     static bool isMOV_imm_T3(const void* address)
2535     {
2536         const uint16_t* instruction = static_cast<const uint16_t*>(address);
2537         return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
2538     }
2539
2540     static bool isMOVT(const void* address)
2541     {
2542         const uint16_t* instruction = static_cast<const uint16_t*>(address);
2543         return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
2544     }
2545
2546     static bool isNOP_T1(const void* address)
2547     {
2548         const uint16_t* instruction = static_cast<const uint16_t*>(address);
2549         return instruction[0] == OP_NOP_T1;
2550     }
2551
2552     static bool isNOP_T2(const void* address)
2553     {
2554         const uint16_t* instruction = static_cast<const uint16_t*>(address);
2555         return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
2556     }
2557
2558     static bool canBeJumpT1(const uint16_t* instruction, const void* target)
2559     {
2560         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2561         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2562         
2563         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2564         // It does not appear to be documented in the ARM ARM (big surprise), but
2565         // for OP_B_T1 the branch displacement encoded in the instruction is 2 
2566         // less than the actual displacement.
2567         relative -= 2;
2568         return ((relative << 23) >> 23) == relative;
2569     }
2570     
2571     static bool canBeJumpT2(const uint16_t* instruction, const void* target)
2572     {
2573         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2574         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2575         
2576         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2577         // It does not appear to be documented in the ARM ARM (big surprise), but
2578         // for OP_B_T2 the branch displacement encoded in the instruction is 2 
2579         // less than the actual displacement.
2580         relative -= 2;
2581         return ((relative << 20) >> 20) == relative;
2582     }
2583     
2584     static bool canBeJumpT3(const uint16_t* instruction, const void* target)
2585     {
2586         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2587         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2588         
2589         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2590         return ((relative << 11) >> 11) == relative;
2591     }
2592     
2593     static bool canBeJumpT4(const uint16_t* instruction, const void* target)
2594     {
2595         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2596         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2597         
2598         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2599         return ((relative << 7) >> 7) == relative;
2600     }
2601     
2602     static void linkJumpT1(Condition cond, uint16_t* writeTarget, const uint16_t* instruction, void* target, CopyFunction copy = performJITMemcpy)
2603     {
2604         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2605         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2606         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2607         ASSERT(canBeJumpT1(instruction, target));
2608         
2609         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2610         // It does not appear to be documented in the ARM ARM (big surprise), but
2611         // for OP_B_T1 the branch displacement encoded in the instruction is 2 
2612         // less than the actual displacement.
2613         relative -= 2;
2614         
2615         // All branch offsets should be an even distance.
2616         ASSERT(!(relative & 1));
2617         uint16_t newInstruction = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1);
2618         copy(writeTarget - 1, &newInstruction, sizeof(uint16_t));
2619     }
2620     
2621     static void linkJumpT2(uint16_t* writeTarget, const uint16_t* instruction, void* target, CopyFunction copy = performJITMemcpy)
2622     {
2623         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2624         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2625         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2626         ASSERT(canBeJumpT2(instruction, target));
2627         
2628         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2629         // It does not appear to be documented in the ARM ARM (big surprise), but
2630         // for OP_B_T2 the branch displacement encoded in the instruction is 2 
2631         // less than the actual displacement.
2632         relative -= 2;
2633         
2634         // All branch offsets should be an even distance.
2635         ASSERT(!(relative & 1));
2636         uint16_t newInstruction = OP_B_T2 | ((relative & 0xffe) >> 1);
2637         copy(writeTarget - 1, &newInstruction, sizeof(uint16_t));
2638     }
2639     
2640     static void linkJumpT3(Condition cond, uint16_t* writeTarget, const uint16_t* instruction, void* target, CopyFunction copy = performJITMemcpy)
2641     {
2642         // FIMXE: this should be up in the MacroAssembler layer. :-(
2643         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2644         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2645         ASSERT(canBeJumpT3(instruction, target));
2646         
2647         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2648         
2649         // All branch offsets should be an even distance.
2650         ASSERT(!(relative & 1));
2651         uint16_t instructions[2];
2652         instructions[0] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12);
2653         instructions[1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1);
2654         copy(writeTarget - 2, instructions, 2 * sizeof(uint16_t));
2655     }
2656     
2657     static void linkJumpT4(uint16_t* writeTarget, const uint16_t* instruction, void* target, CopyFunction copy = performJITMemcpy)
2658     {
2659         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2660         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2661         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2662         ASSERT(canBeJumpT4(instruction, target));
2663         
2664         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2665         // ARM encoding for the top two bits below the sign bit is 'peculiar'.
2666         if (relative >= 0)
2667             relative ^= 0xC00000;
2668         
2669         // All branch offsets should be an even distance.
2670         ASSERT(!(relative & 1));
2671         uint16_t instructions[2];
2672         instructions[0] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
2673         instructions[1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
2674         copy(writeTarget - 2, instructions, 2 * sizeof(uint16_t));
2675     }
2676     
2677     static void linkConditionalJumpT4(Condition cond, uint16_t* writeTarget, const uint16_t* instruction, void* target, CopyFunction copy = performJITMemcpy)
2678     {
2679         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2680         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2681         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2682         
2683         uint16_t newInstruction = ifThenElse(cond) | OP_IT;
2684         copy(writeTarget - 3, &newInstruction, sizeof(uint16_t));
2685         linkJumpT4(writeTarget, instruction, target, copy);
2686     }
2687     
2688     static void linkBX(uint16_t* writeTarget, const uint16_t* instruction, void* target, CopyFunction copy = performJITMemcpy)
2689     {
2690         // FIMXE: this should be up in the MacroAssembler layer. :-(
2691         ASSERT_UNUSED(instruction, !(reinterpret_cast<intptr_t>(instruction) & 1));
2692         ASSERT(!(reinterpret_cast<intptr_t>(writeTarget) & 1));
2693         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2694         
2695         const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2696         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2697         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2698         uint16_t instructions[5];
2699         instructions[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2700         instructions[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2701         instructions[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2702         instructions[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2703         instructions[4] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2704
2705         copy(writeTarget - 5, instructions, 5 * sizeof(uint16_t));
2706     }
2707     
2708     static void linkConditionalBX(Condition cond, uint16_t* writeTarget, const uint16_t* instruction, void* target, CopyFunction copy = performJITMemcpy)
2709     {
2710         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2711         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2712         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2713         
2714         linkBX(writeTarget, instruction, target);
2715         uint16_t newInstruction = ifThenElse(cond, true, true) | OP_IT;
2716         copy(writeTarget - 6, &newInstruction, sizeof(uint16_t));
2717     }
2718     
2719     static void linkJumpAbsolute(uint16_t* writeTarget, const uint16_t* instruction, void* target)
2720     {
2721         // FIMXE: this should be up in the MacroAssembler layer. :-(
2722         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2723         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2724         
2725         ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
2726                || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
2727
2728         if (canBeJumpT4(instruction, target)) {
2729             // There may be a better way to fix this, but right now put the NOPs first, since in the
2730             // case of an conditional branch this will be coming after an ITTT predicating *three*
2731             // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
2732             // variable wdith encoding - the previous instruction might *look* like an ITTT but
2733             // actually be the second half of a 2-word op.
2734             uint16_t instructions[3];
2735             instructions[0] = OP_NOP_T1;
2736             instructions[1] = OP_NOP_T2a;
2737             instructions[2] = OP_NOP_T2b;
2738             performJITMemcpy(writeTarget - 5, instructions, 3 * sizeof(uint16_t));
2739             linkJumpT4(writeTarget, instruction, target);
2740         } else {
2741             const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2742             ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2743             ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2744
2745             uint16_t instructions[5];
2746             instructions[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2747             instructions[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2748             instructions[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2749             instructions[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2750             instructions[4] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2751             performJITMemcpy(writeTarget - 5, instructions, 5 * sizeof(uint16_t));
2752         }
2753     }
2754     
2755     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
2756     {
2757         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
2758     }
2759
2760     static void decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(ARMThumbImmediate& result, uint16_t value)
2761     {
2762         result.m_value.i = (value >> 10) & 1;
2763         result.m_value.imm4 = value & 15;
2764     }
2765
2766     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
2767     {
2768         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
2769     }
2770
2771     static void decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(ARMThumbImmediate& result, uint16_t value)
2772     {
2773         result.m_value.imm3 = (value >> 12) & 7;
2774         result.m_value.imm8 = value & 255;
2775     }
2776
2777     class ARMInstructionFormatter {
2778     public:
2779         ALWAYS_INLINE void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
2780         {
2781             m_buffer.putShort(op | (rd << 8) | imm);
2782         }
2783         
2784         ALWAYS_INLINE void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
2785         {
2786             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
2787         }
2788
2789         ALWAYS_INLINE void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
2790         {
2791             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
2792         }
2793
2794         ALWAYS_INLINE void oneWordOp7Imm9(OpcodeID op, uint16_t imm)
2795         {
2796             m_buffer.putShort(op | imm);
2797         }
2798
2799         ALWAYS_INLINE void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
2800         {
2801             m_buffer.putShort(op | imm);
2802         }
2803
2804         ALWAYS_INLINE void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
2805         {
2806             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
2807         }
2808
2809         ALWAYS_INLINE void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
2810         {
2811             m_buffer.putShort(op | imm);
2812         }
2813
2814         ALWAYS_INLINE void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
2815         {
2816             m_buffer.putShort(op | (reg1 << 3) | reg2);
2817         }
2818
2819         ALWAYS_INLINE void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
2820         {
2821             m_buffer.putShort(op | reg);
2822             m_buffer.putShort(ff.m_u.value);
2823         }
2824         
2825         ALWAYS_INLINE void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
2826         {
2827             m_buffer.putShort(op);
2828             m_buffer.putShort(ff.m_u.value);
2829         }
2830         
2831         ALWAYS_INLINE void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
2832         {
2833             m_buffer.putShort(op1);
2834             m_buffer.putShort(op2);
2835         }
2836
2837         ALWAYS_INLINE void twoWordOp16Imm16(OpcodeID1 op1, uint16_t imm)
2838         {
2839             m_buffer.putShort(op1);
2840             m_buffer.putShort(imm);
2841         }
2842         
2843         ALWAYS_INLINE void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
2844         {
2845             ARMThumbImmediate newImm = imm;
2846             newImm.m_value.imm4 = imm4;
2847
2848             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
2849             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
2850         }
2851
2852         ALWAYS_INLINE void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
2853         {
2854             m_buffer.putShort(op | reg1);
2855             m_buffer.putShort((reg2 << 12) | imm);
2856         }
2857
2858         ALWAYS_INLINE void twoWordOp12Reg40Imm3Reg4Imm20Imm5(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm1, uint16_t imm2, uint16_t imm3)
2859         {
2860             m_buffer.putShort(op | reg1);
2861             m_buffer.putShort((imm1 << 12) | (reg2 << 8) | (imm2 << 6) | imm3);
2862         }
2863
2864         // Formats up instructions of the pattern:
2865         //    111111111B11aaaa:bbbb222SA2C2cccc
2866         // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
2867         // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
2868         ALWAYS_INLINE void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
2869         {
2870             ASSERT(!(op1 & 0x004f));
2871             ASSERT(!(op2 & 0xf1af));
2872             m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4());
2873             m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4());
2874         }
2875
2876         // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
2877         // (i.e. +/-(0..255) 32-bit words)
2878         ALWAYS_INLINE void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
2879         {
2880             bool up = true;
2881             if (imm < 0) {
2882                 imm = -imm;
2883                 up = false;
2884             }
2885             
2886             uint32_t offset = imm;
2887             ASSERT(!(offset & ~0x3fc));
2888             offset >>= 2;
2889
2890             m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn);
2891             m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset);
2892         }
2893
2894         // Administrative methods:
2895
2896         size_t codeSize() const { return m_buffer.codeSize(); }
2897         AssemblerLabel label() const { return m_buffer.label(); }
2898         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
2899         void* data() const { return m_buffer.data(); }
2900
2901         unsigned debugOffset() { return m_buffer.debugOffset(); }
2902
2903         AssemblerBuffer m_buffer;
2904     } m_formatter;
2905
2906     Vector<LinkRecord, 0, UnsafeVectorOverflow> m_jumpsToLink;
2907     int m_indexOfLastWatchpoint;
2908     int m_indexOfTailOfLastWatchpoint;
2909 };
2910
2911 } // namespace JSC
2912
2913 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)