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