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