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