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