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