Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / assembler / assembler / ARMv7Assembler.h
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sw=4 et tw=79:
3  *
4  * ***** BEGIN LICENSE BLOCK *****
5  * Copyright (C) 2009 Apple Inc. All rights reserved.
6  * Copyright (C) 2010 University of Szeged
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
28  * 
29  * ***** END LICENSE BLOCK ***** */
30
31 #ifndef ARMAssembler_h
32 #define ARMAssembler_h
33
34 #include "assembler/wtf/Platform.h"
35
36 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
37
38 #include "AssemblerBuffer.h"
39 #include "assembler/wtf/Assertions.h"
40 #include "assembler/wtf/Vector.h"
41 #include <stdint.h>
42
43 namespace JSC {
44
45 namespace ARMRegisters {
46     typedef enum {
47         r0,
48         r1,
49         r2,
50         r3,
51         r4,
52         r5,
53         r6,
54         r7, wr = r7,   // thumb work register
55         r8,
56         r9, sb = r9,   // static base
57         r10, sl = r10, // stack limit
58         r11, fp = r11, // frame pointer
59         r12, ip = r12,
60         r13, sp = r13,
61         r14, lr = r14,
62         r15, pc = r15,
63     } RegisterID;
64
65     // s0 == d0 == q0
66     // s4 == d2 == q1
67     // etc
68     typedef enum {
69         s0 = 0,
70         s1 = 1,
71         s2 = 2,
72         s3 = 3,
73         s4 = 4,
74         s5 = 5,
75         s6 = 6,
76         s7 = 7,
77         s8 = 8,
78         s9 = 9,
79         s10 = 10,
80         s11 = 11,
81         s12 = 12,
82         s13 = 13,
83         s14 = 14,
84         s15 = 15,
85         s16 = 16,
86         s17 = 17,
87         s18 = 18,
88         s19 = 19,
89         s20 = 20,
90         s21 = 21,
91         s22 = 22,
92         s23 = 23,
93         s24 = 24,
94         s25 = 25,
95         s26 = 26,
96         s27 = 27,
97         s28 = 28,
98         s29 = 29,
99         s30 = 30,
100         s31 = 31,
101         d0 = 0 << 1,
102         d1 = 1 << 1,
103         d2 = 2 << 1,
104         d3 = 3 << 1,
105         d4 = 4 << 1,
106         d5 = 5 << 1,
107         d6 = 6 << 1,
108         d7 = 7 << 1,
109         d8 = 8 << 1,
110         d9 = 9 << 1,
111         d10 = 10 << 1,
112         d11 = 11 << 1,
113         d12 = 12 << 1,
114         d13 = 13 << 1,
115         d14 = 14 << 1,
116         d15 = 15 << 1,
117         d16 = 16 << 1,
118         d17 = 17 << 1,
119         d18 = 18 << 1,
120         d19 = 19 << 1,
121         d20 = 20 << 1,
122         d21 = 21 << 1,
123         d22 = 22 << 1,
124         d23 = 23 << 1,
125         d24 = 24 << 1,
126         d25 = 25 << 1,
127         d26 = 26 << 1,
128         d27 = 27 << 1,
129         d28 = 28 << 1,
130         d29 = 29 << 1,
131         d30 = 30 << 1,
132         d31 = 31 << 1,
133         q0 = 0 << 2,
134         q1 = 1 << 2,
135         q2 = 2 << 2,
136         q3 = 3 << 2,
137         q4 = 4 << 2,
138         q5 = 5 << 2,
139         q6 = 6 << 2,
140         q7 = 7 << 2,
141         q8 = 8 << 2,
142         q9 = 9 << 2,
143         q10 = 10 << 2,
144         q11 = 11 << 2,
145         q12 = 12 << 2,
146         q13 = 13 << 2,
147         q14 = 14 << 2,
148         q15 = 15 << 2,
149         q16 = 16 << 2,
150         q17 = 17 << 2,
151         q18 = 18 << 2,
152         q19 = 19 << 2,
153         q20 = 20 << 2,
154         q21 = 21 << 2,
155         q22 = 22 << 2,
156         q23 = 23 << 2,
157         q24 = 24 << 2,
158         q25 = 25 << 2,
159         q26 = 26 << 2,
160         q27 = 27 << 2,
161         q28 = 28 << 2,
162         q29 = 29 << 2,
163         q30 = 30 << 2,
164         q31 = 31 << 2,
165     } FPRegisterID;
166 }
167
168 class ARMv7Assembler;
169 class ARMThumbImmediate {
170     friend class ARMv7Assembler;
171
172     typedef uint8_t ThumbImmediateType;
173     static const ThumbImmediateType TypeInvalid = 0;
174     static const ThumbImmediateType TypeEncoded = 1;
175     static const ThumbImmediateType TypeUInt16 = 2;
176
177     typedef union {
178         int16_t asInt;
179         struct {
180             unsigned imm8 : 8;
181             unsigned imm3 : 3;
182             unsigned i    : 1;
183             unsigned imm4 : 4;
184         };
185         // If this is an encoded immediate, then it may describe a shift, or a pattern.
186         struct {
187             unsigned shiftValue7 : 7;
188             unsigned shiftAmount : 5;
189         };
190         struct {
191             unsigned immediate   : 8;
192             unsigned pattern     : 4;
193         };
194     } ThumbImmediateValue;
195
196     // byte0 contains least significant bit; not using an array to make client code endian agnostic.
197     typedef union {
198         int32_t asInt;
199         struct {
200             uint8_t byte0;
201             uint8_t byte1;
202             uint8_t byte2;
203             uint8_t byte3;
204         };
205     } PatternBytes;
206
207     ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
208     {
209         if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
210             value >>= N;             /* if any were set, lose the bottom N */
211         else                         /* if none of the top N bits are set, */
212             zeros += N;              /* then we have identified N leading zeros */
213     }
214
215     static int32_t countLeadingZeros(uint32_t value)
216     {
217         if (!value)
218             return 32;
219
220         int32_t zeros = 0;
221         countLeadingZerosPartial(value, zeros, 16);
222         countLeadingZerosPartial(value, zeros, 8);
223         countLeadingZerosPartial(value, zeros, 4);
224         countLeadingZerosPartial(value, zeros, 2);
225         countLeadingZerosPartial(value, zeros, 1);
226         return zeros;
227     }
228
229     ARMThumbImmediate()
230         : m_type(TypeInvalid)
231     {
232         m_value.asInt = 0;
233     }
234         
235     ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
236         : m_type(type)
237         , m_value(value)
238     {
239     }
240
241     ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
242         : m_type(TypeUInt16)
243     {
244         // Make sure this constructor is only reached with type TypeUInt16;
245         // this extra parameter makes the code a little clearer by making it
246         // explicit at call sites which type is being constructed
247         ASSERT_UNUSED(type, type == TypeUInt16);
248
249         m_value.asInt = value;
250     }
251
252 public:
253     static ARMThumbImmediate makeEncodedImm(uint32_t value)
254     {
255         ThumbImmediateValue encoding;
256         encoding.asInt = 0;
257
258         // okay, these are easy.
259         if (value < 256) {
260             encoding.immediate = value;
261             encoding.pattern = 0;
262             return ARMThumbImmediate(TypeEncoded, encoding);
263         }
264
265         int32_t leadingZeros = countLeadingZeros(value);
266         // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
267         ASSERT(leadingZeros < 24);
268
269         // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
270         // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
271         // zero.  count(B) == 8, so the count of bits to be checked is 24 - count(Z).
272         int32_t rightShiftAmount = 24 - leadingZeros;
273         if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
274             // Shift the value down to the low byte position.  The assign to 
275             // shiftValue7 drops the implicit top bit.
276             encoding.shiftValue7 = value >> rightShiftAmount;
277             // The endoded shift amount is the magnitude of a right rotate.
278             encoding.shiftAmount = 8 + leadingZeros;
279             return ARMThumbImmediate(TypeEncoded, encoding);
280         }
281         
282         PatternBytes bytes;
283         bytes.asInt = value;
284
285         if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
286             encoding.immediate = bytes.byte0;
287             encoding.pattern = 3;
288             return ARMThumbImmediate(TypeEncoded, encoding);
289         }
290
291         if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
292             encoding.immediate = bytes.byte0;
293             encoding.pattern = 1;
294             return ARMThumbImmediate(TypeEncoded, encoding);
295         }
296
297         if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
298             encoding.immediate = bytes.byte0;
299             encoding.pattern = 2;
300             return ARMThumbImmediate(TypeEncoded, encoding);
301         }
302
303         return ARMThumbImmediate();
304     }
305
306     static ARMThumbImmediate makeUInt12(int32_t value)
307     {
308         return (!(value & 0xfffff000))
309             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
310             : ARMThumbImmediate();
311     }
312
313     static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
314     {
315         // If this is not a 12-bit unsigned it, try making an encoded immediate.
316         return (!(value & 0xfffff000))
317             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
318             : makeEncodedImm(value);
319     }
320
321     // The 'make' methods, above, return a !isValid() value if the argument
322     // cannot be represented as the requested type.  This methods  is called
323     // 'get' since the argument can always be represented.
324     static ARMThumbImmediate makeUInt16(uint16_t value)
325     {
326         return ARMThumbImmediate(TypeUInt16, value);
327     }
328     
329     bool isValid()
330     {
331         return m_type != TypeInvalid;
332     }
333
334     // These methods rely on the format of encoded byte values.
335     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
336     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
337     bool isUInt5() { return !(m_value.asInt & 0xffe0); }
338     bool isUInt6() { return !(m_value.asInt & 0xffc0); }
339     bool isUInt7() { return !(m_value.asInt & 0xff80); }
340     bool isUInt8() { return !(m_value.asInt & 0xff00); }
341     bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
342     bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
343     bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
344     bool isUInt16() { return m_type == TypeUInt16; }
345     uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
346     uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
347     uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
348     uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
349     uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
350     uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
351     uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
352     uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
353     uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
354     uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
355
356     bool isEncodedImm() { return m_type == TypeEncoded; }
357
358 private:
359     ThumbImmediateType m_type;
360     ThumbImmediateValue m_value;
361 };
362
363
364 typedef enum {
365     SRType_LSL,
366     SRType_LSR,
367     SRType_ASR,
368     SRType_ROR,
369
370     SRType_RRX = SRType_ROR
371 } ARMShiftType;
372
373 class ARMv7Assembler;
374 class ShiftTypeAndAmount {
375     friend class ARMv7Assembler;
376
377 public:
378     ShiftTypeAndAmount()
379     {
380         m_u.type = (ARMShiftType)0;
381         m_u.amount = 0;
382     }
383     
384     ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
385     {
386         m_u.type = type;
387         m_u.amount = amount & 31;
388     }
389     
390     unsigned lo4() { return m_u.lo4; }
391     unsigned hi4() { return m_u.hi4; }
392     
393 private:
394     union {
395         struct {
396             unsigned lo4 : 4;
397             unsigned hi4 : 4;
398         };
399         struct {
400             unsigned type   : 2;
401             unsigned amount : 5;
402         };
403     } m_u;
404 };
405
406
407 /*
408 Some features of the Thumb instruction set are deprecated in ARMv7. Deprecated features affecting 
409 instructions supported by ARMv7-M are as follows: 
410 • use of the PC as <Rd> or <Rm> in a 16-bit ADD (SP plus register) instruction 
411 • use of the SP as <Rm> in a 16-bit ADD (SP plus register) instruction 
412 • use of the SP as <Rm> in a 16-bit CMP (register) instruction 
413 • use of MOV (register) instructions in which <Rd> is the SP or PC and <Rm> is also the SP or PC. 
414 • use of <Rn> as the lowest-numbered register in the register list of a 16-bit STM instruction with base 
415 register writeback 
416 */
417
418 class ARMv7Assembler {
419 public:
420     ~ARMv7Assembler()
421     {
422         ASSERT(m_jumpsToLink.isEmpty());
423     }
424
425     typedef ARMRegisters::RegisterID RegisterID;
426     typedef ARMRegisters::FPRegisterID FPRegisterID;
427
428     // (HS, LO, HI, LS) -> (AE, B, A, BE)
429     // (VS, VC) -> (O, NO)
430     typedef enum {
431         ConditionEQ,
432         ConditionNE,
433         ConditionHS,
434         ConditionLO,
435         ConditionMI,
436         ConditionPL,
437         ConditionVS,
438         ConditionVC,
439         ConditionHI,
440         ConditionLS,
441         ConditionGE,
442         ConditionLT,
443         ConditionGT,
444         ConditionLE,
445         ConditionAL,
446
447         ConditionCS = ConditionHS,
448         ConditionCC = ConditionLO,
449     } Condition;
450
451     class JmpSrc {
452         friend class ARMv7Assembler;
453         friend class ARMInstructionFormatter;
454     public:
455         JmpSrc()
456             : m_offset(-1)
457         {
458         }
459
460     private:
461         JmpSrc(int offset)
462             : m_offset(offset)
463         {
464         }
465
466         int m_offset;
467     };
468     
469     class JmpDst {
470         friend class ARMv7Assembler;
471         friend class ARMInstructionFormatter;
472     public:
473         JmpDst()
474             : m_offset(-1)
475             , m_used(false)
476         {
477         }
478
479         bool isUsed() const { return m_used; }
480         void used() { m_used = true; }
481     private:
482         JmpDst(int offset)
483             : m_offset(offset)
484             , m_used(false)
485         {
486             ASSERT(m_offset == offset);
487         }
488
489         int m_offset : 31;
490         int m_used : 1;
491     };
492
493 private:
494
495     struct LinkRecord {
496         LinkRecord(intptr_t from, intptr_t to)
497             : from(from)
498             , to(to)
499         {
500         }
501
502         intptr_t from;
503         intptr_t to;
504     };
505
506     // ARMv7, Appx-A.6.3
507     bool BadReg(RegisterID reg)
508     {
509         return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
510     }
511
512     bool isSingleRegister(FPRegisterID reg)
513     {
514         // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
515         return !(reg & ~31);
516     }
517
518     bool isDoubleRegister(FPRegisterID reg)
519     {
520         // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
521         return !(reg & ~(31 << 1));
522     }
523
524     bool isQuadRegister(FPRegisterID reg)
525     {
526         return !(reg & ~(31 << 2));
527     }
528
529     uint32_t singleRegisterNum(FPRegisterID reg)
530     {
531         ASSERT(isSingleRegister(reg));
532         return reg;
533     }
534
535     uint32_t doubleRegisterNum(FPRegisterID reg)
536     {
537         ASSERT(isDoubleRegister(reg));
538         return reg >> 1;
539     }
540
541     uint32_t quadRegisterNum(FPRegisterID reg)
542     {
543         ASSERT(isQuadRegister(reg));
544         return reg >> 2;
545     }
546
547     uint32_t singleRegisterMask(FPRegisterID rd, int highBitsShift, int lowBitShift)
548     {
549         uint32_t rdNum = singleRegisterNum(rd);
550         uint32_t rdMask = (rdNum >> 1) << highBitsShift;
551         if (rdNum & 1)
552             rdMask |= 1 << lowBitShift;
553         return rdMask;
554     }
555
556     uint32_t doubleRegisterMask(FPRegisterID rd, int highBitShift, int lowBitsShift)
557     {
558         uint32_t rdNum = doubleRegisterNum(rd);
559         uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
560         if (rdNum & 16)
561             rdMask |= 1 << highBitShift;
562         return rdMask;
563     }
564
565     typedef enum {
566         OP_ADD_reg_T1       = 0x1800,
567         OP_ADD_S_reg_T1     = 0x1800,
568         OP_SUB_reg_T1       = 0x1A00,
569         OP_SUB_S_reg_T1     = 0x1A00,
570         OP_ADD_imm_T1       = 0x1C00,
571         OP_ADD_S_imm_T1     = 0x1C00,
572         OP_SUB_imm_T1       = 0x1E00,
573         OP_SUB_S_imm_T1     = 0x1E00,
574         OP_MOV_imm_T1       = 0x2000,
575         OP_CMP_imm_T1       = 0x2800,
576         OP_ADD_imm_T2       = 0x3000,
577         OP_ADD_S_imm_T2     = 0x3000,
578         OP_SUB_imm_T2       = 0x3800,
579         OP_SUB_S_imm_T2     = 0x3800,
580         OP_AND_reg_T1       = 0x4000,
581         OP_EOR_reg_T1       = 0x4040,
582         OP_TST_reg_T1       = 0x4200,
583         OP_CMP_reg_T1       = 0x4280,
584         OP_ORR_reg_T1       = 0x4300,
585         OP_MVN_reg_T1       = 0x43C0,
586         OP_ADD_reg_T2       = 0x4400,
587         OP_MOV_reg_T1       = 0x4600,
588         OP_BLX              = 0x4700,
589         OP_BX               = 0x4700,
590         OP_STR_reg_T1       = 0x5000,
591         OP_LDR_reg_T1       = 0x5800,
592         OP_LDRH_reg_T1      = 0x5A00,
593         OP_LDRB_reg_T1      = 0x5C00,
594         OP_STR_imm_T1       = 0x6000,
595         OP_LDR_imm_T1       = 0x6800,
596         OP_LDRB_imm_T1      = 0x7800,
597         OP_LDRH_imm_T1      = 0x8800,
598         OP_STR_imm_T2       = 0x9000,
599         OP_LDR_imm_T2       = 0x9800,
600         OP_ADD_SP_imm_T1    = 0xA800,
601         OP_ADD_SP_imm_T2    = 0xB000,
602         OP_SUB_SP_imm_T1    = 0xB080,
603         OP_BKPT             = 0xBE00,
604         OP_IT               = 0xBF00,
605         OP_NOP_T1           = 0xBF00,
606     } OpcodeID;
607
608     typedef enum {
609         OP_AND_reg_T2   = 0xEA00,
610         OP_TST_reg_T2   = 0xEA10,
611         OP_ORR_reg_T2   = 0xEA40,
612         OP_ASR_imm_T1   = 0xEA4F,
613         OP_LSL_imm_T1   = 0xEA4F,
614         OP_LSR_imm_T1   = 0xEA4F,
615         OP_ROR_imm_T1   = 0xEA4F,
616         OP_MVN_reg_T2   = 0xEA6F,
617         OP_EOR_reg_T2   = 0xEA80,
618         OP_ADD_reg_T3   = 0xEB00,
619         OP_ADD_S_reg_T3 = 0xEB10,
620         OP_SUB_reg_T2   = 0xEBA0,
621         OP_SUB_S_reg_T2 = 0xEBB0,
622         OP_CMP_reg_T2   = 0xEBB0,
623         OP_B_T4a        = 0xF000,
624         OP_AND_imm_T1   = 0xF000,
625         OP_TST_imm      = 0xF010,
626         OP_ORR_imm_T1   = 0xF040,
627         OP_MOV_imm_T2   = 0xF040,
628         OP_MVN_imm      = 0xF060,
629         OP_EOR_imm_T1   = 0xF080,
630         OP_ADD_imm_T3   = 0xF100,
631         OP_ADD_S_imm_T3 = 0xF110,
632         OP_CMN_imm      = 0xF110,
633         OP_SUB_imm_T3   = 0xF1A0,
634         OP_SUB_S_imm_T3 = 0xF1B0,
635         OP_CMP_imm_T2   = 0xF1B0,
636         OP_ADD_imm_T4   = 0xF200,
637         OP_MOV_imm_T3   = 0xF240,
638         OP_SUB_imm_T4   = 0xF2A0,
639         OP_MOVT         = 0xF2C0,
640         OP_NOP_T2a      = 0xF3AF,
641         OP_LDRB_imm_T3  = 0xF810,
642         OP_LDRB_reg_T2  = 0xF810,
643         OP_LDRH_reg_T2  = 0xF830,
644         OP_LDRH_imm_T3  = 0xF830,
645         OP_STR_imm_T4   = 0xF840,
646         OP_STR_reg_T2   = 0xF840,
647         OP_LDR_imm_T4   = 0xF850,
648         OP_LDR_reg_T2   = 0xF850,
649         OP_LDRB_imm_T2  = 0xF890,
650         OP_LDRH_imm_T2  = 0xF8B0,
651         OP_STR_imm_T3   = 0xF8C0,
652         OP_LDR_imm_T3   = 0xF8D0,
653         OP_LSL_reg_T2   = 0xFA00,
654         OP_LSR_reg_T2   = 0xFA20,
655         OP_ASR_reg_T2   = 0xFA40,
656         OP_ROR_reg_T2   = 0xFA60,
657         OP_SMULL_T1     = 0xFB80,
658     } OpcodeID1;
659
660     typedef enum {
661         OP_B_T4b        = 0x9000,
662         OP_NOP_T2b      = 0x8000,
663     } OpcodeID2;
664
665     struct FourFours {
666         FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
667         {
668             m_u.f0 = f0;
669             m_u.f1 = f1;
670             m_u.f2 = f2;
671             m_u.f3 = f3;
672         }
673
674         union {
675             unsigned value;
676             struct {
677                 unsigned f0 : 4;
678                 unsigned f1 : 4;
679                 unsigned f2 : 4;
680                 unsigned f3 : 4;
681             };
682         } m_u;
683     };
684
685     class ARMInstructionFormatter;
686
687     // false means else!
688     bool ifThenElseConditionBit(Condition condition, bool isIf)
689     {
690         return isIf ? (condition & 1) : !(condition & 1);
691     }
692     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
693     {
694         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
695             | (ifThenElseConditionBit(condition, inst3if) << 2)
696             | (ifThenElseConditionBit(condition, inst4if) << 1)
697             | 1;
698         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
699         return (condition << 4) | mask;
700     }
701     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
702     {
703         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
704             | (ifThenElseConditionBit(condition, inst3if) << 2)
705             | 2;
706         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
707         return (condition << 4) | mask;
708     }
709     uint8_t ifThenElse(Condition condition, bool inst2if)
710     {
711         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
712             | 4;
713         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
714         return (condition << 4) | mask;
715     }
716
717     uint8_t ifThenElse(Condition condition)
718     {
719         int mask = 8;
720         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
721         return (condition << 4) | mask;
722     }
723
724 public:
725
726     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
727     {
728         // Rd can only be SP if Rn is also SP.
729         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
730         ASSERT(rd != ARMRegisters::pc);
731         ASSERT(rn != ARMRegisters::pc);
732         ASSERT(imm.isValid());
733
734         if (rn == ARMRegisters::sp) {
735             if (!(rd & 8) && imm.isUInt10()) {
736                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
737                 return;
738             } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
739                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
740                 return;
741             }
742         } else if (!((rd | rn) & 8)) {
743             if (imm.isUInt3()) {
744                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
745                 return;
746             } else if ((rd == rn) && imm.isUInt8()) {
747                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
748                 return;
749             }
750         }
751
752         if (imm.isEncodedImm())
753             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
754         else {
755             ASSERT(imm.isUInt12());
756             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
757         }
758     }
759
760     void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
761     {
762         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
763         ASSERT(rd != ARMRegisters::pc);
764         ASSERT(rn != ARMRegisters::pc);
765         ASSERT(!BadReg(rm));
766         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
767     }
768
769     // NOTE: In an IT block, add doesn't modify the flags register.
770     void add(RegisterID rd, RegisterID rn, RegisterID rm)
771     {
772         if (rd == rn)
773             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
774         else if (rd == rm)
775             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
776         else if (!((rd | rn | rm) & 8))
777             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
778         else
779             add(rd, rn, rm, ShiftTypeAndAmount());
780     }
781
782     // Not allowed in an IT (if then) block.
783     void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
784     {
785         // Rd can only be SP if Rn is also SP.
786         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
787         ASSERT(rd != ARMRegisters::pc);
788         ASSERT(rn != ARMRegisters::pc);
789         ASSERT(imm.isEncodedImm());
790
791         if (!((rd | rn) & 8)) {
792             if (imm.isUInt3()) {
793                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
794                 return;
795             } else if ((rd == rn) && imm.isUInt8()) {
796                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_S_imm_T2, rd, imm.getUInt8());
797                 return;
798             }
799         }
800
801         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
802     }
803
804     // Not allowed in an IT (if then) block?
805     void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
806     {
807         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
808         ASSERT(rd != ARMRegisters::pc);
809         ASSERT(rn != ARMRegisters::pc);
810         ASSERT(!BadReg(rm));
811         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
812     }
813
814     // Not allowed in an IT (if then) block.
815     void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
816     {
817         if (!((rd | rn | rm) & 8))
818             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_reg_T1, rm, rn, rd);
819         else
820             add_S(rd, rn, rm, ShiftTypeAndAmount());
821     }
822
823     void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
824     {
825         ASSERT(!BadReg(rd));
826         ASSERT(!BadReg(rn));
827         ASSERT(imm.isEncodedImm());
828         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
829     }
830
831     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
832     {
833         ASSERT(!BadReg(rd));
834         ASSERT(!BadReg(rn));
835         ASSERT(!BadReg(rm));
836         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
837     }
838
839     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
840     {
841         if ((rd == rn) && !((rd | rm) & 8))
842             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
843         else if ((rd == rm) && !((rd | rn) & 8))
844             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
845         else
846             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
847     }
848
849     void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
850     {
851         ASSERT(!BadReg(rd));
852         ASSERT(!BadReg(rm));
853         ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
854         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
855     }
856
857     void asr(RegisterID rd, RegisterID rn, RegisterID rm)
858     {
859         ASSERT(!BadReg(rd));
860         ASSERT(!BadReg(rn));
861         ASSERT(!BadReg(rm));
862         m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
863     }
864
865     // Only allowed in IT (if then) block if last instruction.
866     JmpSrc b()
867     {
868         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
869         return JmpSrc(m_formatter.size());
870     }
871     
872     // Only allowed in IT (if then) block if last instruction.
873     JmpSrc blx(RegisterID rm)
874     {
875         ASSERT(rm != ARMRegisters::pc);
876         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
877         return JmpSrc(m_formatter.size());
878     }
879
880     // Only allowed in IT (if then) block if last instruction.
881     JmpSrc bx(RegisterID rm)
882     {
883         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
884         return JmpSrc(m_formatter.size());
885     }
886
887     void bkpt(uint8_t imm=0)
888     {
889         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
890     }
891
892     void cmn(RegisterID rn, ARMThumbImmediate imm)
893     {
894         ASSERT(rn != ARMRegisters::pc);
895         ASSERT(imm.isEncodedImm());
896
897         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
898     }
899
900     void cmp(RegisterID rn, ARMThumbImmediate imm)
901     {
902         ASSERT(rn != ARMRegisters::pc);
903         ASSERT(imm.isEncodedImm());
904
905         if (!(rn & 8) && imm.isUInt8())
906             m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
907         else
908             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
909     }
910
911     void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
912     {
913         ASSERT(rn != ARMRegisters::pc);
914         ASSERT(!BadReg(rm));
915         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
916     }
917
918     void cmp(RegisterID rn, RegisterID rm)
919     {
920         if ((rn | rm) & 8)
921             cmp(rn, rm, ShiftTypeAndAmount());
922         else
923             m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
924     }
925
926     // xor is not spelled with an 'e'. :-(
927     void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
928     {
929         ASSERT(!BadReg(rd));
930         ASSERT(!BadReg(rn));
931         ASSERT(imm.isEncodedImm());
932         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
933     }
934
935     // xor is not spelled with an 'e'. :-(
936     void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
937     {
938         ASSERT(!BadReg(rd));
939         ASSERT(!BadReg(rn));
940         ASSERT(!BadReg(rm));
941         m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
942     }
943
944     // xor is not spelled with an 'e'. :-(
945     void eor(RegisterID rd, RegisterID rn, RegisterID rm)
946     {
947         if ((rd == rn) && !((rd | rm) & 8))
948             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
949         else if ((rd == rm) && !((rd | rn) & 8))
950             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
951         else
952             eor(rd, rn, rm, ShiftTypeAndAmount());
953     }
954
955     void it(Condition cond)
956     {
957         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
958     }
959
960     void it(Condition cond, bool inst2if)
961     {
962         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
963     }
964
965     void it(Condition cond, bool inst2if, bool inst3if)
966     {
967         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
968     }
969
970     void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
971     {
972         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
973     }
974
975     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
976     void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
977     {
978         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
979         ASSERT(imm.isUInt12());
980
981         if (!((rt | rn) & 8) && imm.isUInt7())
982             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
983         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
984             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
985         else
986             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
987     }
988
989     // If index is set, this is a regular offset or a pre-indexed load;
990     // if index is not set then is is a post-index load.
991     //
992     // If wback is set rn is updated - this is a pre or post index load,
993     // if wback is not set this is a regular offset memory access.
994     //
995     // (-255 <= offset <= 255)
996     // _reg = REG[rn]
997     // _tmp = _reg + offset
998     // MEM[index ? _tmp : _reg] = REG[rt]
999     // if (wback) REG[rn] = _tmp
1000     void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1001     {
1002         ASSERT(rt != ARMRegisters::pc);
1003         ASSERT(rn != ARMRegisters::pc);
1004         ASSERT(index || wback);
1005         ASSERT(!wback | (rt != rn));
1006     
1007         bool add = true;
1008         if (offset < 0) {
1009             add = false;
1010             offset = -offset;
1011         }
1012         ASSERT((offset & ~0xff) == 0);
1013         
1014         offset |= (wback << 8);
1015         offset |= (add   << 9);
1016         offset |= (index << 10);
1017         offset |= (1 << 11);
1018         
1019         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
1020     }
1021
1022     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1023     void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1024     {
1025         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1026         ASSERT(!BadReg(rm));
1027         ASSERT(shift <= 3);
1028
1029         if (!shift && !((rt | rn | rm) & 8))
1030             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
1031         else
1032             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1033     }
1034
1035     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1036     void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1037     {
1038         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1039         ASSERT(imm.isUInt12());
1040
1041         if (!((rt | rn) & 8) && imm.isUInt6())
1042             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
1043         else
1044             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
1045     }
1046
1047     // If index is set, this is a regular offset or a pre-indexed load;
1048     // if index is not set then is is a post-index load.
1049     //
1050     // If wback is set rn is updated - this is a pre or post index load,
1051     // if wback is not set this is a regular offset memory access.
1052     //
1053     // (-255 <= offset <= 255)
1054     // _reg = REG[rn]
1055     // _tmp = _reg + offset
1056     // MEM[index ? _tmp : _reg] = REG[rt]
1057     // if (wback) REG[rn] = _tmp
1058     void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1059     {
1060         ASSERT(rt != ARMRegisters::pc);
1061         ASSERT(rn != ARMRegisters::pc);
1062         ASSERT(index || wback);
1063         ASSERT(!wback | (rt != rn));
1064     
1065         bool add = true;
1066         if (offset < 0) {
1067             add = false;
1068             offset = -offset;
1069         }
1070         ASSERT((offset & ~0xff) == 0);
1071         
1072         offset |= (wback << 8);
1073         offset |= (add   << 9);
1074         offset |= (index << 10);
1075         offset |= (1 << 11);
1076         
1077         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
1078     }
1079
1080     void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1081     {
1082         ASSERT(!BadReg(rt));   // Memory hint
1083         ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
1084         ASSERT(!BadReg(rm));
1085         ASSERT(shift <= 3);
1086
1087         if (!shift && !((rt | rn | rm) & 8))
1088             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
1089         else
1090             m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1091     }
1092
1093     void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1094     {
1095         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1096         ASSERT(imm.isUInt12());
1097
1098         if (!((rt | rn) & 8) && imm.isUInt5())
1099             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
1100         else
1101             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
1102     }
1103
1104     void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1105     {
1106         ASSERT(rt != ARMRegisters::pc);
1107         ASSERT(rn != ARMRegisters::pc);
1108         ASSERT(index || wback);
1109         ASSERT(!wback | (rt != rn));
1110
1111         bool add = true;
1112         if (offset < 0) {
1113             add = false;
1114             offset = -offset;
1115         }
1116
1117         ASSERT(!(offset & ~0xff));
1118
1119         offset |= (wback << 8);
1120         offset |= (add   << 9);
1121         offset |= (index << 10);
1122         offset |= (1 << 11);
1123
1124         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
1125     }
1126
1127     void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1128     {
1129         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1130         ASSERT(!BadReg(rm));
1131         ASSERT(shift <= 3);
1132
1133         if (!shift && !((rt | rn | rm) & 8))
1134             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
1135         else
1136             m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1137     }
1138
1139     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1140     {
1141         ASSERT(!BadReg(rd));
1142         ASSERT(!BadReg(rm));
1143         ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
1144         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1145     }
1146
1147     void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
1148     {
1149         ASSERT(!BadReg(rd));
1150         ASSERT(!BadReg(rn));
1151         ASSERT(!BadReg(rm));
1152         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1153     }
1154
1155     void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1156     {
1157         ASSERT(!BadReg(rd));
1158         ASSERT(!BadReg(rm));
1159         ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
1160         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1161     }
1162
1163     void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
1164     {
1165         ASSERT(!BadReg(rd));
1166         ASSERT(!BadReg(rn));
1167         ASSERT(!BadReg(rm));
1168         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1169     }
1170
1171     void movT3(RegisterID rd, ARMThumbImmediate imm)
1172     {
1173         ASSERT(imm.isValid());
1174         ASSERT(!imm.isEncodedImm());
1175         ASSERT(!BadReg(rd));
1176         
1177         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
1178     }
1179
1180      void mov(RegisterID rd, ARMThumbImmediate imm)
1181     {
1182         ASSERT(imm.isValid());
1183         ASSERT(!BadReg(rd));
1184         
1185         if ((rd < 8) && imm.isUInt8())
1186             m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
1187         else if (imm.isEncodedImm())
1188             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
1189         else
1190             movT3(rd, imm);
1191     }
1192
1193    void mov(RegisterID rd, RegisterID rm)
1194     {
1195         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
1196     }
1197
1198     void movt(RegisterID rd, ARMThumbImmediate imm)
1199     {
1200         ASSERT(imm.isUInt16());
1201         ASSERT(!BadReg(rd));
1202         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
1203     }
1204
1205     void mvn(RegisterID rd, ARMThumbImmediate imm)
1206     {
1207         ASSERT(imm.isEncodedImm());
1208         ASSERT(!BadReg(rd));
1209         
1210         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
1211     }
1212
1213     void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
1214     {
1215         ASSERT(!BadReg(rd));
1216         ASSERT(!BadReg(rm));
1217         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1218     }
1219
1220     void mvn(RegisterID rd, RegisterID rm)
1221     {
1222         if (!((rd | rm) & 8))
1223             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
1224         else
1225             mvn(rd, rm, ShiftTypeAndAmount());
1226     }
1227
1228     void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1229     {
1230         ASSERT(!BadReg(rd));
1231         ASSERT(!BadReg(rn));
1232         ASSERT(imm.isEncodedImm());
1233         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
1234     }
1235
1236     void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1237     {
1238         ASSERT(!BadReg(rd));
1239         ASSERT(!BadReg(rn));
1240         ASSERT(!BadReg(rm));
1241         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1242     }
1243
1244     void orr(RegisterID rd, RegisterID rn, RegisterID rm)
1245     {
1246         if ((rd == rn) && !((rd | rm) & 8))
1247             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1248         else if ((rd == rm) && !((rd | rn) & 8))
1249             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1250         else
1251             orr(rd, rn, rm, ShiftTypeAndAmount());
1252     }
1253
1254     void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1255     {
1256         ASSERT(!BadReg(rd));
1257         ASSERT(!BadReg(rm));
1258         ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
1259         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1260     }
1261
1262     void ror(RegisterID rd, RegisterID rn, RegisterID rm)
1263     {
1264         ASSERT(!BadReg(rd));
1265         ASSERT(!BadReg(rn));
1266         ASSERT(!BadReg(rm));
1267         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1268     }
1269
1270     void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
1271     {
1272         ASSERT(!BadReg(rdLo));
1273         ASSERT(!BadReg(rdHi));
1274         ASSERT(!BadReg(rn));
1275         ASSERT(!BadReg(rm));
1276         ASSERT(rdLo != rdHi);
1277         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
1278     }
1279
1280     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1281     void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1282     {
1283         ASSERT(rt != ARMRegisters::pc);
1284         ASSERT(rn != ARMRegisters::pc);
1285         ASSERT(imm.isUInt12());
1286
1287         if (!((rt | rn) & 8) && imm.isUInt7())
1288             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1289         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1290             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
1291         else
1292             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
1293     }
1294
1295     // If index is set, this is a regular offset or a pre-indexed store;
1296     // if index is not set then is is a post-index store.
1297     //
1298     // If wback is set rn is updated - this is a pre or post index store,
1299     // if wback is not set this is a regular offset memory access.
1300     //
1301     // (-255 <= offset <= 255)
1302     // _reg = REG[rn]
1303     // _tmp = _reg + offset
1304     // MEM[index ? _tmp : _reg] = REG[rt]
1305     // if (wback) REG[rn] = _tmp
1306     void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1307     {
1308         ASSERT(rt != ARMRegisters::pc);
1309         ASSERT(rn != ARMRegisters::pc);
1310         ASSERT(index || wback);
1311         ASSERT(!wback | (rt != rn));
1312     
1313         bool add = true;
1314         if (offset < 0) {
1315             add = false;
1316             offset = -offset;
1317         }
1318         ASSERT((offset & ~0xff) == 0);
1319         
1320         offset |= (wback << 8);
1321         offset |= (add   << 9);
1322         offset |= (index << 10);
1323         offset |= (1 << 11);
1324         
1325         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
1326     }
1327
1328     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1329     void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1330     {
1331         ASSERT(rn != ARMRegisters::pc);
1332         ASSERT(!BadReg(rm));
1333         ASSERT(shift <= 3);
1334
1335         if (!shift && !((rt | rn | rm) & 8))
1336             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
1337         else
1338             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1339     }
1340
1341     void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1342     {
1343         // Rd can only be SP if Rn is also SP.
1344         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1345         ASSERT(rd != ARMRegisters::pc);
1346         ASSERT(rn != ARMRegisters::pc);
1347         ASSERT(imm.isValid());
1348
1349         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1350             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1351             return;
1352         } else if (!((rd | rn) & 8)) {
1353             if (imm.isUInt3()) {
1354                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1355                 return;
1356             } else if ((rd == rn) && imm.isUInt8()) {
1357                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1358                 return;
1359             }
1360         }
1361
1362         if (imm.isEncodedImm())
1363             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
1364         else {
1365             ASSERT(imm.isUInt12());
1366             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
1367         }
1368     }
1369
1370     void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1371     {
1372         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1373         ASSERT(rd != ARMRegisters::pc);
1374         ASSERT(rn != ARMRegisters::pc);
1375         ASSERT(!BadReg(rm));
1376         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1377     }
1378
1379     // NOTE: In an IT block, add doesn't modify the flags register.
1380     void sub(RegisterID rd, RegisterID rn, RegisterID rm)
1381     {
1382         if (!((rd | rn | rm) & 8))
1383             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1384         else
1385             sub(rd, rn, rm, ShiftTypeAndAmount());
1386     }
1387
1388     // Not allowed in an IT (if then) block.
1389     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1390     {
1391         // Rd can only be SP if Rn is also SP.
1392         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1393         ASSERT(rd != ARMRegisters::pc);
1394         ASSERT(rn != ARMRegisters::pc);
1395         ASSERT(imm.isValid());
1396
1397         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1398             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1399             return;
1400         } else if (!((rd | rn) & 8)) {
1401             if (imm.isUInt3()) {
1402                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1403                 return;
1404             } else if ((rd == rn) && imm.isUInt8()) {
1405                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_S_imm_T2, rd, imm.getUInt8());
1406                 return;
1407             }
1408         }
1409
1410         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
1411     }
1412
1413     // Not allowed in an IT (if then) block?
1414     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1415     {
1416         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1417         ASSERT(rd != ARMRegisters::pc);
1418         ASSERT(rn != ARMRegisters::pc);
1419         ASSERT(!BadReg(rm));
1420         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1421     }
1422
1423     // Not allowed in an IT (if then) block.
1424     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
1425     {
1426         if (!((rd | rn | rm) & 8))
1427             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_reg_T1, rm, rn, rd);
1428         else
1429             sub_S(rd, rn, rm, ShiftTypeAndAmount());
1430     }
1431
1432     void tst(RegisterID rn, ARMThumbImmediate imm)
1433     {
1434         ASSERT(!BadReg(rn));
1435         ASSERT(imm.isEncodedImm());
1436
1437         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
1438     }
1439
1440     void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1441     {
1442         ASSERT(!BadReg(rn));
1443         ASSERT(!BadReg(rm));
1444         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1445     }
1446
1447     void tst(RegisterID rn, RegisterID rm)
1448     {
1449         if ((rn | rm) & 8)
1450             tst(rn, rm, ShiftTypeAndAmount());
1451         else
1452             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
1453     }
1454
1455     void vadd_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1456     {
1457         m_formatter.vfpOp(0x0b00ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1458     }
1459
1460     void vcmp_F64(FPRegisterID rd, FPRegisterID rm)
1461     {
1462         m_formatter.vfpOp(0x0bc0eeb4 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rm, 21, 16));
1463     }
1464
1465     void vcvt_F64_S32(FPRegisterID fd, FPRegisterID sm)
1466     {
1467         m_formatter.vfpOp(0x0bc0eeb8 | doubleRegisterMask(fd, 6, 28) | singleRegisterMask(sm, 16, 21));
1468     }
1469
1470     void vcvt_S32_F64(FPRegisterID sd, FPRegisterID fm)
1471     {
1472         m_formatter.vfpOp(0x0bc0eebd | singleRegisterMask(sd, 28, 6) | doubleRegisterMask(fm, 21, 16));
1473     }
1474
1475     void vldr(FPRegisterID rd, RegisterID rn, int32_t imm)
1476     {
1477         vmem(rd, rn, imm, true);
1478     }
1479
1480     void vmov(RegisterID rd, FPRegisterID sn)
1481     {
1482         m_formatter.vfpOp(0x0a10ee10 | (rd << 28) | singleRegisterMask(sn, 0, 23));
1483     }
1484
1485     void vmov(FPRegisterID sn, RegisterID rd)
1486     {
1487         m_formatter.vfpOp(0x0a10ee00 | (rd << 28) | singleRegisterMask(sn, 0, 23));
1488     }
1489
1490     // move FPSCR flags to APSR.
1491     void vmrs_APSR_nzcv_FPSCR()
1492     {
1493         m_formatter.vfpOp(0xfa10eef1);
1494     }
1495
1496     void vmul_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1497     {
1498         m_formatter.vfpOp(0x0b00ee20 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1499     }
1500
1501     void vstr(FPRegisterID rd, RegisterID rn, int32_t imm)
1502     {
1503         vmem(rd, rn, imm, false);
1504     }
1505
1506     void vsub_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1507     {
1508         m_formatter.vfpOp(0x0b40ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1509     }
1510
1511
1512     JmpDst label()
1513     {
1514         return JmpDst(m_formatter.size());
1515     }
1516     
1517     JmpDst align(int alignment)
1518     {
1519         while (!m_formatter.isAligned(alignment))
1520             bkpt();
1521
1522         return label();
1523     }
1524     
1525     static void* getRelocatedAddress(void* code, JmpSrc jump)
1526     {
1527         ASSERT(jump.m_offset != -1);
1528
1529         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1530     }
1531     
1532     static void* getRelocatedAddress(void* code, JmpDst destination)
1533     {
1534         ASSERT(destination.m_offset != -1);
1535
1536         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
1537     }
1538     
1539     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1540     {
1541         return dst.m_offset - src.m_offset;
1542     }
1543     
1544     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1545     {
1546         return dst.m_offset - src.m_offset;
1547     }
1548     
1549     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
1550     {
1551         return dst.m_offset - src.m_offset;
1552     }
1553     
1554     // Assembler admin methods:
1555
1556     size_t size() const
1557     {
1558         return m_formatter.size();
1559     }
1560
1561     void* executableCopy(ExecutablePool* allocator)
1562     {
1563         void* copy = m_formatter.executableCopy(allocator);
1564
1565         unsigned jumpCount = m_jumpsToLink.size();
1566         for (unsigned i = 0; i < jumpCount; ++i) {
1567             uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from);
1568             uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to);
1569             linkJumpAbsolute(location, target);
1570         }
1571         m_jumpsToLink.clear();
1572
1573         ASSERT(copy);
1574         return copy;
1575     }
1576
1577     static unsigned getCallReturnOffset(JmpSrc call)
1578     {
1579         ASSERT(call.m_offset >= 0);
1580         return call.m_offset;
1581     }
1582
1583     // Linking & patching:
1584     //
1585     // 'link' and 'patch' methods are for use on unprotected code - such as the code
1586     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
1587     // code has been finalized it is (platform support permitting) within a non-
1588     // writable region of memory; to modify the code in an execute-only execuable
1589     // pool the 'repatch' and 'relink' methods should be used.
1590
1591     void linkJump(JmpSrc from, JmpDst to)
1592     {
1593         ASSERT(to.m_offset != -1);
1594         ASSERT(from.m_offset != -1);
1595         m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset));
1596     }
1597
1598     static void linkJump(void* code, JmpSrc from, void* to)
1599     {
1600         ASSERT(from.m_offset != -1);
1601         
1602         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
1603         linkJumpAbsolute(location, to);
1604     }
1605
1606     // bah, this mathod should really be static, since it is used by the LinkBuffer.
1607     // return a bool saying whether the link was successful?
1608     static void linkCall(void* code, JmpSrc from, void* to)
1609     {
1610         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
1611         ASSERT(from.m_offset != -1);
1612         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1613
1614         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
1615     }
1616
1617     static void linkPointer(void* code, JmpDst where, void* value)
1618     {
1619         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
1620     }
1621
1622     static void relinkJump(void* from, void* to)
1623     {
1624         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1625         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
1626
1627         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
1628
1629         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
1630     }
1631
1632     static bool canRelinkJump(void* from, void* to)
1633     {
1634         return true;
1635     }
1636     
1637     static void relinkCall(void* from, void* to)
1638     {
1639         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1640         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1641
1642         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
1643
1644         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 4 * sizeof(uint16_t));
1645     }
1646
1647     static void repatchInt32(void* where, int32_t value)
1648     {
1649         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1650         
1651         setInt32(where, value);
1652
1653         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
1654     }
1655
1656     static void repatchPointer(void* where, void* value)
1657     {
1658         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1659         
1660         setPointer(where, value);
1661
1662         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
1663     }
1664
1665     static void repatchLoadPtrToLEA(void* where)
1666     {
1667         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1668
1669         uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
1670         ASSERT((*loadOp & 0xfff0) == OP_LDR_reg_T2);
1671
1672         *loadOp = OP_ADD_reg_T3 | (*loadOp & 0xf);
1673         ExecutableAllocator::cacheFlush(loadOp, sizeof(uint16_t));
1674     }
1675
1676     static void repatchLEAToLoadPtr(void* where)
1677     {
1678         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1679
1680         uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
1681         if ((*loadOp & 0xfff0) == OP_LDR_reg_T2)
1682             return;
1683
1684         ASSERT((*loadOp & 0xfff0) == OP_ADD_reg_T3);
1685
1686         *loadOp = OP_LDR_reg_T2 | (*loadOp & 0xf);
1687         ExecutableAllocator::cacheFlush(loadOp, sizeof(uint16_t));
1688     }
1689
1690 private:
1691
1692     // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
1693     // (i.e. +/-(0..255) 32-bit words)
1694     void vmem(FPRegisterID rd, RegisterID rn, int32_t imm, bool isLoad)
1695     {
1696         bool up;
1697         uint32_t offset;
1698         if (imm < 0) {
1699             offset = -imm;
1700             up = false;
1701         } else {
1702             offset = imm;
1703             up = true;
1704         }
1705
1706         // offset is effectively leftshifted by 2 already (the bottom two bits are zero, and not
1707         // reperesented in the instruction.  Left shift by 14, to mov it into position 0x00AA0000.
1708         ASSERT((offset & ~(0xff << 2)) == 0);
1709         offset <<= 14;
1710
1711         m_formatter.vfpOp(0x0b00ed00 | offset | (up << 7) | (isLoad << 4) | doubleRegisterMask(rd, 6, 28) | rn);
1712     }
1713
1714     static void setInt32(void* code, uint32_t value)
1715     {
1716         uint16_t* location = reinterpret_cast<uint16_t*>(code);
1717         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
1718
1719         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
1720         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
1721         location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
1722         location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
1723         location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
1724         location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
1725
1726         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
1727     }
1728
1729     static void setPointer(void* code, void* value)
1730     {
1731         setInt32(code, reinterpret_cast<uint32_t>(value));
1732     }
1733
1734     static bool isB(void* address)
1735     {
1736         uint16_t* instruction = static_cast<uint16_t*>(address);
1737         return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
1738     }
1739
1740     static bool isBX(void* address)
1741     {
1742         uint16_t* instruction = static_cast<uint16_t*>(address);
1743         return (instruction[0] & 0xff87) == OP_BX;
1744     }
1745
1746     static bool isMOV_imm_T3(void* address)
1747     {
1748         uint16_t* instruction = static_cast<uint16_t*>(address);
1749         return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
1750     }
1751
1752     static bool isMOVT(void* address)
1753     {
1754         uint16_t* instruction = static_cast<uint16_t*>(address);
1755         return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
1756     }
1757
1758     static bool isNOP_T1(void* address)
1759     {
1760         uint16_t* instruction = static_cast<uint16_t*>(address);
1761         return instruction[0] == OP_NOP_T1;
1762     }
1763
1764     static bool isNOP_T2(void* address)
1765     {
1766         uint16_t* instruction = static_cast<uint16_t*>(address);
1767         return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
1768     }
1769
1770     static void linkJumpAbsolute(uint16_t* instruction, void* target)
1771     {
1772         // FIMXE: this should be up in the MacroAssembler layer. :-(
1773         const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
1774
1775         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1776         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1777
1778         ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
1779             || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) );
1780
1781         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1782
1783         // From Cortex-A8 errata:
1784         // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
1785         // the target of the branch falls within the first region it is
1786         // possible for the processor to incorrectly determine the branch
1787         // instruction, and it is also possible in some cases for the processor
1788         // to enter a deadlock state.
1789         // The instruction is spanning two pages if it ends at an address ending 0x002
1790         bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
1791         // The target is in the first page if the jump branch back by [3..0x1002] bytes
1792         bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
1793         bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
1794
1795         if (((relative << 7) >> 7) == relative && !wouldTriggerA8Errata) {
1796             // ARM encoding for the top two bits below the sign bit is 'peculiar'.
1797             if (relative >= 0)
1798                 relative ^= 0xC00000;
1799
1800             // All branch offsets should be an even distance.
1801             ASSERT(!(relative & 1));
1802             // There may be a better way to fix this, but right now put the NOPs first, since in the
1803             // case of an conditional branch this will be coming after an ITTT predicating *three*
1804             // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
1805             // variable wdith encoding - the previous instruction might *look* like an ITTT but
1806             // actually be the second half of a 2-word op.
1807             instruction[-5] = OP_NOP_T1;
1808             instruction[-4] = OP_NOP_T2a;
1809             instruction[-3] = OP_NOP_T2b;
1810             instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
1811             instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
1812         } else {
1813             ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
1814             ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
1815             instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
1816             instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
1817             instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
1818             instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
1819             instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
1820         }
1821     }
1822
1823     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
1824     {
1825         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
1826     }
1827     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
1828     {
1829         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
1830     }
1831
1832     class ARMInstructionFormatter {
1833     public:
1834         void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
1835         {
1836             m_buffer.putShort(op | (rd << 8) | imm);
1837         }
1838         
1839         void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
1840         {
1841             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
1842         }
1843
1844         void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
1845         {
1846             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
1847         }
1848
1849         void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
1850         {
1851             m_buffer.putShort(op | imm);
1852         }
1853
1854         void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
1855         {
1856             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
1857         }
1858         void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
1859         {
1860             m_buffer.putShort(op | imm);
1861         }
1862
1863         void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
1864         {
1865             m_buffer.putShort(op | (reg1 << 3) | reg2);
1866         }
1867
1868         void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
1869         {
1870             m_buffer.putShort(op | reg);
1871             m_buffer.putShort(ff.m_u.value);
1872         }
1873         
1874         void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
1875         {
1876             m_buffer.putShort(op);
1877             m_buffer.putShort(ff.m_u.value);
1878         }
1879         
1880         void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
1881         {
1882             m_buffer.putShort(op1);
1883             m_buffer.putShort(op2);
1884         }
1885
1886         void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
1887         {
1888             ARMThumbImmediate newImm = imm;
1889             newImm.m_value.imm4 = imm4;
1890
1891             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
1892             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
1893         }
1894
1895         void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
1896         {
1897             m_buffer.putShort(op | reg1);
1898             m_buffer.putShort((reg2 << 12) | imm);
1899         }
1900
1901         void vfpOp(int32_t op)
1902         {
1903             m_buffer.putInt(op);
1904         }
1905
1906
1907         // Administrative methods:
1908
1909         size_t size() const { return m_buffer.size(); }
1910         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
1911         void* data() const { return m_buffer.data(); }
1912         void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
1913         bool oom() const { return m_buffer.oom(); }
1914
1915     private:
1916         AssemblerBuffer m_buffer;
1917     } m_formatter;
1918
1919     Vector<LinkRecord> m_jumpsToLink;
1920 };
1921
1922 } // namespace JSC
1923
1924 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
1925
1926 #endif // ARMAssembler_h