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