• 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) && PLATFORM_ARM_ARCH(7)
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 ARM {
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 int32_t 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         m_value.asInt = value;
240     }
241 
242 public:
makeEncodedImm(uint32_t value)243     static ARMThumbImmediate makeEncodedImm(uint32_t value)
244     {
245         ThumbImmediateValue encoding;
246         encoding.asInt = 0;
247 
248         // okay, these are easy.
249         if (value < 256) {
250             encoding.immediate = value;
251             encoding.pattern = 0;
252             return ARMThumbImmediate(TypeEncoded, encoding);
253         }
254 
255         int32_t leadingZeros = countLeadingZeros(value);
256         // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
257         ASSERT(leadingZeros < 24);
258 
259         // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
260         // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
261         // zero.  count(B) == 8, so the count of bits to be checked is 24 - count(Z).
262         int32_t rightShiftAmount = 24 - leadingZeros;
263         if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
264             // Shift the value down to the low byte position.  The assign to
265             // shiftValue7 drops the implicit top bit.
266             encoding.shiftValue7 = value >> rightShiftAmount;
267             // The endoded shift amount is the magnitude of a right rotate.
268             encoding.shiftAmount = 8 + leadingZeros;
269             return ARMThumbImmediate(TypeEncoded, encoding);
270         }
271 
272         PatternBytes bytes;
273         bytes.asInt = value;
274 
275         if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
276             encoding.immediate = bytes.byte0;
277             encoding.pattern = 3;
278             return ARMThumbImmediate(TypeEncoded, encoding);
279         }
280 
281         if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
282             encoding.immediate = bytes.byte0;
283             encoding.pattern = 1;
284             return ARMThumbImmediate(TypeEncoded, encoding);
285         }
286 
287         if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
288             encoding.immediate = bytes.byte0;
289             encoding.pattern = 2;
290             return ARMThumbImmediate(TypeEncoded, encoding);
291         }
292 
293         return ARMThumbImmediate();
294     }
295 
makeUInt12(int32_t value)296     static ARMThumbImmediate makeUInt12(int32_t value)
297     {
298         return (!(value & 0xfffff000))
299             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
300             : ARMThumbImmediate();
301     }
302 
makeUInt12OrEncodedImm(int32_t value)303     static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
304     {
305         // If this is not a 12-bit unsigned it, try making an encoded immediate.
306         return (!(value & 0xfffff000))
307             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
308             : makeEncodedImm(value);
309     }
310 
311     // The 'make' methods, above, return a !isValid() value if the argument
312     // cannot be represented as the requested type.  This methods  is called
313     // 'get' since the argument can always be represented.
makeUInt16(uint16_t value)314     static ARMThumbImmediate makeUInt16(uint16_t value)
315     {
316         return ARMThumbImmediate(TypeUInt16, value);
317     }
318 
isValid()319     bool isValid()
320     {
321         return m_type != TypeInvalid;
322     }
323 
324     // These methods rely on the format of encoded byte values.
isUInt3()325     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
isUInt4()326     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
isUInt5()327     bool isUInt5() { return !(m_value.asInt & 0xffe0); }
isUInt6()328     bool isUInt6() { return !(m_value.asInt & 0xffc0); }
isUInt7()329     bool isUInt7() { return !(m_value.asInt & 0xff80); }
isUInt8()330     bool isUInt8() { return !(m_value.asInt & 0xff00); }
isUInt9()331     bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
isUInt10()332     bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
isUInt12()333     bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
isUInt16()334     bool isUInt16() { return m_type == TypeUInt16; }
getUInt3()335     uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
getUInt4()336     uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
getUInt5()337     uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
getUInt6()338     uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
getUInt7()339     uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
getUInt8()340     uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
getUInt9()341     uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
getUInt10()342     uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
getUInt12()343     uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
getUInt16()344     uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
345 
isEncodedImm()346     bool isEncodedImm() { return m_type == TypeEncoded; }
347 
348 private:
349     ThumbImmediateType m_type;
350     ThumbImmediateValue m_value;
351 };
352 
353 
354 typedef enum {
355     SRType_LSL,
356     SRType_LSR,
357     SRType_ASR,
358     SRType_ROR,
359 
360     SRType_RRX = SRType_ROR
361 } ARMShiftType;
362 
363 class ARMv7Assembler;
364 class ShiftTypeAndAmount {
365     friend class ARMv7Assembler;
366 
367 public:
ShiftTypeAndAmount()368     ShiftTypeAndAmount()
369     {
370         m_u.type = (ARMShiftType)0;
371         m_u.amount = 0;
372     }
373 
ShiftTypeAndAmount(ARMShiftType type,unsigned amount)374     ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
375     {
376         m_u.type = type;
377         m_u.amount = amount & 31;
378     }
379 
lo4()380     unsigned lo4() { return m_u.lo4; }
hi4()381     unsigned hi4() { return m_u.hi4; }
382 
383 private:
384     union {
385         struct {
386             unsigned lo4 : 4;
387             unsigned hi4 : 4;
388         };
389         struct {
390             unsigned type   : 2;
391             unsigned amount : 5;
392         };
393     } m_u;
394 };
395 
396 
397 /*
398 Some features of the Thumb instruction set are deprecated in ARMv7. Deprecated features affecting
399 instructions supported by ARMv7-M are as follows:
400 • use of the PC as <Rd> or <Rm> in a 16-bit ADD (SP plus register) instruction
401 • use of the SP as <Rm> in a 16-bit ADD (SP plus register) instruction
402 • use of the SP as <Rm> in a 16-bit CMP (register) instruction
403 • use of MOV (register) instructions in which <Rd> is the SP or PC and <Rm> is also the SP or PC.
404 • use of <Rn> as the lowest-numbered register in the register list of a 16-bit STM instruction with base
405 register writeback
406 */
407 
408 class ARMv7Assembler {
409 public:
410     typedef ARM::RegisterID RegisterID;
411     typedef ARM::FPRegisterID FPRegisterID;
412 
413     // (HS, LO, HI, LS) -> (AE, B, A, BE)
414     // (VS, VC) -> (O, NO)
415     typedef enum {
416         ConditionEQ,
417         ConditionNE,
418         ConditionHS,
419         ConditionLO,
420         ConditionMI,
421         ConditionPL,
422         ConditionVS,
423         ConditionVC,
424         ConditionHI,
425         ConditionLS,
426         ConditionGE,
427         ConditionLT,
428         ConditionGT,
429         ConditionLE,
430         ConditionAL,
431 
432         ConditionCS = ConditionHS,
433         ConditionCC = ConditionLO,
434     } Condition;
435 
436     class JmpSrc {
437         friend class ARMv7Assembler;
438         friend class ARMInstructionFormatter;
439     public:
JmpSrc()440         JmpSrc()
441             : m_offset(-1)
442         {
443         }
444 
enableLatePatch()445         void enableLatePatch() { }
446     private:
JmpSrc(int offset)447         JmpSrc(int offset)
448             : m_offset(offset)
449         {
450         }
451 
452         int m_offset;
453     };
454 
455     class JmpDst {
456         friend class ARMv7Assembler;
457         friend class ARMInstructionFormatter;
458     public:
JmpDst()459         JmpDst()
460             : m_offset(-1)
461             , m_used(false)
462         {
463         }
464 
isUsed()465         bool isUsed() const { return m_used; }
used()466         void used() { m_used = true; }
467     private:
JmpDst(int offset)468         JmpDst(int offset)
469             : m_offset(offset)
470             , m_used(false)
471         {
472             ASSERT(m_offset == offset);
473         }
474 
475         int m_offset : 31;
476         int m_used : 1;
477     };
478 
479 private:
480 
481     // ARMv7, Appx-A.6.3
BadReg(RegisterID reg)482     bool BadReg(RegisterID reg)
483     {
484         return (reg == ARM::sp) || (reg == ARM::pc);
485     }
486 
isSingleRegister(FPRegisterID reg)487     bool isSingleRegister(FPRegisterID reg)
488     {
489         // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
490         return !(reg & ~31);
491     }
492 
isDoubleRegister(FPRegisterID reg)493     bool isDoubleRegister(FPRegisterID reg)
494     {
495         // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
496         return !(reg & ~(31 << 1));
497     }
498 
isQuadRegister(FPRegisterID reg)499     bool isQuadRegister(FPRegisterID reg)
500     {
501         return !(reg & ~(31 << 2));
502     }
503 
singleRegisterNum(FPRegisterID reg)504     uint32_t singleRegisterNum(FPRegisterID reg)
505     {
506         ASSERT(isSingleRegister(reg));
507         return reg;
508     }
509 
doubleRegisterNum(FPRegisterID reg)510     uint32_t doubleRegisterNum(FPRegisterID reg)
511     {
512         ASSERT(isDoubleRegister(reg));
513         return reg >> 1;
514     }
515 
quadRegisterNum(FPRegisterID reg)516     uint32_t quadRegisterNum(FPRegisterID reg)
517     {
518         ASSERT(isQuadRegister(reg));
519         return reg >> 2;
520     }
521 
singleRegisterMask(FPRegisterID rd,int highBitsShift,int lowBitShift)522     uint32_t singleRegisterMask(FPRegisterID rd, int highBitsShift, int lowBitShift)
523     {
524         uint32_t rdNum = singleRegisterNum(rd);
525         uint32_t rdMask = (rdNum >> 1) << highBitsShift;
526         if (rdNum & 1)
527             rdMask |= 1 << lowBitShift;
528         return rdMask;
529     }
530 
doubleRegisterMask(FPRegisterID rd,int highBitShift,int lowBitsShift)531     uint32_t doubleRegisterMask(FPRegisterID rd, int highBitShift, int lowBitsShift)
532     {
533         uint32_t rdNum = doubleRegisterNum(rd);
534         uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
535         if (rdNum & 16)
536             rdMask |= 1 << highBitShift;
537         return rdMask;
538     }
539 
540     typedef enum {
541         OP_ADD_reg_T1       = 0x1800,
542         OP_ADD_S_reg_T1     = 0x1800,
543         OP_SUB_reg_T1       = 0x1A00,
544         OP_SUB_S_reg_T1     = 0x1A00,
545         OP_ADD_imm_T1       = 0x1C00,
546         OP_ADD_S_imm_T1     = 0x1C00,
547         OP_SUB_imm_T1       = 0x1E00,
548         OP_SUB_S_imm_T1     = 0x1E00,
549         OP_MOV_imm_T1       = 0x2000,
550         OP_CMP_imm_T1       = 0x2800,
551         OP_ADD_imm_T2       = 0x3000,
552         OP_ADD_S_imm_T2     = 0x3000,
553         OP_SUB_imm_T2       = 0x3800,
554         OP_SUB_S_imm_T2     = 0x3800,
555         OP_AND_reg_T1       = 0x4000,
556         OP_EOR_reg_T1       = 0x4040,
557         OP_TST_reg_T1       = 0x4200,
558         OP_CMP_reg_T1       = 0x4280,
559         OP_ORR_reg_T1       = 0x4300,
560         OP_MVN_reg_T1       = 0x43C0,
561         OP_ADD_reg_T2       = 0x4400,
562         OP_MOV_reg_T1       = 0x4600,
563         OP_BLX              = 0x4700,
564         OP_BX               = 0x4700,
565         OP_LDRH_reg_T1      = 0x5A00,
566         OP_STR_reg_T1       = 0x5000,
567         OP_LDR_reg_T1       = 0x5800,
568         OP_STR_imm_T1       = 0x6000,
569         OP_LDR_imm_T1       = 0x6800,
570         OP_LDRH_imm_T1      = 0x8800,
571         OP_STR_imm_T2       = 0x9000,
572         OP_LDR_imm_T2       = 0x9800,
573         OP_ADD_SP_imm_T1    = 0xA800,
574         OP_ADD_SP_imm_T2    = 0xB000,
575         OP_SUB_SP_imm_T1    = 0xB080,
576         OP_BKPT             = 0xBE00,
577         OP_IT               = 0xBF00,
578     } OpcodeID;
579 
580     typedef enum {
581         OP_AND_reg_T2   = 0xEA00,
582         OP_TST_reg_T2   = 0xEA10,
583         OP_ORR_reg_T2   = 0xEA40,
584         OP_ASR_imm_T1   = 0xEA4F,
585         OP_LSL_imm_T1   = 0xEA4F,
586         OP_LSR_imm_T1   = 0xEA4F,
587         OP_ROR_imm_T1   = 0xEA4F,
588         OP_MVN_reg_T2   = 0xEA6F,
589         OP_EOR_reg_T2   = 0xEA80,
590         OP_ADD_reg_T3   = 0xEB00,
591         OP_ADD_S_reg_T3 = 0xEB10,
592         OP_SUB_reg_T2   = 0xEBA0,
593         OP_SUB_S_reg_T2 = 0xEBB0,
594         OP_CMP_reg_T2   = 0xEBB0,
595         OP_B_T4a        = 0xF000,
596         OP_AND_imm_T1   = 0xF000,
597         OP_TST_imm      = 0xF010,
598         OP_ORR_imm_T1   = 0xF040,
599         OP_MOV_imm_T2   = 0xF040,
600         OP_MVN_imm      = 0xF060,
601         OP_EOR_imm_T1   = 0xF080,
602         OP_ADD_imm_T3   = 0xF100,
603         OP_ADD_S_imm_T3 = 0xF110,
604         OP_CMN_imm      = 0xF110,
605         OP_SUB_imm_T3   = 0xF1A0,
606         OP_SUB_S_imm_T3 = 0xF1B0,
607         OP_CMP_imm_T2   = 0xF1B0,
608         OP_ADD_imm_T4   = 0xF200,
609         OP_MOV_imm_T3   = 0xF240,
610         OP_SUB_imm_T4   = 0xF2A0,
611         OP_MOVT         = 0xF2C0,
612         OP_LDRH_reg_T2  = 0xF830,
613         OP_LDRH_imm_T3  = 0xF830,
614         OP_STR_imm_T4   = 0xF840,
615         OP_STR_reg_T2   = 0xF840,
616         OP_LDR_imm_T4   = 0xF850,
617         OP_LDR_reg_T2   = 0xF850,
618         OP_LDRH_imm_T2  = 0xF8B0,
619         OP_STR_imm_T3   = 0xF8C0,
620         OP_LDR_imm_T3   = 0xF8D0,
621         OP_LSL_reg_T2   = 0xFA00,
622         OP_LSR_reg_T2   = 0xFA20,
623         OP_ASR_reg_T2   = 0xFA40,
624         OP_ROR_reg_T2   = 0xFA60,
625         OP_SMULL_T1     = 0xFB80,
626     } OpcodeID1;
627 
628     typedef enum {
629         OP_B_T4b        = 0x9000,
630     } OpcodeID2;
631 
632     struct FourFours {
FourFoursFourFours633         FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
634         {
635             m_u.f0 = f0;
636             m_u.f1 = f1;
637             m_u.f2 = f2;
638             m_u.f3 = f3;
639         }
640 
641         union {
642             unsigned value;
643             struct {
644                 unsigned f0 : 4;
645                 unsigned f1 : 4;
646                 unsigned f2 : 4;
647                 unsigned f3 : 4;
648             };
649         } m_u;
650     };
651 
652     class ARMInstructionFormatter;
653 
654     // false means else!
ifThenElseConditionBit(Condition condition,bool isIf)655     bool ifThenElseConditionBit(Condition condition, bool isIf)
656     {
657         return isIf ? (condition & 1) : !(condition & 1);
658     }
ifThenElse(Condition condition,bool inst2if,bool inst3if,bool inst4if)659     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
660     {
661         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
662             | (ifThenElseConditionBit(condition, inst3if) << 2)
663             | (ifThenElseConditionBit(condition, inst4if) << 1)
664             | 1;
665         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
666         return (condition << 4) | mask;
667     }
ifThenElse(Condition condition,bool inst2if,bool inst3if)668     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
669     {
670         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
671             | (ifThenElseConditionBit(condition, inst3if) << 2)
672             | 2;
673         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
674         return (condition << 4) | mask;
675     }
ifThenElse(Condition condition,bool inst2if)676     uint8_t ifThenElse(Condition condition, bool inst2if)
677     {
678         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
679             | 4;
680         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
681         return (condition << 4) | mask;
682     }
683 
ifThenElse(Condition condition)684     uint8_t ifThenElse(Condition condition)
685     {
686         int mask = 8;
687         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
688         return (condition << 4) | mask;
689     }
690 
691 public:
692 
add(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)693     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
694     {
695         // Rd can only be SP if Rn is also SP.
696         ASSERT((rd != ARM::sp) || (rn == ARM::sp));
697         ASSERT(rd != ARM::pc);
698         ASSERT(rn != ARM::pc);
699         ASSERT(imm.isValid());
700 
701         if (rn == ARM::sp) {
702             if (!(rd & 8) && imm.isUInt10()) {
703                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
704                 return;
705             } else if ((rd == ARM::sp) && imm.isUInt9()) {
706                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
707                 return;
708             }
709         } else if (!((rd | rn) & 8)) {
710             if (imm.isUInt3()) {
711                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
712                 return;
713             } else if ((rd == rn) && imm.isUInt8()) {
714                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
715                 return;
716             }
717         }
718 
719         if (imm.isEncodedImm())
720             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
721         else {
722             ASSERT(imm.isUInt12());
723             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
724         }
725     }
726 
add(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)727     void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
728     {
729         ASSERT((rd != ARM::sp) || (rn == ARM::sp));
730         ASSERT(rd != ARM::pc);
731         ASSERT(rn != ARM::pc);
732         ASSERT(!BadReg(rm));
733         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
734     }
735 
736     // NOTE: In an IT block, add doesn't modify the flags register.
add(RegisterID rd,RegisterID rn,RegisterID rm)737     void add(RegisterID rd, RegisterID rn, RegisterID rm)
738     {
739         if (rd == rn)
740             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
741         else if (rd == rm)
742             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
743         else if (!((rd | rn | rm) & 8))
744             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
745         else
746             add(rd, rn, rm, ShiftTypeAndAmount());
747     }
748 
749     // Not allowed in an IT (if then) block.
add_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)750     void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
751     {
752         // Rd can only be SP if Rn is also SP.
753         ASSERT((rd != ARM::sp) || (rn == ARM::sp));
754         ASSERT(rd != ARM::pc);
755         ASSERT(rn != ARM::pc);
756         ASSERT(imm.isEncodedImm());
757 
758         if (!((rd | rn) & 8)) {
759             if (imm.isUInt3()) {
760                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
761                 return;
762             } else if ((rd == rn) && imm.isUInt8()) {
763                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_S_imm_T2, rd, imm.getUInt8());
764                 return;
765             }
766         }
767 
768         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
769     }
770 
771     // Not allowed in an IT (if then) block?
add_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)772     void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
773     {
774         ASSERT((rd != ARM::sp) || (rn == ARM::sp));
775         ASSERT(rd != ARM::pc);
776         ASSERT(rn != ARM::pc);
777         ASSERT(!BadReg(rm));
778         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
779     }
780 
781     // Not allowed in an IT (if then) block.
add_S(RegisterID rd,RegisterID rn,RegisterID rm)782     void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
783     {
784         if (!((rd | rn | rm) & 8))
785             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_reg_T1, rm, rn, rd);
786         else
787             add_S(rd, rn, rm, ShiftTypeAndAmount());
788     }
789 
ARM_and(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)790     void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
791     {
792         ASSERT(!BadReg(rd));
793         ASSERT(!BadReg(rn));
794         ASSERT(imm.isEncodedImm());
795         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
796     }
797 
ARM_and(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)798     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
799     {
800         ASSERT(!BadReg(rd));
801         ASSERT(!BadReg(rn));
802         ASSERT(!BadReg(rm));
803         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
804     }
805 
ARM_and(RegisterID rd,RegisterID rn,RegisterID rm)806     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
807     {
808         if ((rd == rn) && !((rd | rm) & 8))
809             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
810         else if ((rd == rm) && !((rd | rn) & 8))
811             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
812         else
813             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
814     }
815 
asr(RegisterID rd,RegisterID rm,int32_t shiftAmount)816     void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
817     {
818         ASSERT(!BadReg(rd));
819         ASSERT(!BadReg(rm));
820         ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
821         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
822     }
823 
asr(RegisterID rd,RegisterID rn,RegisterID rm)824     void asr(RegisterID rd, RegisterID rn, RegisterID rm)
825     {
826         ASSERT(!BadReg(rd));
827         ASSERT(!BadReg(rn));
828         ASSERT(!BadReg(rm));
829         m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
830     }
831 
832     // Only allowed in IT (if then) block if last instruction.
b()833     JmpSrc b()
834     {
835         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
836         return JmpSrc(m_formatter.size());
837     }
838 
839     // Only allowed in IT (if then) block if last instruction.
blx(RegisterID rm)840     JmpSrc blx(RegisterID rm)
841     {
842         ASSERT(rm != ARM::pc);
843         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
844         return JmpSrc(m_formatter.size());
845     }
846 
847     // Only allowed in IT (if then) block if last instruction.
bx(RegisterID rm)848     JmpSrc bx(RegisterID rm)
849     {
850         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
851         return JmpSrc(m_formatter.size());
852     }
853 
854     void bkpt(uint8_t imm=0)
855     {
856         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
857     }
858 
cmn(RegisterID rn,ARMThumbImmediate imm)859     void cmn(RegisterID rn, ARMThumbImmediate imm)
860     {
861         ASSERT(rn != ARM::pc);
862         ASSERT(imm.isEncodedImm());
863 
864         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
865     }
866 
cmp(RegisterID rn,ARMThumbImmediate imm)867     void cmp(RegisterID rn, ARMThumbImmediate imm)
868     {
869         ASSERT(rn != ARM::pc);
870         ASSERT(imm.isEncodedImm());
871 
872         if (!(rn & 8) && imm.isUInt8())
873             m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
874         else
875             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
876     }
877 
cmp(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)878     void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
879     {
880         ASSERT(rn != ARM::pc);
881         ASSERT(!BadReg(rm));
882         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
883     }
884 
cmp(RegisterID rn,RegisterID rm)885     void cmp(RegisterID rn, RegisterID rm)
886     {
887         if ((rn | rm) & 8)
888             cmp(rn, rm, ShiftTypeAndAmount());
889         else
890             m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
891     }
892 
893     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)894     void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
895     {
896         ASSERT(!BadReg(rd));
897         ASSERT(!BadReg(rn));
898         ASSERT(imm.isEncodedImm());
899         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
900     }
901 
902     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)903     void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
904     {
905         ASSERT(!BadReg(rd));
906         ASSERT(!BadReg(rn));
907         ASSERT(!BadReg(rm));
908         m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
909     }
910 
911     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,RegisterID rm)912     void eor(RegisterID rd, RegisterID rn, RegisterID rm)
913     {
914         if ((rd == rn) && !((rd | rm) & 8))
915             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
916         else if ((rd == rm) && !((rd | rn) & 8))
917             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
918         else
919             eor(rd, rn, rm, ShiftTypeAndAmount());
920     }
921 
it(Condition cond)922     void it(Condition cond)
923     {
924         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
925     }
926 
it(Condition cond,bool inst2if)927     void it(Condition cond, bool inst2if)
928     {
929         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
930     }
931 
it(Condition cond,bool inst2if,bool inst3if)932     void it(Condition cond, bool inst2if, bool inst3if)
933     {
934         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
935     }
936 
it(Condition cond,bool inst2if,bool inst3if,bool inst4if)937     void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
938     {
939         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
940     }
941 
942     // rt == ARM::pc only allowed if last instruction in IT (if then) block.
ldr(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)943     void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
944     {
945         ASSERT(rn != ARM::pc); // LDR (literal)
946         ASSERT(imm.isUInt12());
947 
948         if (!((rt | rn) & 8) && imm.isUInt7())
949             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
950         else if ((rn == ARM::sp) && !(rt & 8) && imm.isUInt10())
951             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
952         else
953             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
954     }
955 
956     // If index is set, this is a regular offset or a pre-indexed load;
957     // if index is not set then is is a post-index load.
958     //
959     // If wback is set rn is updated - this is a pre or post index load,
960     // if wback is not set this is a regular offset memory access.
961     //
962     // (-255 <= offset <= 255)
963     // _reg = REG[rn]
964     // _tmp = _reg + offset
965     // MEM[index ? _tmp : _reg] = REG[rt]
966     // if (wback) REG[rn] = _tmp
ldr(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)967     void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
968     {
969         ASSERT(rt != ARM::pc);
970         ASSERT(rn != ARM::pc);
971         ASSERT(index || wback);
972         ASSERT(!wback | (rt != rn));
973 
974         bool add = true;
975         if (offset < 0) {
976             add = false;
977             offset = -offset;
978         }
979         ASSERT((offset & ~0xff) == 0);
980 
981         offset |= (wback << 8);
982         offset |= (add   << 9);
983         offset |= (index << 10);
984         offset |= (1 << 11);
985 
986         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
987     }
988 
989     // rt == ARM::pc only allowed if last instruction in IT (if then) block.
990     void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
991     {
992         ASSERT(rn != ARM::pc); // LDR (literal)
993         ASSERT(!BadReg(rm));
994         ASSERT(shift <= 3);
995 
996         if (!shift && !((rt | rn | rm) & 8))
997             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
998         else
999             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1000     }
1001 
1002     // rt == ARM::pc only allowed if last instruction in IT (if then) block.
ldrh(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1003     void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1004     {
1005         ASSERT(rn != ARM::pc); // LDR (literal)
1006         ASSERT(imm.isUInt12());
1007 
1008         if (!((rt | rn) & 8) && imm.isUInt6())
1009             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
1010         else
1011             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
1012     }
1013 
1014     // If index is set, this is a regular offset or a pre-indexed load;
1015     // if index is not set then is is a post-index load.
1016     //
1017     // If wback is set rn is updated - this is a pre or post index load,
1018     // if wback is not set this is a regular offset memory access.
1019     //
1020     // (-255 <= offset <= 255)
1021     // _reg = REG[rn]
1022     // _tmp = _reg + offset
1023     // MEM[index ? _tmp : _reg] = REG[rt]
1024     // if (wback) REG[rn] = _tmp
ldrh(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1025     void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1026     {
1027         ASSERT(rt != ARM::pc);
1028         ASSERT(rn != ARM::pc);
1029         ASSERT(index || wback);
1030         ASSERT(!wback | (rt != rn));
1031 
1032         bool add = true;
1033         if (offset < 0) {
1034             add = false;
1035             offset = -offset;
1036         }
1037         ASSERT((offset & ~0xff) == 0);
1038 
1039         offset |= (wback << 8);
1040         offset |= (add   << 9);
1041         offset |= (index << 10);
1042         offset |= (1 << 11);
1043 
1044         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
1045     }
1046 
1047     void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1048     {
1049         ASSERT(!BadReg(rt));   // Memory hint
1050         ASSERT(rn != ARM::pc); // LDRH (literal)
1051         ASSERT(!BadReg(rm));
1052         ASSERT(shift <= 3);
1053 
1054         if (!shift && !((rt | rn | rm) & 8))
1055             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
1056         else
1057             m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1058     }
1059 
lsl(RegisterID rd,RegisterID rm,int32_t shiftAmount)1060     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1061     {
1062         ASSERT(!BadReg(rd));
1063         ASSERT(!BadReg(rm));
1064         ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
1065         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1066     }
1067 
lsl(RegisterID rd,RegisterID rn,RegisterID rm)1068     void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
1069     {
1070         ASSERT(!BadReg(rd));
1071         ASSERT(!BadReg(rn));
1072         ASSERT(!BadReg(rm));
1073         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1074     }
1075 
lsr(RegisterID rd,RegisterID rm,int32_t shiftAmount)1076     void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1077     {
1078         ASSERT(!BadReg(rd));
1079         ASSERT(!BadReg(rm));
1080         ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
1081         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1082     }
1083 
lsr(RegisterID rd,RegisterID rn,RegisterID rm)1084     void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
1085     {
1086         ASSERT(!BadReg(rd));
1087         ASSERT(!BadReg(rn));
1088         ASSERT(!BadReg(rm));
1089         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1090     }
1091 
movT3(RegisterID rd,ARMThumbImmediate imm)1092     void movT3(RegisterID rd, ARMThumbImmediate imm)
1093     {
1094         ASSERT(imm.isValid());
1095         ASSERT(!imm.isEncodedImm());
1096         ASSERT(!BadReg(rd));
1097 
1098         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
1099     }
1100 
mov(RegisterID rd,ARMThumbImmediate imm)1101      void mov(RegisterID rd, ARMThumbImmediate imm)
1102     {
1103         ASSERT(imm.isValid());
1104         ASSERT(!BadReg(rd));
1105 
1106         if ((rd < 8) && imm.isUInt8())
1107             m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
1108         else if (imm.isEncodedImm())
1109             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
1110         else
1111             movT3(rd, imm);
1112     }
1113 
mov(RegisterID rd,RegisterID rm)1114    void mov(RegisterID rd, RegisterID rm)
1115     {
1116         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
1117     }
1118 
movt(RegisterID rd,ARMThumbImmediate imm)1119     void movt(RegisterID rd, ARMThumbImmediate imm)
1120     {
1121         ASSERT(imm.isUInt16());
1122         ASSERT(!BadReg(rd));
1123         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
1124     }
1125 
mvn(RegisterID rd,ARMThumbImmediate imm)1126     void mvn(RegisterID rd, ARMThumbImmediate imm)
1127     {
1128         ASSERT(imm.isEncodedImm());
1129         ASSERT(!BadReg(rd));
1130 
1131         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
1132     }
1133 
mvn(RegisterID rd,RegisterID rm,ShiftTypeAndAmount shift)1134     void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
1135     {
1136         ASSERT(!BadReg(rd));
1137         ASSERT(!BadReg(rm));
1138         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1139     }
1140 
mvn(RegisterID rd,RegisterID rm)1141     void mvn(RegisterID rd, RegisterID rm)
1142     {
1143         if (!((rd | rm) & 8))
1144             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
1145         else
1146             mvn(rd, rm, ShiftTypeAndAmount());
1147     }
1148 
orr(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1149     void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1150     {
1151         ASSERT(!BadReg(rd));
1152         ASSERT(!BadReg(rn));
1153         ASSERT(imm.isEncodedImm());
1154         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
1155     }
1156 
orr(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1157     void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1158     {
1159         ASSERT(!BadReg(rd));
1160         ASSERT(!BadReg(rn));
1161         ASSERT(!BadReg(rm));
1162         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1163     }
1164 
orr(RegisterID rd,RegisterID rn,RegisterID rm)1165     void orr(RegisterID rd, RegisterID rn, RegisterID rm)
1166     {
1167         if ((rd == rn) && !((rd | rm) & 8))
1168             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1169         else if ((rd == rm) && !((rd | rn) & 8))
1170             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1171         else
1172             orr(rd, rn, rm, ShiftTypeAndAmount());
1173     }
1174 
ror(RegisterID rd,RegisterID rm,int32_t shiftAmount)1175     void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1176     {
1177         ASSERT(!BadReg(rd));
1178         ASSERT(!BadReg(rm));
1179         ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
1180         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1181     }
1182 
ror(RegisterID rd,RegisterID rn,RegisterID rm)1183     void ror(RegisterID rd, RegisterID rn, RegisterID rm)
1184     {
1185         ASSERT(!BadReg(rd));
1186         ASSERT(!BadReg(rn));
1187         ASSERT(!BadReg(rm));
1188         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1189     }
1190 
smull(RegisterID rdLo,RegisterID rdHi,RegisterID rn,RegisterID rm)1191     void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
1192     {
1193         ASSERT(!BadReg(rdLo));
1194         ASSERT(!BadReg(rdHi));
1195         ASSERT(!BadReg(rn));
1196         ASSERT(!BadReg(rm));
1197         ASSERT(rdLo != rdHi);
1198         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
1199     }
1200 
1201     // rt == ARM::pc only allowed if last instruction in IT (if then) block.
str(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1202     void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1203     {
1204         ASSERT(rt != ARM::pc);
1205         ASSERT(rn != ARM::pc);
1206         ASSERT(imm.isUInt12());
1207 
1208         if (!((rt | rn) & 8) && imm.isUInt7())
1209             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1210         else if ((rn == ARM::sp) && !(rt & 8) && imm.isUInt10())
1211             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
1212         else
1213             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
1214     }
1215 
1216     // If index is set, this is a regular offset or a pre-indexed store;
1217     // if index is not set then is is a post-index store.
1218     //
1219     // If wback is set rn is updated - this is a pre or post index store,
1220     // if wback is not set this is a regular offset memory access.
1221     //
1222     // (-255 <= offset <= 255)
1223     // _reg = REG[rn]
1224     // _tmp = _reg + offset
1225     // MEM[index ? _tmp : _reg] = REG[rt]
1226     // if (wback) REG[rn] = _tmp
str(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1227     void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1228     {
1229         ASSERT(rt != ARM::pc);
1230         ASSERT(rn != ARM::pc);
1231         ASSERT(index || wback);
1232         ASSERT(!wback | (rt != rn));
1233 
1234         bool add = true;
1235         if (offset < 0) {
1236             add = false;
1237             offset = -offset;
1238         }
1239         ASSERT((offset & ~0xff) == 0);
1240 
1241         offset |= (wback << 8);
1242         offset |= (add   << 9);
1243         offset |= (index << 10);
1244         offset |= (1 << 11);
1245 
1246         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
1247     }
1248 
1249     // rt == ARM::pc only allowed if last instruction in IT (if then) block.
1250     void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1251     {
1252         ASSERT(rn != ARM::pc);
1253         ASSERT(!BadReg(rm));
1254         ASSERT(shift <= 3);
1255 
1256         if (!shift && !((rt | rn | rm) & 8))
1257             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
1258         else
1259             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1260     }
1261 
sub(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1262     void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1263     {
1264         // Rd can only be SP if Rn is also SP.
1265         ASSERT((rd != ARM::sp) || (rn == ARM::sp));
1266         ASSERT(rd != ARM::pc);
1267         ASSERT(rn != ARM::pc);
1268         ASSERT(imm.isValid());
1269 
1270         if ((rn == ARM::sp) && (rd == ARM::sp) && imm.isUInt9()) {
1271             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1272             return;
1273         } else if (!((rd | rn) & 8)) {
1274             if (imm.isUInt3()) {
1275                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1276                 return;
1277             } else if ((rd == rn) && imm.isUInt8()) {
1278                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1279                 return;
1280             }
1281         }
1282 
1283         if (imm.isEncodedImm())
1284             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
1285         else {
1286             ASSERT(imm.isUInt12());
1287             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
1288         }
1289     }
1290 
sub(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1291     void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1292     {
1293         ASSERT((rd != ARM::sp) || (rn == ARM::sp));
1294         ASSERT(rd != ARM::pc);
1295         ASSERT(rn != ARM::pc);
1296         ASSERT(!BadReg(rm));
1297         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1298     }
1299 
1300     // NOTE: In an IT block, add doesn't modify the flags register.
sub(RegisterID rd,RegisterID rn,RegisterID rm)1301     void sub(RegisterID rd, RegisterID rn, RegisterID rm)
1302     {
1303         if (!((rd | rn | rm) & 8))
1304             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1305         else
1306             sub(rd, rn, rm, ShiftTypeAndAmount());
1307     }
1308 
1309     // Not allowed in an IT (if then) block.
sub_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1310     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1311     {
1312         // Rd can only be SP if Rn is also SP.
1313         ASSERT((rd != ARM::sp) || (rn == ARM::sp));
1314         ASSERT(rd != ARM::pc);
1315         ASSERT(rn != ARM::pc);
1316         ASSERT(imm.isValid());
1317 
1318         if ((rn == ARM::sp) && (rd == ARM::sp) && imm.isUInt9()) {
1319             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1320             return;
1321         } else if (!((rd | rn) & 8)) {
1322             if (imm.isUInt3()) {
1323                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1324                 return;
1325             } else if ((rd == rn) && imm.isUInt8()) {
1326                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_S_imm_T2, rd, imm.getUInt8());
1327                 return;
1328             }
1329         }
1330 
1331         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
1332     }
1333 
1334     // Not allowed in an IT (if then) block?
sub_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1335     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1336     {
1337         ASSERT((rd != ARM::sp) || (rn == ARM::sp));
1338         ASSERT(rd != ARM::pc);
1339         ASSERT(rn != ARM::pc);
1340         ASSERT(!BadReg(rm));
1341         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1342     }
1343 
1344     // Not allowed in an IT (if then) block.
sub_S(RegisterID rd,RegisterID rn,RegisterID rm)1345     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
1346     {
1347         if (!((rd | rn | rm) & 8))
1348             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_reg_T1, rm, rn, rd);
1349         else
1350             sub_S(rd, rn, rm, ShiftTypeAndAmount());
1351     }
1352 
tst(RegisterID rn,ARMThumbImmediate imm)1353     void tst(RegisterID rn, ARMThumbImmediate imm)
1354     {
1355         ASSERT(!BadReg(rn));
1356         ASSERT(imm.isEncodedImm());
1357 
1358         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
1359     }
1360 
tst(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1361     void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1362     {
1363         ASSERT(!BadReg(rn));
1364         ASSERT(!BadReg(rm));
1365         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1366     }
1367 
tst(RegisterID rn,RegisterID rm)1368     void tst(RegisterID rn, RegisterID rm)
1369     {
1370         if ((rn | rm) & 8)
1371             tst(rn, rm, ShiftTypeAndAmount());
1372         else
1373             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
1374     }
1375 
vadd_F64(FPRegisterID rd,FPRegisterID rn,FPRegisterID rm)1376     void vadd_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1377     {
1378         m_formatter.vfpOp(0x0b00ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1379     }
1380 
vcmp_F64(FPRegisterID rd,FPRegisterID rm)1381     void vcmp_F64(FPRegisterID rd, FPRegisterID rm)
1382     {
1383         m_formatter.vfpOp(0x0bc0eeb4 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rm, 21, 16));
1384     }
1385 
vcvt_F64_S32(FPRegisterID fd,FPRegisterID sm)1386     void vcvt_F64_S32(FPRegisterID fd, FPRegisterID sm)
1387     {
1388         m_formatter.vfpOp(0x0bc0eeb8 | doubleRegisterMask(fd, 6, 28) | singleRegisterMask(sm, 16, 21));
1389     }
1390 
vcvt_S32_F64(FPRegisterID sd,FPRegisterID fm)1391     void vcvt_S32_F64(FPRegisterID sd, FPRegisterID fm)
1392     {
1393         m_formatter.vfpOp(0x0bc0eebd | singleRegisterMask(sd, 28, 6) | doubleRegisterMask(fm, 21, 16));
1394     }
1395 
vldr(FPRegisterID rd,RegisterID rn,int32_t imm)1396     void vldr(FPRegisterID rd, RegisterID rn, int32_t imm)
1397     {
1398         vmem(rd, rn, imm, true);
1399     }
1400 
vmov(RegisterID rd,FPRegisterID sn)1401     void vmov(RegisterID rd, FPRegisterID sn)
1402     {
1403         m_formatter.vfpOp(0x0a10ee10 | (rd << 28) | singleRegisterMask(sn, 0, 23));
1404     }
1405 
vmov(FPRegisterID sn,RegisterID rd)1406     void vmov(FPRegisterID sn, RegisterID rd)
1407     {
1408         m_formatter.vfpOp(0x0a10ee00 | (rd << 28) | singleRegisterMask(sn, 0, 23));
1409     }
1410 
1411     // move FPSCR flags to APSR.
vmrs_APSR_nzcv_FPSCR()1412     void vmrs_APSR_nzcv_FPSCR()
1413     {
1414         m_formatter.vfpOp(0xfa10eef1);
1415     }
1416 
vmul_F64(FPRegisterID rd,FPRegisterID rn,FPRegisterID rm)1417     void vmul_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1418     {
1419         m_formatter.vfpOp(0x0b00ee20 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1420     }
1421 
vstr(FPRegisterID rd,RegisterID rn,int32_t imm)1422     void vstr(FPRegisterID rd, RegisterID rn, int32_t imm)
1423     {
1424         vmem(rd, rn, imm, false);
1425     }
1426 
vsub_F64(FPRegisterID rd,FPRegisterID rn,FPRegisterID rm)1427     void vsub_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1428     {
1429         m_formatter.vfpOp(0x0b40ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1430     }
1431 
1432 
label()1433     JmpDst label()
1434     {
1435         return JmpDst(m_formatter.size());
1436     }
1437 
align(int alignment)1438     JmpDst align(int alignment)
1439     {
1440         while (!m_formatter.isAligned(alignment))
1441             bkpt();
1442 
1443         return label();
1444     }
1445 
getRelocatedAddress(void * code,JmpSrc jump)1446     static void* getRelocatedAddress(void* code, JmpSrc jump)
1447     {
1448         ASSERT(jump.m_offset != -1);
1449 
1450         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1451     }
1452 
getRelocatedAddress(void * code,JmpDst destination)1453     static void* getRelocatedAddress(void* code, JmpDst destination)
1454     {
1455         ASSERT(destination.m_offset != -1);
1456 
1457         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
1458     }
1459 
getDifferenceBetweenLabels(JmpDst src,JmpDst dst)1460     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1461     {
1462         return dst.m_offset - src.m_offset;
1463     }
1464 
getDifferenceBetweenLabels(JmpDst src,JmpSrc dst)1465     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1466     {
1467         return dst.m_offset - src.m_offset;
1468     }
1469 
getDifferenceBetweenLabels(JmpSrc src,JmpDst dst)1470     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
1471     {
1472         return dst.m_offset - src.m_offset;
1473     }
1474 
1475     // Assembler admin methods:
1476 
size()1477     size_t size() const
1478     {
1479         return m_formatter.size();
1480     }
1481 
executableCopy(ExecutablePool * allocator)1482     void* executableCopy(ExecutablePool* allocator)
1483     {
1484         void* copy = m_formatter.executableCopy(allocator);
1485         ASSERT(copy);
1486         return copy;
1487     }
1488 
getCallReturnOffset(JmpSrc call)1489     static unsigned getCallReturnOffset(JmpSrc call)
1490     {
1491         ASSERT(call.m_offset >= 0);
1492         return call.m_offset;
1493     }
1494 
1495     // Linking & patching:
1496     //
1497     // 'link' and 'patch' methods are for use on unprotected code - such as the code
1498     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
1499     // code has been finalized it is (platform support permitting) within a non-
1500     // writable region of memory; to modify the code in an execute-only execuable
1501     // pool the 'repatch' and 'relink' methods should be used.
1502 
linkJump(JmpSrc from,JmpDst to)1503     void linkJump(JmpSrc from, JmpDst to)
1504     {
1505         ASSERT(to.m_offset != -1);
1506         ASSERT(from.m_offset != -1);
1507 
1508         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(m_formatter.data()) + from.m_offset);
1509         intptr_t relative = to.m_offset - from.m_offset;
1510 
1511         linkWithOffset(location, relative);
1512     }
1513 
linkJump(void * code,JmpSrc from,void * to)1514     static void linkJump(void* code, JmpSrc from, void* to)
1515     {
1516         ASSERT(from.m_offset != -1);
1517 
1518         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
1519         intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(location);
1520 
1521         linkWithOffset(location, relative);
1522     }
1523 
1524     // bah, this mathod should really be static, since it is used by the LinkBuffer.
1525     // return a bool saying whether the link was successful?
linkCall(void * code,JmpSrc from,void * to)1526     static void linkCall(void* code, JmpSrc from, void* to)
1527     {
1528         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
1529         ASSERT(from.m_offset != -1);
1530         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1531 
1532         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
1533     }
1534 
linkPointer(void * code,JmpDst where,void * value)1535     static void linkPointer(void* code, JmpDst where, void* value)
1536     {
1537         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
1538     }
1539 
relinkJump(void * from,void * to)1540     static void relinkJump(void* from, void* to)
1541     {
1542         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1543         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
1544 
1545         intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
1546         linkWithOffset(reinterpret_cast<uint16_t*>(from), relative);
1547 
1548         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 2, 2 * sizeof(uint16_t));
1549     }
1550 
relinkCall(void * from,void * to)1551     static void relinkCall(void* from, void* to)
1552     {
1553         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1554         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1555 
1556         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
1557 
1558         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 4 * sizeof(uint16_t));
1559     }
1560 
repatchInt32(void * where,int32_t value)1561     static void repatchInt32(void* where, int32_t value)
1562     {
1563         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1564 
1565         setInt32(where, value);
1566 
1567         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
1568     }
1569 
repatchPointer(void * where,void * value)1570     static void repatchPointer(void* where, void* value)
1571     {
1572         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1573 
1574         setPointer(where, value);
1575 
1576         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
1577     }
1578 
repatchLoadPtrToLEA(void * where)1579     static void repatchLoadPtrToLEA(void* where)
1580     {
1581         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1582 
1583         uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
1584         ASSERT((*loadOp & 0xfff0) == OP_LDR_reg_T2);
1585 
1586         *loadOp = OP_ADD_reg_T3 | (*loadOp & 0xf);
1587         ExecutableAllocator::cacheFlush(loadOp, sizeof(uint16_t));
1588     }
1589 
1590 private:
1591 
1592     // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
1593     // (i.e. +/-(0..255) 32-bit words)
vmem(FPRegisterID rd,RegisterID rn,int32_t imm,bool isLoad)1594     void vmem(FPRegisterID rd, RegisterID rn, int32_t imm, bool isLoad)
1595     {
1596         bool up;
1597         uint32_t offset;
1598         if (imm < 0) {
1599             offset = -imm;
1600             up = false;
1601         } else {
1602             offset = imm;
1603             up = true;
1604         }
1605 
1606         // offset is effectively leftshifted by 2 already (the bottom two bits are zero, and not
1607         // reperesented in the instruction.  Left shift by 14, to mov it into position 0x00AA0000.
1608         ASSERT((offset & ~(0xff << 2)) == 0);
1609         offset <<= 14;
1610 
1611         m_formatter.vfpOp(0x0b00ed00 | offset | (up << 7) | (isLoad << 4) | doubleRegisterMask(rd, 6, 28) | rn);
1612     }
1613 
setInt32(void * code,uint32_t value)1614     static void setInt32(void* code, uint32_t value)
1615     {
1616         uint16_t* location = reinterpret_cast<uint16_t*>(code);
1617 
1618         uint16_t lo16 = value;
1619         uint16_t hi16 = value >> 16;
1620 
1621         spliceHi5(location - 4, lo16);
1622         spliceLo11(location - 3, lo16);
1623         spliceHi5(location - 2, hi16);
1624         spliceLo11(location - 1, hi16);
1625 
1626         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
1627     }
1628 
setPointer(void * code,void * value)1629     static void setPointer(void* code, void* value)
1630     {
1631         setInt32(code, reinterpret_cast<uint32_t>(value));
1632     }
1633 
1634     // Linking & patching:
1635     // This method assumes that the JmpSrc being linked is a T4 b instruction.
linkWithOffset(uint16_t * instruction,intptr_t relative)1636     static void linkWithOffset(uint16_t* instruction, intptr_t relative)
1637     {
1638         // Currently branches > 16m = mostly deathy.
1639         if (((relative << 7) >> 7) != relative) {
1640             // FIXME: This CRASH means we cannot turn the JIT on by default on arm-v7.
1641             fprintf(stderr, "Error: Cannot link T4b.\n");
1642             CRASH();
1643         }
1644 
1645         // ARM encoding for the top two bits below the sign bit is 'peculiar'.
1646         if (relative >= 0)
1647             relative ^= 0xC00000;
1648 
1649         // All branch offsets should be an even distance.
1650         ASSERT(!(relative & 1));
1651 
1652         int word1 = ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
1653         int word2 = ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
1654 
1655         instruction[-2] = OP_B_T4a | word1;
1656         instruction[-1] = OP_B_T4b | word2;
1657     }
1658 
1659     // These functions can be used to splice 16-bit immediates back into previously generated instructions.
spliceHi5(uint16_t * where,uint16_t what)1660     static void spliceHi5(uint16_t* where, uint16_t what)
1661     {
1662         uint16_t pattern = (what >> 12) | ((what & 0x0800) >> 1);
1663         *where = (*where & 0xFBF0) | pattern;
1664     }
spliceLo11(uint16_t * where,uint16_t what)1665     static void spliceLo11(uint16_t* where, uint16_t what)
1666     {
1667         uint16_t pattern = ((what & 0x0700) << 4) | (what & 0x00FF);
1668         *where = (*where & 0x8F00) | pattern;
1669     }
1670 
1671     class ARMInstructionFormatter {
1672     public:
oneWordOp5Reg3Imm8(OpcodeID op,RegisterID rd,uint8_t imm)1673         void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
1674         {
1675             m_buffer.putShort(op | (rd << 8) | imm);
1676         }
1677 
oneWordOp5Imm5Reg3Reg3(OpcodeID op,uint8_t imm,RegisterID reg1,RegisterID reg2)1678         void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
1679         {
1680             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
1681         }
1682 
oneWordOp7Reg3Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2,RegisterID reg3)1683         void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
1684         {
1685             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
1686         }
1687 
oneWordOp8Imm8(OpcodeID op,uint8_t imm)1688         void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
1689         {
1690             m_buffer.putShort(op | imm);
1691         }
1692 
oneWordOp8RegReg143(OpcodeID op,RegisterID reg1,RegisterID reg2)1693         void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
1694         {
1695             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
1696         }
oneWordOp9Imm7(OpcodeID op,uint8_t imm)1697         void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
1698         {
1699             m_buffer.putShort(op | imm);
1700         }
1701 
oneWordOp10Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2)1702         void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
1703         {
1704             m_buffer.putShort(op | (reg1 << 3) | reg2);
1705         }
1706 
twoWordOp12Reg4FourFours(OpcodeID1 op,RegisterID reg,FourFours ff)1707         void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
1708         {
1709             m_buffer.putShort(op | reg);
1710             m_buffer.putShort(ff.m_u.value);
1711         }
1712 
twoWordOp16FourFours(OpcodeID1 op,FourFours ff)1713         void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
1714         {
1715             m_buffer.putShort(op);
1716             m_buffer.putShort(ff.m_u.value);
1717         }
1718 
twoWordOp16Op16(OpcodeID1 op1,OpcodeID2 op2)1719         void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
1720         {
1721             m_buffer.putShort(op1);
1722             m_buffer.putShort(op2);
1723         }
1724 
twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op,int imm4,RegisterID rd,ARMThumbImmediate imm)1725         void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
1726         {
1727             m_buffer.putShort(op | (imm.m_value.i << 10) | imm4);
1728             m_buffer.putShort((imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8);
1729         }
1730 
twoWordOp12Reg4Reg4Imm12(OpcodeID1 op,RegisterID reg1,RegisterID reg2,uint16_t imm)1731         void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
1732         {
1733             m_buffer.putShort(op | reg1);
1734             m_buffer.putShort((reg2 << 12) | imm);
1735         }
1736 
vfpOp(int32_t op)1737         void vfpOp(int32_t op)
1738         {
1739             m_buffer.putInt(op);
1740         }
1741 
1742 
1743         // Administrative methods:
1744 
size()1745         size_t size() const { return m_buffer.size(); }
isAligned(int alignment)1746         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
data()1747         void* data() const { return m_buffer.data(); }
executableCopy(ExecutablePool * allocator)1748         void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
1749 
1750     private:
1751         AssemblerBuffer m_buffer;
1752     } m_formatter;
1753 };
1754 
1755 } // namespace JSC
1756 
1757 #endif // ENABLE(ASSEMBLER) && PLATFORM_ARM_ARCH(7)
1758 
1759 #endif // ARMAssembler_h
1760