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