initial import
[vuplus_webkit] / Source / JavaScriptCore / assembler / ARMv7Assembler.h
1 /*
2  * Copyright (C) 2009, 2010 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     ~ARMv7Assembler()
418     {
419         ASSERT(m_jumpsToLink.isEmpty());
420     }
421
422     typedef ARMRegisters::RegisterID RegisterID;
423     typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
424     typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
425     typedef ARMRegisters::FPQuadRegisterID FPQuadRegisterID;
426
427     // (HS, LO, HI, LS) -> (AE, B, A, BE)
428     // (VS, VC) -> (O, NO)
429     typedef enum {
430         ConditionEQ,
431         ConditionNE,
432         ConditionHS, ConditionCS = ConditionHS,
433         ConditionLO, ConditionCC = ConditionLO,
434         ConditionMI,
435         ConditionPL,
436         ConditionVS,
437         ConditionVC,
438         ConditionHI,
439         ConditionLS,
440         ConditionGE,
441         ConditionLT,
442         ConditionGT,
443         ConditionLE,
444         ConditionAL,
445         ConditionInvalid
446     } Condition;
447
448 #define JUMP_ENUM_WITH_SIZE(index, value) (((value) << 3) | (index))
449 #define JUMP_ENUM_SIZE(jump) ((jump) >> 3) 
450     enum JumpType { JumpFixed = JUMP_ENUM_WITH_SIZE(0, 0), 
451                     JumpNoCondition = JUMP_ENUM_WITH_SIZE(1, 5 * sizeof(uint16_t)),
452                     JumpCondition = JUMP_ENUM_WITH_SIZE(2, 6 * sizeof(uint16_t)),
453                     JumpNoConditionFixedSize = JUMP_ENUM_WITH_SIZE(3, 5 * sizeof(uint16_t)),
454                     JumpConditionFixedSize = JUMP_ENUM_WITH_SIZE(4, 6 * sizeof(uint16_t))
455     };
456     enum JumpLinkType { 
457         LinkInvalid = JUMP_ENUM_WITH_SIZE(0, 0),
458         LinkJumpT1 = JUMP_ENUM_WITH_SIZE(1, sizeof(uint16_t)),
459         LinkJumpT2 = JUMP_ENUM_WITH_SIZE(2, sizeof(uint16_t)),
460         LinkJumpT3 = JUMP_ENUM_WITH_SIZE(3, 2 * sizeof(uint16_t)),
461         LinkJumpT4 = JUMP_ENUM_WITH_SIZE(4, 2 * sizeof(uint16_t)),
462         LinkConditionalJumpT4 = JUMP_ENUM_WITH_SIZE(5, 3 * sizeof(uint16_t)),
463         LinkBX = JUMP_ENUM_WITH_SIZE(6, 5 * sizeof(uint16_t)),
464         LinkConditionalBX = JUMP_ENUM_WITH_SIZE(7, 6 * sizeof(uint16_t))
465     };
466
467     class LinkRecord {
468     public:
469         LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
470             : m_from(from)
471             , m_to(to)
472             , m_type(type)
473             , m_linkType(LinkInvalid)
474             , m_condition(condition)
475         {
476         }
477         intptr_t from() const { return m_from; }
478         void setFrom(intptr_t from) { m_from = from; }
479         intptr_t to() const { return m_to; }
480         JumpType type() const { return m_type; }
481         JumpLinkType linkType() const { return m_linkType; }
482         void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; }
483         Condition condition() const { return m_condition; }
484     private:
485         intptr_t m_from : 31;
486         intptr_t m_to : 31;
487         JumpType m_type : 8;
488         JumpLinkType m_linkType : 8;
489         Condition m_condition : 16;
490     };
491
492 private:
493
494     // ARMv7, Appx-A.6.3
495     bool BadReg(RegisterID reg)
496     {
497         return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
498     }
499
500     uint32_t singleRegisterMask(FPSingleRegisterID rdNum, int highBitsShift, int lowBitShift)
501     {
502         uint32_t rdMask = (rdNum >> 1) << highBitsShift;
503         if (rdNum & 1)
504             rdMask |= 1 << lowBitShift;
505         return rdMask;
506     }
507
508     uint32_t doubleRegisterMask(FPDoubleRegisterID rdNum, int highBitShift, int lowBitsShift)
509     {
510         uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
511         if (rdNum & 16)
512             rdMask |= 1 << highBitShift;
513         return rdMask;
514     }
515
516     typedef enum {
517         OP_ADD_reg_T1       = 0x1800,
518         OP_SUB_reg_T1       = 0x1A00,
519         OP_ADD_imm_T1       = 0x1C00,
520         OP_SUB_imm_T1       = 0x1E00,
521         OP_MOV_imm_T1       = 0x2000,
522         OP_CMP_imm_T1       = 0x2800,
523         OP_ADD_imm_T2       = 0x3000,
524         OP_SUB_imm_T2       = 0x3800,
525         OP_AND_reg_T1       = 0x4000,
526         OP_EOR_reg_T1       = 0x4040,
527         OP_TST_reg_T1       = 0x4200,
528         OP_RSB_imm_T1       = 0x4240,
529         OP_CMP_reg_T1       = 0x4280,
530         OP_ORR_reg_T1       = 0x4300,
531         OP_MVN_reg_T1       = 0x43C0,
532         OP_ADD_reg_T2       = 0x4400,
533         OP_MOV_reg_T1       = 0x4600,
534         OP_BLX              = 0x4700,
535         OP_BX               = 0x4700,
536         OP_STR_reg_T1       = 0x5000,
537         OP_LDR_reg_T1       = 0x5800,
538         OP_LDRH_reg_T1      = 0x5A00,
539         OP_LDRB_reg_T1      = 0x5C00,
540         OP_STR_imm_T1       = 0x6000,
541         OP_LDR_imm_T1       = 0x6800,
542         OP_LDRB_imm_T1      = 0x7800,
543         OP_LDRH_imm_T1      = 0x8800,
544         OP_STR_imm_T2       = 0x9000,
545         OP_LDR_imm_T2       = 0x9800,
546         OP_ADD_SP_imm_T1    = 0xA800,
547         OP_ADD_SP_imm_T2    = 0xB000,
548         OP_SUB_SP_imm_T1    = 0xB080,
549         OP_BKPT             = 0xBE00,
550         OP_IT               = 0xBF00,
551         OP_NOP_T1           = 0xBF00,
552     } OpcodeID;
553
554     typedef enum {
555         OP_B_T1         = 0xD000,
556         OP_B_T2         = 0xE000,
557         OP_AND_reg_T2   = 0xEA00,
558         OP_TST_reg_T2   = 0xEA10,
559         OP_ORR_reg_T2   = 0xEA40,
560         OP_ORR_S_reg_T2 = 0xEA50,
561         OP_ASR_imm_T1   = 0xEA4F,
562         OP_LSL_imm_T1   = 0xEA4F,
563         OP_LSR_imm_T1   = 0xEA4F,
564         OP_ROR_imm_T1   = 0xEA4F,
565         OP_MVN_reg_T2   = 0xEA6F,
566         OP_EOR_reg_T2   = 0xEA80,
567         OP_ADD_reg_T3   = 0xEB00,
568         OP_ADD_S_reg_T3 = 0xEB10,
569         OP_SUB_reg_T2   = 0xEBA0,
570         OP_SUB_S_reg_T2 = 0xEBB0,
571         OP_CMP_reg_T2   = 0xEBB0,
572         OP_VSTR         = 0xED00,
573         OP_VLDR         = 0xED10,
574         OP_VMOV_StoC    = 0xEE00,
575         OP_VMOV_CtoS    = 0xEE10,
576         OP_VMUL_T2      = 0xEE20,
577         OP_VADD_T2      = 0xEE30,
578         OP_VSUB_T2      = 0xEE30,
579         OP_VDIV         = 0xEE80,
580         OP_VCMP         = 0xEEB0,
581         OP_VCVT_FPIVFP  = 0xEEB0,
582         OP_VMOV_IMM_T2  = 0xEEB0,
583         OP_VMRS         = 0xEEB0,
584         OP_B_T3a        = 0xF000,
585         OP_B_T4a        = 0xF000,
586         OP_AND_imm_T1   = 0xF000,
587         OP_TST_imm      = 0xF010,
588         OP_ORR_imm_T1   = 0xF040,
589         OP_MOV_imm_T2   = 0xF040,
590         OP_MVN_imm      = 0xF060,
591         OP_EOR_imm_T1   = 0xF080,
592         OP_ADD_imm_T3   = 0xF100,
593         OP_ADD_S_imm_T3 = 0xF110,
594         OP_CMN_imm      = 0xF110,
595         OP_SUB_imm_T3   = 0xF1A0,
596         OP_SUB_S_imm_T3 = 0xF1B0,
597         OP_CMP_imm_T2   = 0xF1B0,
598         OP_RSB_imm_T2   = 0xF1C0,
599         OP_ADD_imm_T4   = 0xF200,
600         OP_MOV_imm_T3   = 0xF240,
601         OP_SUB_imm_T4   = 0xF2A0,
602         OP_MOVT         = 0xF2C0,
603         OP_UBFX_T1      = 0xF3C0,
604         OP_NOP_T2a      = 0xF3AF,
605         OP_LDRB_imm_T3  = 0xF810,
606         OP_LDRB_reg_T2  = 0xF810,
607         OP_LDRH_reg_T2  = 0xF830,
608         OP_LDRH_imm_T3  = 0xF830,
609         OP_STR_imm_T4   = 0xF840,
610         OP_STR_reg_T2   = 0xF840,
611         OP_LDR_imm_T4   = 0xF850,
612         OP_LDR_reg_T2   = 0xF850,
613         OP_LDRB_imm_T2  = 0xF890,
614         OP_LDRH_imm_T2  = 0xF8B0,
615         OP_STR_imm_T3   = 0xF8C0,
616         OP_LDR_imm_T3   = 0xF8D0,
617         OP_LSL_reg_T2   = 0xFA00,
618         OP_LSR_reg_T2   = 0xFA20,
619         OP_ASR_reg_T2   = 0xFA40,
620         OP_ROR_reg_T2   = 0xFA60,
621         OP_CLZ          = 0xFAB0,
622         OP_SMULL_T1     = 0xFB80,
623     } OpcodeID1;
624
625     typedef enum {
626         OP_VADD_T2b     = 0x0A00,
627         OP_VDIVb        = 0x0A00,
628         OP_VLDRb        = 0x0A00,
629         OP_VMOV_IMM_T2b = 0x0A00,
630         OP_VMUL_T2b     = 0x0A00,
631         OP_VSTRb        = 0x0A00,
632         OP_VMOV_CtoSb   = 0x0A10,
633         OP_VMOV_StoCb   = 0x0A10,
634         OP_VMRSb        = 0x0A10,
635         OP_VCMPb        = 0x0A40,
636         OP_VCVT_FPIVFPb = 0x0A40,
637         OP_VSUB_T2b     = 0x0A40,
638         OP_NOP_T2b      = 0x8000,
639         OP_B_T3b        = 0x8000,
640         OP_B_T4b        = 0x9000,
641     } OpcodeID2;
642
643     struct FourFours {
644         FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
645         {
646             m_u.f0 = f0;
647             m_u.f1 = f1;
648             m_u.f2 = f2;
649             m_u.f3 = f3;
650         }
651
652         union {
653             unsigned value;
654             struct {
655                 unsigned f0 : 4;
656                 unsigned f1 : 4;
657                 unsigned f2 : 4;
658                 unsigned f3 : 4;
659             };
660         } m_u;
661     };
662
663     class ARMInstructionFormatter;
664
665     // false means else!
666     bool ifThenElseConditionBit(Condition condition, bool isIf)
667     {
668         return isIf ? (condition & 1) : !(condition & 1);
669     }
670     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
671     {
672         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
673             | (ifThenElseConditionBit(condition, inst3if) << 2)
674             | (ifThenElseConditionBit(condition, inst4if) << 1)
675             | 1;
676         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
677         return (condition << 4) | mask;
678     }
679     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
680     {
681         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
682             | (ifThenElseConditionBit(condition, inst3if) << 2)
683             | 2;
684         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
685         return (condition << 4) | mask;
686     }
687     uint8_t ifThenElse(Condition condition, bool inst2if)
688     {
689         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
690             | 4;
691         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
692         return (condition << 4) | mask;
693     }
694
695     uint8_t ifThenElse(Condition condition)
696     {
697         int mask = 8;
698         return (condition << 4) | mask;
699     }
700
701 public:
702     
703     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
704     {
705         // Rd can only be SP if Rn is also SP.
706         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
707         ASSERT(rd != ARMRegisters::pc);
708         ASSERT(rn != ARMRegisters::pc);
709         ASSERT(imm.isValid());
710
711         if (rn == ARMRegisters::sp) {
712             if (!(rd & 8) && imm.isUInt10()) {
713                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, static_cast<uint8_t>(imm.getUInt10() >> 2));
714                 return;
715             } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
716                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, static_cast<uint8_t>(imm.getUInt9() >> 2));
717                 return;
718             }
719         } else if (!((rd | rn) & 8)) {
720             if (imm.isUInt3()) {
721                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
722                 return;
723             } else if ((rd == rn) && imm.isUInt8()) {
724                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
725                 return;
726             }
727         }
728
729         if (imm.isEncodedImm())
730             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
731         else {
732             ASSERT(imm.isUInt12());
733             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
734         }
735     }
736
737     ALWAYS_INLINE void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
738     {
739         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
740         ASSERT(rd != ARMRegisters::pc);
741         ASSERT(rn != ARMRegisters::pc);
742         ASSERT(!BadReg(rm));
743         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
744     }
745
746     // NOTE: In an IT block, add doesn't modify the flags register.
747     ALWAYS_INLINE void add(RegisterID rd, RegisterID rn, RegisterID rm)
748     {
749         if (rd == rn)
750             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
751         else if (rd == rm)
752             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
753         else if (!((rd | rn | rm) & 8))
754             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
755         else
756             add(rd, rn, rm, ShiftTypeAndAmount());
757     }
758
759     // Not allowed in an IT (if then) block.
760     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
761     {
762         // Rd can only be SP if Rn is also SP.
763         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
764         ASSERT(rd != ARMRegisters::pc);
765         ASSERT(rn != ARMRegisters::pc);
766         ASSERT(imm.isEncodedImm());
767
768         if (!((rd | rn) & 8)) {
769             if (imm.isUInt3()) {
770                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
771                 return;
772             } else if ((rd == rn) && imm.isUInt8()) {
773                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
774                 return;
775             }
776         }
777
778         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
779     }
780
781     // Not allowed in an IT (if then) block?
782     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
783     {
784         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
785         ASSERT(rd != ARMRegisters::pc);
786         ASSERT(rn != ARMRegisters::pc);
787         ASSERT(!BadReg(rm));
788         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
789     }
790
791     // Not allowed in an IT (if then) block.
792     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
793     {
794         if (!((rd | rn | rm) & 8))
795             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
796         else
797             add_S(rd, rn, rm, ShiftTypeAndAmount());
798     }
799
800     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
801     {
802         ASSERT(!BadReg(rd));
803         ASSERT(!BadReg(rn));
804         ASSERT(imm.isEncodedImm());
805         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
806     }
807
808     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
809     {
810         ASSERT(!BadReg(rd));
811         ASSERT(!BadReg(rn));
812         ASSERT(!BadReg(rm));
813         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
814     }
815
816     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
817     {
818         if ((rd == rn) && !((rd | rm) & 8))
819             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
820         else if ((rd == rm) && !((rd | rn) & 8))
821             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
822         else
823             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
824     }
825
826     ALWAYS_INLINE void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
827     {
828         ASSERT(!BadReg(rd));
829         ASSERT(!BadReg(rm));
830         ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
831         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
832     }
833
834     ALWAYS_INLINE void asr(RegisterID rd, RegisterID rn, RegisterID rm)
835     {
836         ASSERT(!BadReg(rd));
837         ASSERT(!BadReg(rn));
838         ASSERT(!BadReg(rm));
839         m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
840     }
841     
842     // Only allowed in IT (if then) block if last instruction.
843     ALWAYS_INLINE AssemblerLabel b()
844     {
845         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
846         return m_formatter.label();
847     }
848     
849     // Only allowed in IT (if then) block if last instruction.
850     ALWAYS_INLINE AssemblerLabel blx(RegisterID rm)
851     {
852         ASSERT(rm != ARMRegisters::pc);
853         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
854         return m_formatter.label();
855     }
856
857     // Only allowed in IT (if then) block if last instruction.
858     ALWAYS_INLINE AssemblerLabel bx(RegisterID rm)
859     {
860         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
861         return m_formatter.label();
862     }
863
864     void bkpt(uint8_t imm=0)
865     {
866         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
867     }
868
869     ALWAYS_INLINE void clz(RegisterID rd, RegisterID rm)
870     {
871         ASSERT(!BadReg(rd));
872         ASSERT(!BadReg(rm));
873         m_formatter.twoWordOp12Reg4FourFours(OP_CLZ, rm, FourFours(0xf, rd, 8, rm));
874     }
875
876     ALWAYS_INLINE void cmn(RegisterID rn, ARMThumbImmediate imm)
877     {
878         ASSERT(rn != ARMRegisters::pc);
879         ASSERT(imm.isEncodedImm());
880
881         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
882     }
883
884     ALWAYS_INLINE void cmp(RegisterID rn, ARMThumbImmediate imm)
885     {
886         ASSERT(rn != ARMRegisters::pc);
887         ASSERT(imm.isEncodedImm());
888
889         if (!(rn & 8) && imm.isUInt8())
890             m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
891         else
892             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
893     }
894
895     ALWAYS_INLINE void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
896     {
897         ASSERT(rn != ARMRegisters::pc);
898         ASSERT(!BadReg(rm));
899         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
900     }
901
902     ALWAYS_INLINE void cmp(RegisterID rn, RegisterID rm)
903     {
904         if ((rn | rm) & 8)
905             cmp(rn, rm, ShiftTypeAndAmount());
906         else
907             m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
908     }
909
910     // xor is not spelled with an 'e'. :-(
911     ALWAYS_INLINE void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
912     {
913         ASSERT(!BadReg(rd));
914         ASSERT(!BadReg(rn));
915         ASSERT(imm.isEncodedImm());
916         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
917     }
918
919     // xor is not spelled with an 'e'. :-(
920     ALWAYS_INLINE void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
921     {
922         ASSERT(!BadReg(rd));
923         ASSERT(!BadReg(rn));
924         ASSERT(!BadReg(rm));
925         m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
926     }
927
928     // xor is not spelled with an 'e'. :-(
929     void eor(RegisterID rd, RegisterID rn, RegisterID rm)
930     {
931         if ((rd == rn) && !((rd | rm) & 8))
932             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
933         else if ((rd == rm) && !((rd | rn) & 8))
934             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
935         else
936             eor(rd, rn, rm, ShiftTypeAndAmount());
937     }
938
939     ALWAYS_INLINE void it(Condition cond)
940     {
941         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
942     }
943
944     ALWAYS_INLINE void it(Condition cond, bool inst2if)
945     {
946         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
947     }
948
949     ALWAYS_INLINE void it(Condition cond, bool inst2if, bool inst3if)
950     {
951         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
952     }
953
954     ALWAYS_INLINE void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
955     {
956         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
957     }
958
959     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
960     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
961     {
962         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
963         ASSERT(imm.isUInt12());
964
965         if (!((rt | rn) & 8) && imm.isUInt7())
966             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
967         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
968             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, static_cast<uint8_t>(imm.getUInt10() >> 2));
969         else
970             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
971     }
972
973     ALWAYS_INLINE void ldrCompact(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
974     {
975         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
976         ASSERT(imm.isUInt7());
977         ASSERT(!((rt | rn) & 8));
978         m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
979     }
980
981     // If index is set, this is a regular offset or a pre-indexed load;
982     // if index is not set then is is a post-index load.
983     //
984     // If wback is set rn is updated - this is a pre or post index load,
985     // if wback is not set this is a regular offset memory access.
986     //
987     // (-255 <= offset <= 255)
988     // _reg = REG[rn]
989     // _tmp = _reg + offset
990     // MEM[index ? _tmp : _reg] = REG[rt]
991     // if (wback) REG[rn] = _tmp
992     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
993     {
994         ASSERT(rt != ARMRegisters::pc);
995         ASSERT(rn != ARMRegisters::pc);
996         ASSERT(index || wback);
997         ASSERT(!wback | (rt != rn));
998     
999         bool add = true;
1000         if (offset < 0) {
1001             add = false;
1002             offset = -offset;
1003         }
1004         ASSERT((offset & ~0xff) == 0);
1005         
1006         offset |= (wback << 8);
1007         offset |= (add   << 9);
1008         offset |= (index << 10);
1009         offset |= (1 << 11);
1010         
1011         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
1012     }
1013
1014     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1015     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1016     {
1017         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1018         ASSERT(!BadReg(rm));
1019         ASSERT(shift <= 3);
1020
1021         if (!shift && !((rt | rn | rm) & 8))
1022             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
1023         else
1024             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1025     }
1026
1027     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1028     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1029     {
1030         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1031         ASSERT(imm.isUInt12());
1032
1033         if (!((rt | rn) & 8) && imm.isUInt6())
1034             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
1035         else
1036             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
1037     }
1038
1039     // If index is set, this is a regular offset or a pre-indexed load;
1040     // if index is not set then is is a post-index load.
1041     //
1042     // If wback is set rn is updated - this is a pre or post index load,
1043     // if wback is not set this is a regular offset memory access.
1044     //
1045     // (-255 <= offset <= 255)
1046     // _reg = REG[rn]
1047     // _tmp = _reg + offset
1048     // MEM[index ? _tmp : _reg] = REG[rt]
1049     // if (wback) REG[rn] = _tmp
1050     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1051     {
1052         ASSERT(rt != ARMRegisters::pc);
1053         ASSERT(rn != ARMRegisters::pc);
1054         ASSERT(index || wback);
1055         ASSERT(!wback | (rt != rn));
1056     
1057         bool add = true;
1058         if (offset < 0) {
1059             add = false;
1060             offset = -offset;
1061         }
1062         ASSERT((offset & ~0xff) == 0);
1063         
1064         offset |= (wback << 8);
1065         offset |= (add   << 9);
1066         offset |= (index << 10);
1067         offset |= (1 << 11);
1068         
1069         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
1070     }
1071
1072     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1073     {
1074         ASSERT(!BadReg(rt));   // Memory hint
1075         ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
1076         ASSERT(!BadReg(rm));
1077         ASSERT(shift <= 3);
1078
1079         if (!shift && !((rt | rn | rm) & 8))
1080             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
1081         else
1082             m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1083     }
1084
1085     void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1086     {
1087         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1088         ASSERT(imm.isUInt12());
1089
1090         if (!((rt | rn) & 8) && imm.isUInt5())
1091             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
1092         else
1093             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
1094     }
1095
1096     void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1097     {
1098         ASSERT(rt != ARMRegisters::pc);
1099         ASSERT(rn != ARMRegisters::pc);
1100         ASSERT(index || wback);
1101         ASSERT(!wback | (rt != rn));
1102
1103         bool add = true;
1104         if (offset < 0) {
1105             add = false;
1106             offset = -offset;
1107         }
1108
1109         ASSERT(!(offset & ~0xff));
1110
1111         offset |= (wback << 8);
1112         offset |= (add   << 9);
1113         offset |= (index << 10);
1114         offset |= (1 << 11);
1115
1116         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
1117     }
1118
1119     ALWAYS_INLINE void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1120     {
1121         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1122         ASSERT(!BadReg(rm));
1123         ASSERT(shift <= 3);
1124
1125         if (!shift && !((rt | rn | rm) & 8))
1126             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
1127         else
1128             m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1129     }
1130
1131     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1132     {
1133         ASSERT(!BadReg(rd));
1134         ASSERT(!BadReg(rm));
1135         ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
1136         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1137     }
1138
1139     ALWAYS_INLINE void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
1140     {
1141         ASSERT(!BadReg(rd));
1142         ASSERT(!BadReg(rn));
1143         ASSERT(!BadReg(rm));
1144         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1145     }
1146
1147     ALWAYS_INLINE void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1148     {
1149         ASSERT(!BadReg(rd));
1150         ASSERT(!BadReg(rm));
1151         ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
1152         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1153     }
1154
1155     ALWAYS_INLINE void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
1156     {
1157         ASSERT(!BadReg(rd));
1158         ASSERT(!BadReg(rn));
1159         ASSERT(!BadReg(rm));
1160         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1161     }
1162
1163     ALWAYS_INLINE void movT3(RegisterID rd, ARMThumbImmediate imm)
1164     {
1165         ASSERT(imm.isValid());
1166         ASSERT(!imm.isEncodedImm());
1167         ASSERT(!BadReg(rd));
1168         
1169         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
1170     }
1171
1172     ALWAYS_INLINE void mov(RegisterID rd, ARMThumbImmediate imm)
1173     {
1174         ASSERT(imm.isValid());
1175         ASSERT(!BadReg(rd));
1176         
1177         if ((rd < 8) && imm.isUInt8())
1178             m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
1179         else if (imm.isEncodedImm())
1180             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
1181         else
1182             movT3(rd, imm);
1183     }
1184
1185     ALWAYS_INLINE void mov(RegisterID rd, RegisterID rm)
1186     {
1187         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
1188     }
1189
1190     ALWAYS_INLINE void movt(RegisterID rd, ARMThumbImmediate imm)
1191     {
1192         ASSERT(imm.isUInt16());
1193         ASSERT(!BadReg(rd));
1194         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
1195     }
1196
1197     ALWAYS_INLINE void mvn(RegisterID rd, ARMThumbImmediate imm)
1198     {
1199         ASSERT(imm.isEncodedImm());
1200         ASSERT(!BadReg(rd));
1201         
1202         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
1203     }
1204
1205     ALWAYS_INLINE void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
1206     {
1207         ASSERT(!BadReg(rd));
1208         ASSERT(!BadReg(rm));
1209         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1210     }
1211
1212     ALWAYS_INLINE void mvn(RegisterID rd, RegisterID rm)
1213     {
1214         if (!((rd | rm) & 8))
1215             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
1216         else
1217             mvn(rd, rm, ShiftTypeAndAmount());
1218     }
1219
1220     ALWAYS_INLINE void neg(RegisterID rd, RegisterID rm)
1221     {
1222         ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
1223         sub(rd, zero, rm);
1224     }
1225
1226     ALWAYS_INLINE void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1227     {
1228         ASSERT(!BadReg(rd));
1229         ASSERT(!BadReg(rn));
1230         ASSERT(imm.isEncodedImm());
1231         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
1232     }
1233
1234     ALWAYS_INLINE void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1235     {
1236         ASSERT(!BadReg(rd));
1237         ASSERT(!BadReg(rn));
1238         ASSERT(!BadReg(rm));
1239         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1240     }
1241
1242     void orr(RegisterID rd, RegisterID rn, RegisterID rm)
1243     {
1244         if ((rd == rn) && !((rd | rm) & 8))
1245             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1246         else if ((rd == rm) && !((rd | rn) & 8))
1247             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1248         else
1249             orr(rd, rn, rm, ShiftTypeAndAmount());
1250     }
1251
1252     ALWAYS_INLINE void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1253     {
1254         ASSERT(!BadReg(rd));
1255         ASSERT(!BadReg(rn));
1256         ASSERT(!BadReg(rm));
1257         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1258     }
1259
1260     void orr_S(RegisterID rd, RegisterID rn, RegisterID rm)
1261     {
1262         if ((rd == rn) && !((rd | rm) & 8))
1263             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1264         else if ((rd == rm) && !((rd | rn) & 8))
1265             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1266         else
1267             orr_S(rd, rn, rm, ShiftTypeAndAmount());
1268     }
1269
1270     ALWAYS_INLINE void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1271     {
1272         ASSERT(!BadReg(rd));
1273         ASSERT(!BadReg(rm));
1274         ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
1275         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1276     }
1277
1278     ALWAYS_INLINE void ror(RegisterID rd, RegisterID rn, RegisterID rm)
1279     {
1280         ASSERT(!BadReg(rd));
1281         ASSERT(!BadReg(rn));
1282         ASSERT(!BadReg(rm));
1283         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1284     }
1285
1286     ALWAYS_INLINE void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
1287     {
1288         ASSERT(!BadReg(rdLo));
1289         ASSERT(!BadReg(rdHi));
1290         ASSERT(!BadReg(rn));
1291         ASSERT(!BadReg(rm));
1292         ASSERT(rdLo != rdHi);
1293         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
1294     }
1295
1296     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1297     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1298     {
1299         ASSERT(rt != ARMRegisters::pc);
1300         ASSERT(rn != ARMRegisters::pc);
1301         ASSERT(imm.isUInt12());
1302
1303         if (!((rt | rn) & 8) && imm.isUInt7())
1304             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1305         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1306             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, static_cast<uint8_t>(imm.getUInt10() >> 2));
1307         else
1308             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
1309     }
1310
1311     // If index is set, this is a regular offset or a pre-indexed store;
1312     // if index is not set then is is a post-index store.
1313     //
1314     // If wback is set rn is updated - this is a pre or post index store,
1315     // if wback is not set this is a regular offset memory access.
1316     //
1317     // (-255 <= offset <= 255)
1318     // _reg = REG[rn]
1319     // _tmp = _reg + offset
1320     // MEM[index ? _tmp : _reg] = REG[rt]
1321     // if (wback) REG[rn] = _tmp
1322     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1323     {
1324         ASSERT(rt != ARMRegisters::pc);
1325         ASSERT(rn != ARMRegisters::pc);
1326         ASSERT(index || wback);
1327         ASSERT(!wback | (rt != rn));
1328     
1329         bool add = true;
1330         if (offset < 0) {
1331             add = false;
1332             offset = -offset;
1333         }
1334         ASSERT((offset & ~0xff) == 0);
1335         
1336         offset |= (wback << 8);
1337         offset |= (add   << 9);
1338         offset |= (index << 10);
1339         offset |= (1 << 11);
1340         
1341         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
1342     }
1343
1344     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1345     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1346     {
1347         ASSERT(rn != ARMRegisters::pc);
1348         ASSERT(!BadReg(rm));
1349         ASSERT(shift <= 3);
1350
1351         if (!shift && !((rt | rn | rm) & 8))
1352             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
1353         else
1354             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1355     }
1356
1357     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1358     {
1359         // Rd can only be SP if Rn is also SP.
1360         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1361         ASSERT(rd != ARMRegisters::pc);
1362         ASSERT(rn != ARMRegisters::pc);
1363         ASSERT(imm.isValid());
1364
1365         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1366             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
1367             return;
1368         } else if (!((rd | rn) & 8)) {
1369             if (imm.isUInt3()) {
1370                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1371                 return;
1372             } else if ((rd == rn) && imm.isUInt8()) {
1373                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1374                 return;
1375             }
1376         }
1377
1378         if (imm.isEncodedImm())
1379             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
1380         else {
1381             ASSERT(imm.isUInt12());
1382             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
1383         }
1384     }
1385
1386     ALWAYS_INLINE void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
1387     {
1388         ASSERT(rd != ARMRegisters::pc);
1389         ASSERT(rn != ARMRegisters::pc);
1390         ASSERT(imm.isValid());
1391         ASSERT(imm.isUInt12());
1392
1393         if (!((rd | rn) & 8) && !imm.getUInt12())
1394             m_formatter.oneWordOp10Reg3Reg3(OP_RSB_imm_T1, rn, rd);
1395         else
1396             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
1397     }
1398
1399     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1400     {
1401         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1402         ASSERT(rd != ARMRegisters::pc);
1403         ASSERT(rn != ARMRegisters::pc);
1404         ASSERT(!BadReg(rm));
1405         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1406     }
1407
1408     // NOTE: In an IT block, add doesn't modify the flags register.
1409     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, RegisterID rm)
1410     {
1411         if (!((rd | rn | rm) & 8))
1412             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1413         else
1414             sub(rd, rn, rm, ShiftTypeAndAmount());
1415     }
1416
1417     // Not allowed in an IT (if then) block.
1418     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1419     {
1420         // Rd can only be SP if Rn is also SP.
1421         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1422         ASSERT(rd != ARMRegisters::pc);
1423         ASSERT(rn != ARMRegisters::pc);
1424         ASSERT(imm.isValid());
1425
1426         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1427             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
1428             return;
1429         } else if (!((rd | rn) & 8)) {
1430             if (imm.isUInt3()) {
1431                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1432                 return;
1433             } else if ((rd == rn) && imm.isUInt8()) {
1434                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1435                 return;
1436             }
1437         }
1438
1439         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
1440     }
1441
1442     // Not allowed in an IT (if then) block?
1443     ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1444     {
1445         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1446         ASSERT(rd != ARMRegisters::pc);
1447         ASSERT(rn != ARMRegisters::pc);
1448         ASSERT(!BadReg(rm));
1449         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1450     }
1451
1452     // Not allowed in an IT (if then) block.
1453     ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
1454     {
1455         if (!((rd | rn | rm) & 8))
1456             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1457         else
1458             sub_S(rd, rn, rm, ShiftTypeAndAmount());
1459     }
1460
1461     ALWAYS_INLINE void tst(RegisterID rn, ARMThumbImmediate imm)
1462     {
1463         ASSERT(!BadReg(rn));
1464         ASSERT(imm.isEncodedImm());
1465
1466         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
1467     }
1468
1469     ALWAYS_INLINE void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1470     {
1471         ASSERT(!BadReg(rn));
1472         ASSERT(!BadReg(rm));
1473         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1474     }
1475
1476     ALWAYS_INLINE void tst(RegisterID rn, RegisterID rm)
1477     {
1478         if ((rn | rm) & 8)
1479             tst(rn, rm, ShiftTypeAndAmount());
1480         else
1481             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
1482     }
1483
1484     ALWAYS_INLINE void ubfx(RegisterID rd, RegisterID rn, unsigned lsb, unsigned width)
1485     {
1486         ASSERT(lsb < 32);
1487         ASSERT((width >= 1) && (width <= 32));
1488         ASSERT((lsb + width) <= 32);
1489         m_formatter.twoWordOp12Reg40Imm3Reg4Imm20Imm5(OP_UBFX_T1, rd, rn, (lsb & 0x1c) << 10, (lsb & 0x3) << 6, (width - 1) & 0x1f);
1490     }
1491
1492     void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1493     {
1494         m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
1495     }
1496
1497     void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1498     {
1499         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
1500     }
1501
1502     void vcmpz_F64(FPDoubleRegisterID rd)
1503     {
1504         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
1505     }
1506
1507     void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)
1508     {
1509         // boolean values are 64bit (toInt, unsigned, roundZero)
1510         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
1511     }
1512
1513     void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1514     {
1515         // boolean values are 64bit (toInt, unsigned, roundZero)
1516         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
1517     }
1518
1519     void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1520     {
1521         m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
1522     }
1523
1524     void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1525     {
1526         m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
1527     }
1528
1529     void vmov(RegisterID rd, FPSingleRegisterID rn)
1530     {
1531         ASSERT(!BadReg(rd));
1532         m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));
1533     }
1534
1535     void vmov(FPSingleRegisterID rd, RegisterID rn)
1536     {
1537         ASSERT(!BadReg(rn));
1538         m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0));
1539     }
1540
1541     void vmrs(RegisterID reg = ARMRegisters::pc)
1542     {
1543         ASSERT(reg != ARMRegisters::sp);
1544         m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
1545     }
1546
1547     void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1548     {
1549         m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
1550     }
1551
1552     void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1553     {
1554         m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
1555     }
1556
1557     void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1558     {
1559         m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
1560     }
1561
1562     void nop()
1563     {
1564         m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0);
1565     }
1566
1567     AssemblerLabel label()
1568     {
1569         return m_formatter.label();
1570     }
1571     
1572     AssemblerLabel align(int alignment)
1573     {
1574         while (!m_formatter.isAligned(alignment))
1575             bkpt();
1576
1577         return label();
1578     }
1579     
1580     static void* getRelocatedAddress(void* code, AssemblerLabel label)
1581     {
1582         ASSERT(label.isSet());
1583         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + label.m_offset);
1584     }
1585     
1586     static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
1587     {
1588         return b.m_offset - a.m_offset;
1589     }
1590
1591     int executableOffsetFor(int location)
1592     {
1593         if (!location)
1594             return 0;
1595         return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1];
1596     }
1597     
1598     int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JUMP_ENUM_SIZE(jumpType) - JUMP_ENUM_SIZE(jumpLinkType); }
1599     
1600     // Assembler admin methods:
1601
1602     static ALWAYS_INLINE bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
1603     {
1604         return a.from() < b.from();
1605     }
1606
1607     bool canCompact(JumpType jumpType)
1608     {
1609         // The following cannot be compacted:
1610         //   JumpFixed: represents custom jump sequence
1611         //   JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size
1612         //   JumpConditionFixedSize: represents conditional jump that must remain a fixed size
1613         return (jumpType == JumpNoCondition) || (jumpType == JumpCondition);
1614     }
1615     
1616     JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
1617     {
1618         if (jumpType == JumpFixed)
1619             return LinkInvalid;
1620         
1621         // for patchable jump we must leave space for the longest code sequence
1622         if (jumpType == JumpNoConditionFixedSize)
1623             return LinkBX;
1624         if (jumpType == JumpConditionFixedSize)
1625             return LinkConditionalBX;
1626         
1627         const int paddingSize = JUMP_ENUM_SIZE(jumpType);
1628         bool mayTriggerErrata = false;
1629         
1630         if (jumpType == JumpCondition) {
1631             // 2-byte conditional T1
1632             const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1)));
1633             if (canBeJumpT1(jumpT1Location, to))
1634                 return LinkJumpT1;
1635             // 4-byte conditional T3
1636             const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3)));
1637             if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) {
1638                 if (!mayTriggerErrata)
1639                     return LinkJumpT3;
1640             }
1641             // 4-byte conditional T4 with IT
1642             const uint16_t* conditionalJumpT4Location = 
1643             reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4)));
1644             if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) {
1645                 if (!mayTriggerErrata)
1646                     return LinkConditionalJumpT4;
1647             }
1648         } else {
1649             // 2-byte unconditional T2
1650             const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2)));
1651             if (canBeJumpT2(jumpT2Location, to))
1652                 return LinkJumpT2;
1653             // 4-byte unconditional T4
1654             const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4)));
1655             if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) {
1656                 if (!mayTriggerErrata)
1657                     return LinkJumpT4;
1658             }
1659             // use long jump sequence
1660             return LinkBX;
1661         }
1662         
1663         ASSERT(jumpType == JumpCondition);
1664         return LinkConditionalBX;
1665     }
1666     
1667     JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
1668     {
1669         JumpLinkType linkType = computeJumpType(record.type(), from, to);
1670         record.setLinkType(linkType);
1671         return linkType;
1672     }
1673     
1674     void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
1675     {
1676         int32_t ptr = regionStart / sizeof(int32_t);
1677         const int32_t end = regionEnd / sizeof(int32_t);
1678         int32_t* offsets = static_cast<int32_t*>(m_formatter.data());
1679         while (ptr < end)
1680             offsets[ptr++] = offset;
1681     }
1682     
1683     Vector<LinkRecord>& jumpsToLink()
1684     {
1685         std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
1686         return m_jumpsToLink;
1687     }
1688
1689     void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to)
1690     {
1691         switch (record.linkType()) {
1692         case LinkJumpT1:
1693             linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1694             break;
1695         case LinkJumpT2:
1696             linkJumpT2(reinterpret_cast<uint16_t*>(from), to);
1697             break;
1698         case LinkJumpT3:
1699             linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1700             break;
1701         case LinkJumpT4:
1702             linkJumpT4(reinterpret_cast<uint16_t*>(from), to);
1703             break;
1704         case LinkConditionalJumpT4:
1705             linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1706             break;
1707         case LinkConditionalBX:
1708             linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1709             break;
1710         case LinkBX:
1711             linkBX(reinterpret_cast<uint16_t*>(from), to);
1712             break;
1713         default:
1714             ASSERT_NOT_REACHED();
1715             break;
1716         }
1717     }
1718
1719     void* unlinkedCode() { return m_formatter.data(); }
1720     size_t codeSize() const { return m_formatter.codeSize(); }
1721
1722     static unsigned getCallReturnOffset(AssemblerLabel call)
1723     {
1724         ASSERT(call.isSet());
1725         return call.m_offset;
1726     }
1727
1728     // Linking & patching:
1729     //
1730     // 'link' and 'patch' methods are for use on unprotected code - such as the code
1731     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
1732     // code has been finalized it is (platform support permitting) within a non-
1733     // writable region of memory; to modify the code in an execute-only execuable
1734     // pool the 'repatch' and 'relink' methods should be used.
1735
1736     void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type, Condition condition)
1737     {
1738         ASSERT(to.isSet());
1739         ASSERT(from.isSet());
1740         m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, type, condition));
1741     }
1742
1743     static void linkJump(void* code, AssemblerLabel from, void* to)
1744     {
1745         ASSERT(from.isSet());
1746         
1747         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
1748         linkJumpAbsolute(location, to);
1749     }
1750
1751     static void linkCall(void* code, AssemblerLabel from, void* to)
1752     {
1753         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
1754         ASSERT(from.isSet());
1755         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1756
1757         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
1758     }
1759
1760     static void linkPointer(void* code, AssemblerLabel where, void* value)
1761     {
1762         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
1763     }
1764
1765     static void relinkJump(void* from, void* to)
1766     {
1767         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1768         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
1769
1770         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
1771
1772         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
1773     }
1774     
1775     static void relinkCall(void* from, void* to)
1776     {
1777         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1778         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1779
1780         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
1781     }
1782
1783     static void repatchInt32(void* where, int32_t value)
1784     {
1785         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1786         
1787         setInt32(where, value);
1788     }
1789     
1790     static void repatchCompact(void* where, int32_t value)
1791     {
1792         ASSERT(value >= 0);
1793         ASSERT(ARMThumbImmediate::makeUInt12(value).isUInt7());
1794         setUInt7ForLoad(where, ARMThumbImmediate::makeUInt12(value));
1795     }
1796
1797     static void repatchPointer(void* where, void* value)
1798     {
1799         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1800         
1801         setPointer(where, value);
1802     }
1803
1804     static void* readPointer(void* where)
1805     {
1806         return reinterpret_cast<void*>(readInt32(where));
1807     }
1808
1809 private:
1810     // VFP operations commonly take one or more 5-bit operands, typically representing a
1811     // floating point register number.  This will commonly be encoded in the instruction
1812     // in two parts, with one single bit field, and one 4-bit field.  In the case of
1813     // double precision operands the high bit of the register number will be encoded
1814     // separately, and for single precision operands the high bit of the register number
1815     // will be encoded individually.
1816     // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit
1817     // field to be encoded together in the instruction (the low 4-bits of a double
1818     // register number, or the high 4-bits of a single register number), and bit 4
1819     // contains the bit value to be encoded individually.
1820     struct VFPOperand {
1821         explicit VFPOperand(uint32_t value)
1822             : m_value(value)
1823         {
1824             ASSERT(!(m_value & ~0x1f));
1825         }
1826
1827         VFPOperand(FPDoubleRegisterID reg)
1828             : m_value(reg)
1829         {
1830         }
1831
1832         VFPOperand(RegisterID reg)
1833             : m_value(reg)
1834         {
1835         }
1836
1837         VFPOperand(FPSingleRegisterID reg)
1838             : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top.
1839         {
1840         }
1841
1842         uint32_t bits1()
1843         {
1844             return m_value >> 4;
1845         }
1846
1847         uint32_t bits4()
1848         {
1849             return m_value & 0xf;
1850         }
1851
1852         uint32_t m_value;
1853     };
1854
1855     VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero)
1856     {
1857         // Cannot specify rounding when converting to float.
1858         ASSERT(toInteger || !isRoundZero);
1859
1860         uint32_t op = 0x8;
1861         if (toInteger) {
1862             // opc2 indicates both toInteger & isUnsigned.
1863             op |= isUnsigned ? 0x4 : 0x5;
1864             // 'op' field in instruction is isRoundZero
1865             if (isRoundZero)
1866                 op |= 0x10;
1867         } else {
1868             // 'op' field in instruction is isUnsigned
1869             if (!isUnsigned)
1870                 op |= 0x10;
1871         }
1872         return VFPOperand(op);
1873     }
1874
1875     static void setInt32(void* code, uint32_t value)
1876     {
1877         uint16_t* location = reinterpret_cast<uint16_t*>(code);
1878         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
1879
1880         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
1881         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
1882         location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
1883         location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
1884         location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
1885         location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
1886
1887         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
1888     }
1889     
1890     static int32_t readInt32(void* code)
1891     {
1892         uint16_t* location = reinterpret_cast<uint16_t*>(code);
1893         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
1894         
1895         ARMThumbImmediate lo16;
1896         ARMThumbImmediate hi16;
1897         decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(lo16, location[-4]);
1898         decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(lo16, location[-3]);
1899         decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(hi16, location[-2]);
1900         decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(hi16, location[-1]);
1901         uint32_t result = hi16.asUInt16();
1902         result <<= 16;
1903         result |= lo16.asUInt16();
1904         return static_cast<int32_t>(result);
1905     }
1906
1907     static void setUInt7ForLoad(void* code, ARMThumbImmediate imm)
1908     {
1909         // Requires us to have planted a LDR_imm_T1
1910         ASSERT(imm.isValid());
1911         ASSERT(imm.isUInt7());
1912         uint16_t* location = reinterpret_cast<uint16_t*>(code);
1913         location[0] |= (imm.getUInt7() >> 2) << 6;
1914         ExecutableAllocator::cacheFlush(location, sizeof(uint16_t));
1915     }
1916
1917     static void setPointer(void* code, void* value)
1918     {
1919         setInt32(code, reinterpret_cast<uint32_t>(value));
1920     }
1921
1922     static bool isB(void* address)
1923     {
1924         uint16_t* instruction = static_cast<uint16_t*>(address);
1925         return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
1926     }
1927
1928     static bool isBX(void* address)
1929     {
1930         uint16_t* instruction = static_cast<uint16_t*>(address);
1931         return (instruction[0] & 0xff87) == OP_BX;
1932     }
1933
1934     static bool isMOV_imm_T3(void* address)
1935     {
1936         uint16_t* instruction = static_cast<uint16_t*>(address);
1937         return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
1938     }
1939
1940     static bool isMOVT(void* address)
1941     {
1942         uint16_t* instruction = static_cast<uint16_t*>(address);
1943         return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
1944     }
1945
1946     static bool isNOP_T1(void* address)
1947     {
1948         uint16_t* instruction = static_cast<uint16_t*>(address);
1949         return instruction[0] == OP_NOP_T1;
1950     }
1951
1952     static bool isNOP_T2(void* address)
1953     {
1954         uint16_t* instruction = static_cast<uint16_t*>(address);
1955         return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
1956     }
1957
1958     static bool canBeJumpT1(const uint16_t* instruction, const void* target)
1959     {
1960         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1961         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1962         
1963         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1964         // It does not appear to be documented in the ARM ARM (big surprise), but
1965         // for OP_B_T1 the branch displacement encoded in the instruction is 2 
1966         // less than the actual displacement.
1967         relative -= 2;
1968         return ((relative << 23) >> 23) == relative;
1969     }
1970     
1971     static bool canBeJumpT2(const uint16_t* instruction, const void* target)
1972     {
1973         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1974         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1975         
1976         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1977         // It does not appear to be documented in the ARM ARM (big surprise), but
1978         // for OP_B_T2 the branch displacement encoded in the instruction is 2 
1979         // less than the actual displacement.
1980         relative -= 2;
1981         return ((relative << 20) >> 20) == relative;
1982     }
1983     
1984     static bool canBeJumpT3(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
1985     {
1986         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1987         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1988         
1989         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1990         // From Cortex-A8 errata:
1991         // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
1992         // the target of the branch falls within the first region it is
1993         // possible for the processor to incorrectly determine the branch
1994         // instruction, and it is also possible in some cases for the processor
1995         // to enter a deadlock state.
1996         // The instruction is spanning two pages if it ends at an address ending 0x002
1997         bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
1998         mayTriggerErrata = spansTwo4K;
1999         // The target is in the first page if the jump branch back by [3..0x1002] bytes
2000         bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
2001         bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
2002         return ((relative << 11) >> 11) == relative && !wouldTriggerA8Errata;
2003     }
2004     
2005     static bool canBeJumpT4(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
2006     {
2007         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2008         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2009         
2010         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2011         // From Cortex-A8 errata:
2012         // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
2013         // the target of the branch falls within the first region it is
2014         // possible for the processor to incorrectly determine the branch
2015         // instruction, and it is also possible in some cases for the processor
2016         // to enter a deadlock state.
2017         // The instruction is spanning two pages if it ends at an address ending 0x002
2018         bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
2019         mayTriggerErrata = spansTwo4K;
2020         // The target is in the first page if the jump branch back by [3..0x1002] bytes
2021         bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
2022         bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
2023         return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata;
2024     }
2025     
2026     void linkJumpT1(Condition cond, uint16_t* instruction, void* target)
2027     {
2028         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2029         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2030         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2031         ASSERT(canBeJumpT1(instruction, target));
2032         
2033         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2034         // It does not appear to be documented in the ARM ARM (big surprise), but
2035         // for OP_B_T1 the branch displacement encoded in the instruction is 2 
2036         // less than the actual displacement.
2037         relative -= 2;
2038         
2039         // All branch offsets should be an even distance.
2040         ASSERT(!(relative & 1));
2041         instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1);
2042     }
2043     
2044     static void linkJumpT2(uint16_t* instruction, void* target)
2045     {
2046         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2047         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2048         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2049         ASSERT(canBeJumpT2(instruction, target));
2050         
2051         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2052         // It does not appear to be documented in the ARM ARM (big surprise), but
2053         // for OP_B_T2 the branch displacement encoded in the instruction is 2 
2054         // less than the actual displacement.
2055         relative -= 2;
2056         
2057         // All branch offsets should be an even distance.
2058         ASSERT(!(relative & 1));
2059         instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1);
2060     }
2061     
2062     void linkJumpT3(Condition cond, uint16_t* instruction, void* target)
2063     {
2064         // FIMXE: this should be up in the MacroAssembler layer. :-(
2065         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2066         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2067         bool scratch;
2068         UNUSED_PARAM(scratch);
2069         ASSERT(canBeJumpT3(instruction, target, scratch));
2070         
2071         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2072         
2073         // All branch offsets should be an even distance.
2074         ASSERT(!(relative & 1));
2075         instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12);
2076         instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1);
2077     }
2078     
2079     static void linkJumpT4(uint16_t* instruction, void* target)
2080     {
2081         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2082         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2083         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2084         bool scratch;
2085         UNUSED_PARAM(scratch);
2086         ASSERT(canBeJumpT4(instruction, target, scratch));
2087         
2088         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2089         // ARM encoding for the top two bits below the sign bit is 'peculiar'.
2090         if (relative >= 0)
2091             relative ^= 0xC00000;
2092         
2093         // All branch offsets should be an even distance.
2094         ASSERT(!(relative & 1));
2095         instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
2096         instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
2097     }
2098     
2099     void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target)
2100     {
2101         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2102         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2103         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2104         
2105         instruction[-3] = ifThenElse(cond) | OP_IT;
2106         linkJumpT4(instruction, target);
2107     }
2108     
2109     static void linkBX(uint16_t* instruction, void* target)
2110     {
2111         // FIMXE: this should be up in the MacroAssembler layer. :-(
2112         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2113         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2114         
2115         const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2116         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2117         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2118         instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2119         instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2120         instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2121         instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2122         instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2123     }
2124     
2125     void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
2126     {
2127         // FIMXE: this should be up in the MacroAssembler layer. :-(        
2128         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2129         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2130         
2131         linkBX(instruction, target);
2132         instruction[-6] = ifThenElse(cond, true, true) | OP_IT;
2133     }
2134     
2135     static void linkJumpAbsolute(uint16_t* instruction, void* target)
2136     {
2137         // FIMXE: this should be up in the MacroAssembler layer. :-(
2138         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2139         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2140         
2141         ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
2142                || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
2143         
2144         bool scratch;
2145         if (canBeJumpT4(instruction, target, scratch)) {
2146             // There may be a better way to fix this, but right now put the NOPs first, since in the
2147             // case of an conditional branch this will be coming after an ITTT predicating *three*
2148             // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
2149             // variable wdith encoding - the previous instruction might *look* like an ITTT but
2150             // actually be the second half of a 2-word op.
2151             instruction[-5] = OP_NOP_T1;
2152             instruction[-4] = OP_NOP_T2a;
2153             instruction[-3] = OP_NOP_T2b;
2154             linkJumpT4(instruction, target);
2155         } else {
2156             const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2157             ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2158             ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2159             instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2160             instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2161             instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2162             instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2163             instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2164         }
2165     }
2166     
2167     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
2168     {
2169         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
2170     }
2171
2172     static void decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(ARMThumbImmediate& result, uint16_t value)
2173     {
2174         result.m_value.i = (value >> 10) & 1;
2175         result.m_value.imm4 = value & 15;
2176     }
2177
2178     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
2179     {
2180         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
2181     }
2182
2183     static void decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(ARMThumbImmediate& result, uint16_t value)
2184     {
2185         result.m_value.imm3 = (value >> 12) & 7;
2186         result.m_value.imm8 = value & 255;
2187     }
2188
2189     class ARMInstructionFormatter {
2190     public:
2191         ALWAYS_INLINE void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
2192         {
2193             m_buffer.putShort(op | (rd << 8) | imm);
2194         }
2195         
2196         ALWAYS_INLINE void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
2197         {
2198             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
2199         }
2200
2201         ALWAYS_INLINE void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
2202         {
2203             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
2204         }
2205
2206         ALWAYS_INLINE void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
2207         {
2208             m_buffer.putShort(op | imm);
2209         }
2210
2211         ALWAYS_INLINE void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
2212         {
2213             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
2214         }
2215
2216         ALWAYS_INLINE void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
2217         {
2218             m_buffer.putShort(op | imm);
2219         }
2220
2221         ALWAYS_INLINE void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
2222         {
2223             m_buffer.putShort(op | (reg1 << 3) | reg2);
2224         }
2225
2226         ALWAYS_INLINE void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
2227         {
2228             m_buffer.putShort(op | reg);
2229             m_buffer.putShort(ff.m_u.value);
2230         }
2231         
2232         ALWAYS_INLINE void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
2233         {
2234             m_buffer.putShort(op);
2235             m_buffer.putShort(ff.m_u.value);
2236         }
2237         
2238         ALWAYS_INLINE void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
2239         {
2240             m_buffer.putShort(op1);
2241             m_buffer.putShort(op2);
2242         }
2243
2244         ALWAYS_INLINE void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
2245         {
2246             ARMThumbImmediate newImm = imm;
2247             newImm.m_value.imm4 = imm4;
2248
2249             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
2250             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
2251         }
2252
2253         ALWAYS_INLINE void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
2254         {
2255             m_buffer.putShort(op | reg1);
2256             m_buffer.putShort((reg2 << 12) | imm);
2257         }
2258
2259         ALWAYS_INLINE void twoWordOp12Reg40Imm3Reg4Imm20Imm5(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm1, uint16_t imm2, uint16_t imm3)
2260         {
2261             m_buffer.putShort(op | reg1);
2262             m_buffer.putShort((imm1 << 12) | (reg2 << 8) | (imm2 << 6) | imm3);
2263         }
2264
2265         // Formats up instructions of the pattern:
2266         //    111111111B11aaaa:bbbb222SA2C2cccc
2267         // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
2268         // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
2269         ALWAYS_INLINE void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
2270         {
2271             ASSERT(!(op1 & 0x004f));
2272             ASSERT(!(op2 & 0xf1af));
2273             m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4());
2274             m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4());
2275         }
2276
2277         // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
2278         // (i.e. +/-(0..255) 32-bit words)
2279         ALWAYS_INLINE void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
2280         {
2281             bool up = true;
2282             if (imm < 0) {
2283                 imm = -imm;
2284                 up = false;
2285             }
2286             
2287             uint32_t offset = imm;
2288             ASSERT(!(offset & ~0x3fc));
2289             offset >>= 2;
2290
2291             m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn);
2292             m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset);
2293         }
2294
2295         // Administrative methods:
2296
2297         size_t codeSize() const { return m_buffer.codeSize(); }
2298         AssemblerLabel label() const { return m_buffer.label(); }
2299         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
2300         void* data() const { return m_buffer.data(); }
2301
2302 #ifndef NDEBUG
2303         unsigned debugOffset() { return m_buffer.debugOffset(); }
2304 #endif
2305
2306     private:
2307         AssemblerBuffer m_buffer;
2308     } m_formatter;
2309
2310     Vector<LinkRecord> m_jumpsToLink;
2311     Vector<int32_t> m_offsets;
2312 };
2313
2314 } // namespace JSC
2315
2316 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
2317
2318 #endif // ARMAssembler_h