• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 University of Szeged
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #ifndef ARMAssembler_h
28 #define ARMAssembler_h
29 
30 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
31 
32 #include "AssemblerBuffer.h"
33 #include <wtf/Assertions.h>
34 #include <wtf/Vector.h>
35 #include <stdint.h>
36 
37 namespace JSC {
38 
39 namespace ARMRegisters {
40     typedef enum {
41         r0,
42         r1,
43         r2,
44         r3,
45         r4,
46         r5,
47         r6,
48         r7, wr = r7,   // thumb work register
49         r8,
50         r9, sb = r9,   // static base
51         r10, sl = r10, // stack limit
52         r11, fp = r11, // frame pointer
53         r12, ip = r12,
54         r13, sp = r13,
55         r14, lr = r14,
56         r15, pc = r15,
57     } RegisterID;
58 
59     typedef enum {
60         s0,
61         s1,
62         s2,
63         s3,
64         s4,
65         s5,
66         s6,
67         s7,
68         s8,
69         s9,
70         s10,
71         s11,
72         s12,
73         s13,
74         s14,
75         s15,
76         s16,
77         s17,
78         s18,
79         s19,
80         s20,
81         s21,
82         s22,
83         s23,
84         s24,
85         s25,
86         s26,
87         s27,
88         s28,
89         s29,
90         s30,
91         s31,
92     } FPSingleRegisterID;
93 
94     typedef enum {
95         d0,
96         d1,
97         d2,
98         d3,
99         d4,
100         d5,
101         d6,
102         d7,
103         d8,
104         d9,
105         d10,
106         d11,
107         d12,
108         d13,
109         d14,
110         d15,
111         d16,
112         d17,
113         d18,
114         d19,
115         d20,
116         d21,
117         d22,
118         d23,
119         d24,
120         d25,
121         d26,
122         d27,
123         d28,
124         d29,
125         d30,
126         d31,
127     } FPDoubleRegisterID;
128 
129     typedef enum {
130         q0,
131         q1,
132         q2,
133         q3,
134         q4,
135         q5,
136         q6,
137         q7,
138         q8,
139         q9,
140         q10,
141         q11,
142         q12,
143         q13,
144         q14,
145         q15,
146         q16,
147         q17,
148         q18,
149         q19,
150         q20,
151         q21,
152         q22,
153         q23,
154         q24,
155         q25,
156         q26,
157         q27,
158         q28,
159         q29,
160         q30,
161         q31,
162     } FPQuadRegisterID;
163 
asSingle(FPDoubleRegisterID reg)164     inline FPSingleRegisterID asSingle(FPDoubleRegisterID reg)
165     {
166         ASSERT(reg < d16);
167         return (FPSingleRegisterID)(reg << 1);
168     }
169 
asDouble(FPSingleRegisterID reg)170     inline FPDoubleRegisterID asDouble(FPSingleRegisterID reg)
171     {
172         ASSERT(!(reg & 1));
173         return (FPDoubleRegisterID)(reg >> 1);
174     }
175 }
176 
177 class ARMv7Assembler;
178 class ARMThumbImmediate {
179     friend class ARMv7Assembler;
180 
181     typedef uint8_t ThumbImmediateType;
182     static const ThumbImmediateType TypeInvalid = 0;
183     static const ThumbImmediateType TypeEncoded = 1;
184     static const ThumbImmediateType TypeUInt16 = 2;
185 
186     typedef union {
187         int16_t asInt;
188         struct {
189             unsigned imm8 : 8;
190             unsigned imm3 : 3;
191             unsigned i    : 1;
192             unsigned imm4 : 4;
193         };
194         // If this is an encoded immediate, then it may describe a shift, or a pattern.
195         struct {
196             unsigned shiftValue7 : 7;
197             unsigned shiftAmount : 5;
198         };
199         struct {
200             unsigned immediate   : 8;
201             unsigned pattern     : 4;
202         };
203     } ThumbImmediateValue;
204 
205     // byte0 contains least significant bit; not using an array to make client code endian agnostic.
206     typedef union {
207         int32_t asInt;
208         struct {
209             uint8_t byte0;
210             uint8_t byte1;
211             uint8_t byte2;
212             uint8_t byte3;
213         };
214     } PatternBytes;
215 
countLeadingZerosPartial(uint32_t & value,int32_t & zeros,const int N)216     ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
217     {
218         if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
219             value >>= N;             /* if any were set, lose the bottom N */
220         else                         /* if none of the top N bits are set, */
221             zeros += N;              /* then we have identified N leading zeros */
222     }
223 
countLeadingZeros(uint32_t value)224     static int32_t countLeadingZeros(uint32_t value)
225     {
226         if (!value)
227             return 32;
228 
229         int32_t zeros = 0;
230         countLeadingZerosPartial(value, zeros, 16);
231         countLeadingZerosPartial(value, zeros, 8);
232         countLeadingZerosPartial(value, zeros, 4);
233         countLeadingZerosPartial(value, zeros, 2);
234         countLeadingZerosPartial(value, zeros, 1);
235         return zeros;
236     }
237 
ARMThumbImmediate()238     ARMThumbImmediate()
239         : m_type(TypeInvalid)
240     {
241         m_value.asInt = 0;
242     }
243 
ARMThumbImmediate(ThumbImmediateType type,ThumbImmediateValue value)244     ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
245         : m_type(type)
246         , m_value(value)
247     {
248     }
249 
ARMThumbImmediate(ThumbImmediateType type,uint16_t value)250     ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
251         : m_type(TypeUInt16)
252     {
253         // Make sure this constructor is only reached with type TypeUInt16;
254         // this extra parameter makes the code a little clearer by making it
255         // explicit at call sites which type is being constructed
256         ASSERT_UNUSED(type, type == TypeUInt16);
257 
258         m_value.asInt = value;
259     }
260 
261 public:
makeEncodedImm(uint32_t value)262     static ARMThumbImmediate makeEncodedImm(uint32_t value)
263     {
264         ThumbImmediateValue encoding;
265         encoding.asInt = 0;
266 
267         // okay, these are easy.
268         if (value < 256) {
269             encoding.immediate = value;
270             encoding.pattern = 0;
271             return ARMThumbImmediate(TypeEncoded, encoding);
272         }
273 
274         int32_t leadingZeros = countLeadingZeros(value);
275         // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
276         ASSERT(leadingZeros < 24);
277 
278         // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
279         // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
280         // zero.  count(B) == 8, so the count of bits to be checked is 24 - count(Z).
281         int32_t rightShiftAmount = 24 - leadingZeros;
282         if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
283             // Shift the value down to the low byte position.  The assign to
284             // shiftValue7 drops the implicit top bit.
285             encoding.shiftValue7 = value >> rightShiftAmount;
286             // The endoded shift amount is the magnitude of a right rotate.
287             encoding.shiftAmount = 8 + leadingZeros;
288             return ARMThumbImmediate(TypeEncoded, encoding);
289         }
290 
291         PatternBytes bytes;
292         bytes.asInt = value;
293 
294         if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
295             encoding.immediate = bytes.byte0;
296             encoding.pattern = 3;
297             return ARMThumbImmediate(TypeEncoded, encoding);
298         }
299 
300         if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
301             encoding.immediate = bytes.byte0;
302             encoding.pattern = 1;
303             return ARMThumbImmediate(TypeEncoded, encoding);
304         }
305 
306         if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
307             encoding.immediate = bytes.byte1;
308             encoding.pattern = 2;
309             return ARMThumbImmediate(TypeEncoded, encoding);
310         }
311 
312         return ARMThumbImmediate();
313     }
314 
makeUInt12(int32_t value)315     static ARMThumbImmediate makeUInt12(int32_t value)
316     {
317         return (!(value & 0xfffff000))
318             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
319             : ARMThumbImmediate();
320     }
321 
makeUInt12OrEncodedImm(int32_t value)322     static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
323     {
324         // If this is not a 12-bit unsigned it, try making an encoded immediate.
325         return (!(value & 0xfffff000))
326             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
327             : makeEncodedImm(value);
328     }
329 
330     // The 'make' methods, above, return a !isValid() value if the argument
331     // cannot be represented as the requested type.  This methods  is called
332     // 'get' since the argument can always be represented.
makeUInt16(uint16_t value)333     static ARMThumbImmediate makeUInt16(uint16_t value)
334     {
335         return ARMThumbImmediate(TypeUInt16, value);
336     }
337 
isValid()338     bool isValid()
339     {
340         return m_type != TypeInvalid;
341     }
342 
343     // These methods rely on the format of encoded byte values.
isUInt3()344     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
isUInt4()345     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
isUInt5()346     bool isUInt5() { return !(m_value.asInt & 0xffe0); }
isUInt6()347     bool isUInt6() { return !(m_value.asInt & 0xffc0); }
isUInt7()348     bool isUInt7() { return !(m_value.asInt & 0xff80); }
isUInt8()349     bool isUInt8() { return !(m_value.asInt & 0xff00); }
isUInt9()350     bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
isUInt10()351     bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
isUInt12()352     bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
isUInt16()353     bool isUInt16() { return m_type == TypeUInt16; }
getUInt3()354     uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
getUInt4()355     uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
getUInt5()356     uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
getUInt6()357     uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
getUInt7()358     uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
getUInt8()359     uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
getUInt9()360     uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
getUInt10()361     uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
getUInt12()362     uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
getUInt16()363     uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
364 
isEncodedImm()365     bool isEncodedImm() { return m_type == TypeEncoded; }
366 
367 private:
368     ThumbImmediateType m_type;
369     ThumbImmediateValue m_value;
370 };
371 
372 typedef enum {
373     SRType_LSL,
374     SRType_LSR,
375     SRType_ASR,
376     SRType_ROR,
377 
378     SRType_RRX = SRType_ROR
379 } ARMShiftType;
380 
381 class ShiftTypeAndAmount {
382     friend class ARMv7Assembler;
383 
384 public:
ShiftTypeAndAmount()385     ShiftTypeAndAmount()
386     {
387         m_u.type = (ARMShiftType)0;
388         m_u.amount = 0;
389     }
390 
ShiftTypeAndAmount(ARMShiftType type,unsigned amount)391     ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
392     {
393         m_u.type = type;
394         m_u.amount = amount & 31;
395     }
396 
lo4()397     unsigned lo4() { return m_u.lo4; }
hi4()398     unsigned hi4() { return m_u.hi4; }
399 
400 private:
401     union {
402         struct {
403             unsigned lo4 : 4;
404             unsigned hi4 : 4;
405         };
406         struct {
407             unsigned type   : 2;
408             unsigned amount : 6;
409         };
410     } m_u;
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::FPSingleRegisterID FPSingleRegisterID;
422     typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
423     typedef ARMRegisters::FPQuadRegisterID FPQuadRegisterID;
424 
425     // (HS, LO, HI, LS) -> (AE, B, A, BE)
426     // (VS, VC) -> (O, NO)
427     typedef enum {
428         ConditionEQ,
429         ConditionNE,
430         ConditionHS, ConditionCS = ConditionHS,
431         ConditionLO, ConditionCC = ConditionLO,
432         ConditionMI,
433         ConditionPL,
434         ConditionVS,
435         ConditionVC,
436         ConditionHI,
437         ConditionLS,
438         ConditionGE,
439         ConditionLT,
440         ConditionGT,
441         ConditionLE,
442         ConditionAL,
443         ConditionInvalid
444     } Condition;
445 
446     enum JumpType { JumpFixed, JumpNoCondition, JumpCondition, JumpNoConditionFixedSize, JumpConditionFixedSize, JumpTypeCount };
447     enum JumpLinkType { LinkInvalid, LinkJumpT1, LinkJumpT2, LinkJumpT3,
448         LinkJumpT4, LinkConditionalJumpT4, LinkBX, LinkConditionalBX, JumpLinkTypeCount };
449     static const int JumpSizes[JumpLinkTypeCount];
450     static const int JumpPaddingSizes[JumpTypeCount];
451     class LinkRecord {
452     public:
LinkRecord(intptr_t from,intptr_t to,JumpType type,Condition condition)453         LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
454             : m_from(from)
455             , m_to(to)
456             , m_type(type)
457             , m_linkType(LinkInvalid)
458             , m_condition(condition)
459         {
460         }
from()461         intptr_t from() const { return m_from; }
setFrom(intptr_t from)462         void setFrom(intptr_t from) { m_from = from; }
to()463         intptr_t to() const { return m_to; }
type()464         JumpType type() const { return m_type; }
linkType()465         JumpLinkType linkType() const { return m_linkType; }
setLinkType(JumpLinkType linkType)466         void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; }
condition()467         Condition condition() const { return m_condition; }
468     private:
469         intptr_t m_from : 31;
470         intptr_t m_to : 31;
471         JumpType m_type : 3;
472         JumpLinkType m_linkType : 4;
473         Condition m_condition : 16;
474     };
475 
476     class JmpSrc {
477         friend class ARMv7Assembler;
478         friend class ARMInstructionFormatter;
479         friend class LinkBuffer;
480     public:
JmpSrc()481         JmpSrc()
482             : m_offset(-1)
483         {
484         }
485 
486     private:
JmpSrc(int offset,JumpType type)487         JmpSrc(int offset, JumpType type)
488             : m_offset(offset)
489             , m_condition(ConditionInvalid)
490             , m_type(type)
491         {
492             ASSERT(m_type == JumpFixed || m_type == JumpNoCondition || m_type == JumpNoConditionFixedSize);
493         }
494 
JmpSrc(int offset,JumpType type,Condition condition)495         JmpSrc(int offset, JumpType type, Condition condition)
496             : m_offset(offset)
497             , m_condition(condition)
498             , m_type(type)
499         {
500             ASSERT(m_type == JumpFixed || m_type == JumpCondition || m_type == JumpConditionFixedSize);
501         }
502 
503         int m_offset;
504         Condition m_condition : 16;
505         JumpType m_type : 16;
506 
507     };
508 
509     class JmpDst {
510         friend class ARMv7Assembler;
511         friend class ARMInstructionFormatter;
512         friend class LinkBuffer;
513     public:
JmpDst()514         JmpDst()
515             : m_offset(-1)
516             , m_used(false)
517         {
518         }
519 
isUsed()520         bool isUsed() const { return m_used; }
isSet()521         bool isSet() const { return (m_offset != -1); }
used()522         void used() { m_used = true; }
523     private:
JmpDst(int offset)524         JmpDst(int offset)
525             : m_offset(offset)
526             , m_used(false)
527         {
528             ASSERT(m_offset == offset);
529         }
530 
531         signed int m_offset : 31;
532         int m_used : 1;
533     };
534 
535 private:
536 
537     // ARMv7, Appx-A.6.3
BadReg(RegisterID reg)538     bool BadReg(RegisterID reg)
539     {
540         return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
541     }
542 
singleRegisterMask(FPSingleRegisterID rdNum,int highBitsShift,int lowBitShift)543     uint32_t singleRegisterMask(FPSingleRegisterID rdNum, int highBitsShift, int lowBitShift)
544     {
545         uint32_t rdMask = (rdNum >> 1) << highBitsShift;
546         if (rdNum & 1)
547             rdMask |= 1 << lowBitShift;
548         return rdMask;
549     }
550 
doubleRegisterMask(FPDoubleRegisterID rdNum,int highBitShift,int lowBitsShift)551     uint32_t doubleRegisterMask(FPDoubleRegisterID rdNum, int highBitShift, int lowBitsShift)
552     {
553         uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
554         if (rdNum & 16)
555             rdMask |= 1 << highBitShift;
556         return rdMask;
557     }
558 
559     typedef enum {
560         OP_ADD_reg_T1       = 0x1800,
561         OP_SUB_reg_T1       = 0x1A00,
562         OP_ADD_imm_T1       = 0x1C00,
563         OP_SUB_imm_T1       = 0x1E00,
564         OP_MOV_imm_T1       = 0x2000,
565         OP_CMP_imm_T1       = 0x2800,
566         OP_ADD_imm_T2       = 0x3000,
567         OP_SUB_imm_T2       = 0x3800,
568         OP_AND_reg_T1       = 0x4000,
569         OP_EOR_reg_T1       = 0x4040,
570         OP_TST_reg_T1       = 0x4200,
571         OP_RSB_imm_T1       = 0x4240,
572         OP_CMP_reg_T1       = 0x4280,
573         OP_ORR_reg_T1       = 0x4300,
574         OP_MVN_reg_T1       = 0x43C0,
575         OP_ADD_reg_T2       = 0x4400,
576         OP_MOV_reg_T1       = 0x4600,
577         OP_BLX              = 0x4700,
578         OP_BX               = 0x4700,
579         OP_STR_reg_T1       = 0x5000,
580         OP_LDR_reg_T1       = 0x5800,
581         OP_LDRH_reg_T1      = 0x5A00,
582         OP_LDRB_reg_T1      = 0x5C00,
583         OP_STR_imm_T1       = 0x6000,
584         OP_LDR_imm_T1       = 0x6800,
585         OP_LDRB_imm_T1      = 0x7800,
586         OP_LDRH_imm_T1      = 0x8800,
587         OP_STR_imm_T2       = 0x9000,
588         OP_LDR_imm_T2       = 0x9800,
589         OP_ADD_SP_imm_T1    = 0xA800,
590         OP_ADD_SP_imm_T2    = 0xB000,
591         OP_SUB_SP_imm_T1    = 0xB080,
592         OP_BKPT             = 0xBE00,
593         OP_IT               = 0xBF00,
594         OP_NOP_T1           = 0xBF00,
595     } OpcodeID;
596 
597     typedef enum {
598         OP_B_T1         = 0xD000,
599         OP_B_T2         = 0xE000,
600         OP_AND_reg_T2   = 0xEA00,
601         OP_TST_reg_T2   = 0xEA10,
602         OP_ORR_reg_T2   = 0xEA40,
603         OP_ORR_S_reg_T2 = 0xEA50,
604         OP_ASR_imm_T1   = 0xEA4F,
605         OP_LSL_imm_T1   = 0xEA4F,
606         OP_LSR_imm_T1   = 0xEA4F,
607         OP_ROR_imm_T1   = 0xEA4F,
608         OP_MVN_reg_T2   = 0xEA6F,
609         OP_EOR_reg_T2   = 0xEA80,
610         OP_ADD_reg_T3   = 0xEB00,
611         OP_ADD_S_reg_T3 = 0xEB10,
612         OP_SUB_reg_T2   = 0xEBA0,
613         OP_SUB_S_reg_T2 = 0xEBB0,
614         OP_CMP_reg_T2   = 0xEBB0,
615         OP_VSTR         = 0xED00,
616         OP_VLDR         = 0xED10,
617         OP_VMOV_StoC    = 0xEE00,
618         OP_VMOV_CtoS    = 0xEE10,
619         OP_VMUL_T2      = 0xEE20,
620         OP_VADD_T2      = 0xEE30,
621         OP_VSUB_T2      = 0xEE30,
622         OP_VDIV         = 0xEE80,
623         OP_VCMP         = 0xEEB0,
624         OP_VCVT_FPIVFP  = 0xEEB0,
625         OP_VMOV_IMM_T2  = 0xEEB0,
626         OP_VMRS         = 0xEEB0,
627         OP_B_T3a        = 0xF000,
628         OP_B_T4a        = 0xF000,
629         OP_AND_imm_T1   = 0xF000,
630         OP_TST_imm      = 0xF010,
631         OP_ORR_imm_T1   = 0xF040,
632         OP_MOV_imm_T2   = 0xF040,
633         OP_MVN_imm      = 0xF060,
634         OP_EOR_imm_T1   = 0xF080,
635         OP_ADD_imm_T3   = 0xF100,
636         OP_ADD_S_imm_T3 = 0xF110,
637         OP_CMN_imm      = 0xF110,
638         OP_SUB_imm_T3   = 0xF1A0,
639         OP_SUB_S_imm_T3 = 0xF1B0,
640         OP_CMP_imm_T2   = 0xF1B0,
641         OP_RSB_imm_T2   = 0xF1C0,
642         OP_ADD_imm_T4   = 0xF200,
643         OP_MOV_imm_T3   = 0xF240,
644         OP_SUB_imm_T4   = 0xF2A0,
645         OP_MOVT         = 0xF2C0,
646         OP_NOP_T2a      = 0xF3AF,
647         OP_LDRB_imm_T3  = 0xF810,
648         OP_LDRB_reg_T2  = 0xF810,
649         OP_LDRH_reg_T2  = 0xF830,
650         OP_LDRH_imm_T3  = 0xF830,
651         OP_STR_imm_T4   = 0xF840,
652         OP_STR_reg_T2   = 0xF840,
653         OP_LDR_imm_T4   = 0xF850,
654         OP_LDR_reg_T2   = 0xF850,
655         OP_LDRB_imm_T2  = 0xF890,
656         OP_LDRH_imm_T2  = 0xF8B0,
657         OP_STR_imm_T3   = 0xF8C0,
658         OP_LDR_imm_T3   = 0xF8D0,
659         OP_LSL_reg_T2   = 0xFA00,
660         OP_LSR_reg_T2   = 0xFA20,
661         OP_ASR_reg_T2   = 0xFA40,
662         OP_ROR_reg_T2   = 0xFA60,
663         OP_CLZ          = 0xFAB0,
664         OP_SMULL_T1     = 0xFB80,
665     } OpcodeID1;
666 
667     typedef enum {
668         OP_VADD_T2b     = 0x0A00,
669         OP_VDIVb        = 0x0A00,
670         OP_VLDRb        = 0x0A00,
671         OP_VMOV_IMM_T2b = 0x0A00,
672         OP_VMUL_T2b     = 0x0A00,
673         OP_VSTRb        = 0x0A00,
674         OP_VMOV_CtoSb   = 0x0A10,
675         OP_VMOV_StoCb   = 0x0A10,
676         OP_VMRSb        = 0x0A10,
677         OP_VCMPb        = 0x0A40,
678         OP_VCVT_FPIVFPb = 0x0A40,
679         OP_VSUB_T2b     = 0x0A40,
680         OP_NOP_T2b      = 0x8000,
681         OP_B_T3b        = 0x8000,
682         OP_B_T4b        = 0x9000,
683     } OpcodeID2;
684 
685     struct FourFours {
FourFoursFourFours686         FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
687         {
688             m_u.f0 = f0;
689             m_u.f1 = f1;
690             m_u.f2 = f2;
691             m_u.f3 = f3;
692         }
693 
694         union {
695             unsigned value;
696             struct {
697                 unsigned f0 : 4;
698                 unsigned f1 : 4;
699                 unsigned f2 : 4;
700                 unsigned f3 : 4;
701             };
702         } m_u;
703     };
704 
705     class ARMInstructionFormatter;
706 
707     // false means else!
ifThenElseConditionBit(Condition condition,bool isIf)708     bool ifThenElseConditionBit(Condition condition, bool isIf)
709     {
710         return isIf ? (condition & 1) : !(condition & 1);
711     }
ifThenElse(Condition condition,bool inst2if,bool inst3if,bool inst4if)712     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
713     {
714         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
715             | (ifThenElseConditionBit(condition, inst3if) << 2)
716             | (ifThenElseConditionBit(condition, inst4if) << 1)
717             | 1;
718         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
719         return (condition << 4) | mask;
720     }
ifThenElse(Condition condition,bool inst2if,bool inst3if)721     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
722     {
723         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
724             | (ifThenElseConditionBit(condition, inst3if) << 2)
725             | 2;
726         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
727         return (condition << 4) | mask;
728     }
ifThenElse(Condition condition,bool inst2if)729     uint8_t ifThenElse(Condition condition, bool inst2if)
730     {
731         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
732             | 4;
733         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
734         return (condition << 4) | mask;
735     }
736 
ifThenElse(Condition condition)737     uint8_t ifThenElse(Condition condition)
738     {
739         int mask = 8;
740         return (condition << 4) | mask;
741     }
742 
743 public:
744 
add(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)745     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
746     {
747         // Rd can only be SP if Rn is also SP.
748         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
749         ASSERT(rd != ARMRegisters::pc);
750         ASSERT(rn != ARMRegisters::pc);
751         ASSERT(imm.isValid());
752 
753         if (rn == ARMRegisters::sp) {
754             if (!(rd & 8) && imm.isUInt10()) {
755                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
756                 return;
757             } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
758                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
759                 return;
760             }
761         } else if (!((rd | rn) & 8)) {
762             if (imm.isUInt3()) {
763                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
764                 return;
765             } else if ((rd == rn) && imm.isUInt8()) {
766                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
767                 return;
768             }
769         }
770 
771         if (imm.isEncodedImm())
772             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
773         else {
774             ASSERT(imm.isUInt12());
775             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
776         }
777     }
778 
add(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)779     void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
780     {
781         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
782         ASSERT(rd != ARMRegisters::pc);
783         ASSERT(rn != ARMRegisters::pc);
784         ASSERT(!BadReg(rm));
785         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
786     }
787 
788     // NOTE: In an IT block, add doesn't modify the flags register.
add(RegisterID rd,RegisterID rn,RegisterID rm)789     void add(RegisterID rd, RegisterID rn, RegisterID rm)
790     {
791         if (rd == rn)
792             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
793         else if (rd == rm)
794             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
795         else if (!((rd | rn | rm) & 8))
796             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
797         else
798             add(rd, rn, rm, ShiftTypeAndAmount());
799     }
800 
801     // Not allowed in an IT (if then) block.
add_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)802     void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
803     {
804         // Rd can only be SP if Rn is also SP.
805         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
806         ASSERT(rd != ARMRegisters::pc);
807         ASSERT(rn != ARMRegisters::pc);
808         ASSERT(imm.isEncodedImm());
809 
810         if (!((rd | rn) & 8)) {
811             if (imm.isUInt3()) {
812                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
813                 return;
814             } else if ((rd == rn) && imm.isUInt8()) {
815                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
816                 return;
817             }
818         }
819 
820         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
821     }
822 
823     // Not allowed in an IT (if then) block?
add_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)824     void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
825     {
826         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
827         ASSERT(rd != ARMRegisters::pc);
828         ASSERT(rn != ARMRegisters::pc);
829         ASSERT(!BadReg(rm));
830         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
831     }
832 
833     // Not allowed in an IT (if then) block.
add_S(RegisterID rd,RegisterID rn,RegisterID rm)834     void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
835     {
836         if (!((rd | rn | rm) & 8))
837             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
838         else
839             add_S(rd, rn, rm, ShiftTypeAndAmount());
840     }
841 
ARM_and(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)842     void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
843     {
844         ASSERT(!BadReg(rd));
845         ASSERT(!BadReg(rn));
846         ASSERT(imm.isEncodedImm());
847         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
848     }
849 
ARM_and(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)850     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
851     {
852         ASSERT(!BadReg(rd));
853         ASSERT(!BadReg(rn));
854         ASSERT(!BadReg(rm));
855         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
856     }
857 
ARM_and(RegisterID rd,RegisterID rn,RegisterID rm)858     void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
859     {
860         if ((rd == rn) && !((rd | rm) & 8))
861             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
862         else if ((rd == rm) && !((rd | rn) & 8))
863             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
864         else
865             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
866     }
867 
asr(RegisterID rd,RegisterID rm,int32_t shiftAmount)868     void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
869     {
870         ASSERT(!BadReg(rd));
871         ASSERT(!BadReg(rm));
872         ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
873         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
874     }
875 
asr(RegisterID rd,RegisterID rn,RegisterID rm)876     void asr(RegisterID rd, RegisterID rn, RegisterID rm)
877     {
878         ASSERT(!BadReg(rd));
879         ASSERT(!BadReg(rn));
880         ASSERT(!BadReg(rm));
881         m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
882     }
883 
884     // Only allowed in IT (if then) block if last instruction.
b(JumpType type)885     JmpSrc b(JumpType type)
886     {
887         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
888         return JmpSrc(m_formatter.size(), type);
889     }
890 
891     // Only allowed in IT (if then) block if last instruction.
blx(RegisterID rm,JumpType type)892     JmpSrc blx(RegisterID rm, JumpType type)
893     {
894         ASSERT(rm != ARMRegisters::pc);
895         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
896         return JmpSrc(m_formatter.size(), type);
897     }
898 
899     // Only allowed in IT (if then) block if last instruction.
bx(RegisterID rm,JumpType type,Condition condition)900     JmpSrc bx(RegisterID rm, JumpType type, Condition condition)
901     {
902         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
903         return JmpSrc(m_formatter.size(), type, condition);
904     }
905 
bx(RegisterID rm,JumpType type)906     JmpSrc bx(RegisterID rm, JumpType type)
907     {
908         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
909         return JmpSrc(m_formatter.size(), type);
910     }
911 
912     void bkpt(uint8_t imm=0)
913     {
914         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
915     }
916 
clz(RegisterID rd,RegisterID rm)917     void clz(RegisterID rd, RegisterID rm)
918     {
919         ASSERT(!BadReg(rd));
920         ASSERT(!BadReg(rm));
921         m_formatter.twoWordOp12Reg4FourFours(OP_CLZ, rm, FourFours(0xf, rd, 8, rm));
922     }
923 
cmn(RegisterID rn,ARMThumbImmediate imm)924     void cmn(RegisterID rn, ARMThumbImmediate imm)
925     {
926         ASSERT(rn != ARMRegisters::pc);
927         ASSERT(imm.isEncodedImm());
928 
929         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
930     }
931 
cmp(RegisterID rn,ARMThumbImmediate imm)932     void cmp(RegisterID rn, ARMThumbImmediate imm)
933     {
934         ASSERT(rn != ARMRegisters::pc);
935         ASSERT(imm.isEncodedImm());
936 
937         if (!(rn & 8) && imm.isUInt8())
938             m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
939         else
940             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
941     }
942 
cmp(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)943     void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
944     {
945         ASSERT(rn != ARMRegisters::pc);
946         ASSERT(!BadReg(rm));
947         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
948     }
949 
cmp(RegisterID rn,RegisterID rm)950     void cmp(RegisterID rn, RegisterID rm)
951     {
952         if ((rn | rm) & 8)
953             cmp(rn, rm, ShiftTypeAndAmount());
954         else
955             m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
956     }
957 
958     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)959     void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
960     {
961         ASSERT(!BadReg(rd));
962         ASSERT(!BadReg(rn));
963         ASSERT(imm.isEncodedImm());
964         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
965     }
966 
967     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)968     void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
969     {
970         ASSERT(!BadReg(rd));
971         ASSERT(!BadReg(rn));
972         ASSERT(!BadReg(rm));
973         m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
974     }
975 
976     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,RegisterID rm)977     void eor(RegisterID rd, RegisterID rn, RegisterID rm)
978     {
979         if ((rd == rn) && !((rd | rm) & 8))
980             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
981         else if ((rd == rm) && !((rd | rn) & 8))
982             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
983         else
984             eor(rd, rn, rm, ShiftTypeAndAmount());
985     }
986 
it(Condition cond)987     void it(Condition cond)
988     {
989         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
990     }
991 
it(Condition cond,bool inst2if)992     void it(Condition cond, bool inst2if)
993     {
994         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
995     }
996 
it(Condition cond,bool inst2if,bool inst3if)997     void it(Condition cond, bool inst2if, bool inst3if)
998     {
999         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
1000     }
1001 
it(Condition cond,bool inst2if,bool inst3if,bool inst4if)1002     void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
1003     {
1004         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
1005     }
1006 
1007     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
ldr(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1008     void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1009     {
1010         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1011         ASSERT(imm.isUInt12());
1012 
1013         if (!((rt | rn) & 8) && imm.isUInt7())
1014             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1015         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1016             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
1017         else
1018             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
1019     }
1020 
1021     // If index is set, this is a regular offset or a pre-indexed load;
1022     // if index is not set then is is a post-index load.
1023     //
1024     // If wback is set rn is updated - this is a pre or post index load,
1025     // if wback is not set this is a regular offset memory access.
1026     //
1027     // (-255 <= offset <= 255)
1028     // _reg = REG[rn]
1029     // _tmp = _reg + offset
1030     // MEM[index ? _tmp : _reg] = REG[rt]
1031     // if (wback) REG[rn] = _tmp
ldr(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1032     void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1033     {
1034         ASSERT(rt != ARMRegisters::pc);
1035         ASSERT(rn != ARMRegisters::pc);
1036         ASSERT(index || wback);
1037         ASSERT(!wback | (rt != rn));
1038 
1039         bool add = true;
1040         if (offset < 0) {
1041             add = false;
1042             offset = -offset;
1043         }
1044         ASSERT((offset & ~0xff) == 0);
1045 
1046         offset |= (wback << 8);
1047         offset |= (add   << 9);
1048         offset |= (index << 10);
1049         offset |= (1 << 11);
1050 
1051         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
1052     }
1053 
1054     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1055     void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1056     {
1057         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1058         ASSERT(!BadReg(rm));
1059         ASSERT(shift <= 3);
1060 
1061         if (!shift && !((rt | rn | rm) & 8))
1062             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
1063         else
1064             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1065     }
1066 
1067     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
ldrh(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1068     void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1069     {
1070         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1071         ASSERT(imm.isUInt12());
1072 
1073         if (!((rt | rn) & 8) && imm.isUInt6())
1074             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
1075         else
1076             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
1077     }
1078 
1079     // If index is set, this is a regular offset or a pre-indexed load;
1080     // if index is not set then is is a post-index load.
1081     //
1082     // If wback is set rn is updated - this is a pre or post index load,
1083     // if wback is not set this is a regular offset memory access.
1084     //
1085     // (-255 <= offset <= 255)
1086     // _reg = REG[rn]
1087     // _tmp = _reg + offset
1088     // MEM[index ? _tmp : _reg] = REG[rt]
1089     // if (wback) REG[rn] = _tmp
ldrh(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1090     void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1091     {
1092         ASSERT(rt != ARMRegisters::pc);
1093         ASSERT(rn != ARMRegisters::pc);
1094         ASSERT(index || wback);
1095         ASSERT(!wback | (rt != rn));
1096 
1097         bool add = true;
1098         if (offset < 0) {
1099             add = false;
1100             offset = -offset;
1101         }
1102         ASSERT((offset & ~0xff) == 0);
1103 
1104         offset |= (wback << 8);
1105         offset |= (add   << 9);
1106         offset |= (index << 10);
1107         offset |= (1 << 11);
1108 
1109         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
1110     }
1111 
1112     void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1113     {
1114         ASSERT(!BadReg(rt));   // Memory hint
1115         ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
1116         ASSERT(!BadReg(rm));
1117         ASSERT(shift <= 3);
1118 
1119         if (!shift && !((rt | rn | rm) & 8))
1120             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
1121         else
1122             m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1123     }
1124 
ldrb(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1125     void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1126     {
1127         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1128         ASSERT(imm.isUInt12());
1129 
1130         if (!((rt | rn) & 8) && imm.isUInt5())
1131             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
1132         else
1133             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
1134     }
1135 
ldrb(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1136     void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1137     {
1138         ASSERT(rt != ARMRegisters::pc);
1139         ASSERT(rn != ARMRegisters::pc);
1140         ASSERT(index || wback);
1141         ASSERT(!wback | (rt != rn));
1142 
1143         bool add = true;
1144         if (offset < 0) {
1145             add = false;
1146             offset = -offset;
1147         }
1148 
1149         ASSERT(!(offset & ~0xff));
1150 
1151         offset |= (wback << 8);
1152         offset |= (add   << 9);
1153         offset |= (index << 10);
1154         offset |= (1 << 11);
1155 
1156         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
1157     }
1158 
1159     void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1160     {
1161         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1162         ASSERT(!BadReg(rm));
1163         ASSERT(shift <= 3);
1164 
1165         if (!shift && !((rt | rn | rm) & 8))
1166             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
1167         else
1168             m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1169     }
1170 
lsl(RegisterID rd,RegisterID rm,int32_t shiftAmount)1171     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1172     {
1173         ASSERT(!BadReg(rd));
1174         ASSERT(!BadReg(rm));
1175         ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
1176         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1177     }
1178 
lsl(RegisterID rd,RegisterID rn,RegisterID rm)1179     void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
1180     {
1181         ASSERT(!BadReg(rd));
1182         ASSERT(!BadReg(rn));
1183         ASSERT(!BadReg(rm));
1184         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1185     }
1186 
lsr(RegisterID rd,RegisterID rm,int32_t shiftAmount)1187     void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1188     {
1189         ASSERT(!BadReg(rd));
1190         ASSERT(!BadReg(rm));
1191         ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
1192         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1193     }
1194 
lsr(RegisterID rd,RegisterID rn,RegisterID rm)1195     void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
1196     {
1197         ASSERT(!BadReg(rd));
1198         ASSERT(!BadReg(rn));
1199         ASSERT(!BadReg(rm));
1200         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1201     }
1202 
movT3(RegisterID rd,ARMThumbImmediate imm)1203     void movT3(RegisterID rd, ARMThumbImmediate imm)
1204     {
1205         ASSERT(imm.isValid());
1206         ASSERT(!imm.isEncodedImm());
1207         ASSERT(!BadReg(rd));
1208 
1209         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
1210     }
1211 
mov(RegisterID rd,ARMThumbImmediate imm)1212      void mov(RegisterID rd, ARMThumbImmediate imm)
1213     {
1214         ASSERT(imm.isValid());
1215         ASSERT(!BadReg(rd));
1216 
1217         if ((rd < 8) && imm.isUInt8())
1218             m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
1219         else if (imm.isEncodedImm())
1220             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
1221         else
1222             movT3(rd, imm);
1223     }
1224 
mov(RegisterID rd,RegisterID rm)1225    void mov(RegisterID rd, RegisterID rm)
1226     {
1227         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
1228     }
1229 
movt(RegisterID rd,ARMThumbImmediate imm)1230     void movt(RegisterID rd, ARMThumbImmediate imm)
1231     {
1232         ASSERT(imm.isUInt16());
1233         ASSERT(!BadReg(rd));
1234         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
1235     }
1236 
mvn(RegisterID rd,ARMThumbImmediate imm)1237     void mvn(RegisterID rd, ARMThumbImmediate imm)
1238     {
1239         ASSERT(imm.isEncodedImm());
1240         ASSERT(!BadReg(rd));
1241 
1242         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
1243     }
1244 
mvn(RegisterID rd,RegisterID rm,ShiftTypeAndAmount shift)1245     void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
1246     {
1247         ASSERT(!BadReg(rd));
1248         ASSERT(!BadReg(rm));
1249         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1250     }
1251 
mvn(RegisterID rd,RegisterID rm)1252     void mvn(RegisterID rd, RegisterID rm)
1253     {
1254         if (!((rd | rm) & 8))
1255             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
1256         else
1257             mvn(rd, rm, ShiftTypeAndAmount());
1258     }
1259 
neg(RegisterID rd,RegisterID rm)1260     void neg(RegisterID rd, RegisterID rm)
1261     {
1262         ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
1263         sub(rd, zero, rm);
1264     }
1265 
orr(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1266     void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1267     {
1268         ASSERT(!BadReg(rd));
1269         ASSERT(!BadReg(rn));
1270         ASSERT(imm.isEncodedImm());
1271         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
1272     }
1273 
orr(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1274     void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1275     {
1276         ASSERT(!BadReg(rd));
1277         ASSERT(!BadReg(rn));
1278         ASSERT(!BadReg(rm));
1279         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1280     }
1281 
orr(RegisterID rd,RegisterID rn,RegisterID rm)1282     void orr(RegisterID rd, RegisterID rn, RegisterID rm)
1283     {
1284         if ((rd == rn) && !((rd | rm) & 8))
1285             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1286         else if ((rd == rm) && !((rd | rn) & 8))
1287             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1288         else
1289             orr(rd, rn, rm, ShiftTypeAndAmount());
1290     }
1291 
orr_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1292     void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1293     {
1294         ASSERT(!BadReg(rd));
1295         ASSERT(!BadReg(rn));
1296         ASSERT(!BadReg(rm));
1297         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1298     }
1299 
orr_S(RegisterID rd,RegisterID rn,RegisterID rm)1300     void orr_S(RegisterID rd, RegisterID rn, RegisterID rm)
1301     {
1302         if ((rd == rn) && !((rd | rm) & 8))
1303             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1304         else if ((rd == rm) && !((rd | rn) & 8))
1305             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1306         else
1307             orr_S(rd, rn, rm, ShiftTypeAndAmount());
1308     }
1309 
ror(RegisterID rd,RegisterID rm,int32_t shiftAmount)1310     void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1311     {
1312         ASSERT(!BadReg(rd));
1313         ASSERT(!BadReg(rm));
1314         ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
1315         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1316     }
1317 
ror(RegisterID rd,RegisterID rn,RegisterID rm)1318     void ror(RegisterID rd, RegisterID rn, RegisterID rm)
1319     {
1320         ASSERT(!BadReg(rd));
1321         ASSERT(!BadReg(rn));
1322         ASSERT(!BadReg(rm));
1323         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1324     }
1325 
smull(RegisterID rdLo,RegisterID rdHi,RegisterID rn,RegisterID rm)1326     void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
1327     {
1328         ASSERT(!BadReg(rdLo));
1329         ASSERT(!BadReg(rdHi));
1330         ASSERT(!BadReg(rn));
1331         ASSERT(!BadReg(rm));
1332         ASSERT(rdLo != rdHi);
1333         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
1334     }
1335 
1336     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
str(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1337     void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1338     {
1339         ASSERT(rt != ARMRegisters::pc);
1340         ASSERT(rn != ARMRegisters::pc);
1341         ASSERT(imm.isUInt12());
1342 
1343         if (!((rt | rn) & 8) && imm.isUInt7())
1344             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1345         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1346             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
1347         else
1348             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
1349     }
1350 
1351     // If index is set, this is a regular offset or a pre-indexed store;
1352     // if index is not set then is is a post-index store.
1353     //
1354     // If wback is set rn is updated - this is a pre or post index store,
1355     // if wback is not set this is a regular offset memory access.
1356     //
1357     // (-255 <= offset <= 255)
1358     // _reg = REG[rn]
1359     // _tmp = _reg + offset
1360     // MEM[index ? _tmp : _reg] = REG[rt]
1361     // if (wback) REG[rn] = _tmp
str(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1362     void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1363     {
1364         ASSERT(rt != ARMRegisters::pc);
1365         ASSERT(rn != ARMRegisters::pc);
1366         ASSERT(index || wback);
1367         ASSERT(!wback | (rt != rn));
1368 
1369         bool add = true;
1370         if (offset < 0) {
1371             add = false;
1372             offset = -offset;
1373         }
1374         ASSERT((offset & ~0xff) == 0);
1375 
1376         offset |= (wback << 8);
1377         offset |= (add   << 9);
1378         offset |= (index << 10);
1379         offset |= (1 << 11);
1380 
1381         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
1382     }
1383 
1384     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1385     void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1386     {
1387         ASSERT(rn != ARMRegisters::pc);
1388         ASSERT(!BadReg(rm));
1389         ASSERT(shift <= 3);
1390 
1391         if (!shift && !((rt | rn | rm) & 8))
1392             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
1393         else
1394             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1395     }
1396 
sub(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1397     void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1398     {
1399         // Rd can only be SP if Rn is also SP.
1400         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1401         ASSERT(rd != ARMRegisters::pc);
1402         ASSERT(rn != ARMRegisters::pc);
1403         ASSERT(imm.isValid());
1404 
1405         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1406             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1407             return;
1408         } else if (!((rd | rn) & 8)) {
1409             if (imm.isUInt3()) {
1410                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1411                 return;
1412             } else if ((rd == rn) && imm.isUInt8()) {
1413                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1414                 return;
1415             }
1416         }
1417 
1418         if (imm.isEncodedImm())
1419             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
1420         else {
1421             ASSERT(imm.isUInt12());
1422             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
1423         }
1424     }
1425 
sub(RegisterID rd,ARMThumbImmediate imm,RegisterID rn)1426     void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
1427     {
1428         ASSERT(rd != ARMRegisters::pc);
1429         ASSERT(rn != ARMRegisters::pc);
1430         ASSERT(imm.isValid());
1431         ASSERT(imm.isUInt12());
1432 
1433         if (!((rd | rn) & 8) && !imm.getUInt12())
1434             m_formatter.oneWordOp10Reg3Reg3(OP_RSB_imm_T1, rn, rd);
1435         else
1436             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
1437     }
1438 
sub(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1439     void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1440     {
1441         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1442         ASSERT(rd != ARMRegisters::pc);
1443         ASSERT(rn != ARMRegisters::pc);
1444         ASSERT(!BadReg(rm));
1445         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1446     }
1447 
1448     // NOTE: In an IT block, add doesn't modify the flags register.
sub(RegisterID rd,RegisterID rn,RegisterID rm)1449     void sub(RegisterID rd, RegisterID rn, RegisterID rm)
1450     {
1451         if (!((rd | rn | rm) & 8))
1452             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1453         else
1454             sub(rd, rn, rm, ShiftTypeAndAmount());
1455     }
1456 
1457     // Not allowed in an IT (if then) block.
sub_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1458     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1459     {
1460         // Rd can only be SP if Rn is also SP.
1461         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1462         ASSERT(rd != ARMRegisters::pc);
1463         ASSERT(rn != ARMRegisters::pc);
1464         ASSERT(imm.isValid());
1465 
1466         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1467             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1468             return;
1469         } else if (!((rd | rn) & 8)) {
1470             if (imm.isUInt3()) {
1471                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1472                 return;
1473             } else if ((rd == rn) && imm.isUInt8()) {
1474                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1475                 return;
1476             }
1477         }
1478 
1479         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
1480     }
1481 
1482     // Not allowed in an IT (if then) block?
sub_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1483     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1484     {
1485         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1486         ASSERT(rd != ARMRegisters::pc);
1487         ASSERT(rn != ARMRegisters::pc);
1488         ASSERT(!BadReg(rm));
1489         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1490     }
1491 
1492     // Not allowed in an IT (if then) block.
sub_S(RegisterID rd,RegisterID rn,RegisterID rm)1493     void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
1494     {
1495         if (!((rd | rn | rm) & 8))
1496             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1497         else
1498             sub_S(rd, rn, rm, ShiftTypeAndAmount());
1499     }
1500 
tst(RegisterID rn,ARMThumbImmediate imm)1501     void tst(RegisterID rn, ARMThumbImmediate imm)
1502     {
1503         ASSERT(!BadReg(rn));
1504         ASSERT(imm.isEncodedImm());
1505 
1506         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
1507     }
1508 
tst(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1509     void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1510     {
1511         ASSERT(!BadReg(rn));
1512         ASSERT(!BadReg(rm));
1513         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1514     }
1515 
tst(RegisterID rn,RegisterID rm)1516     void tst(RegisterID rn, RegisterID rm)
1517     {
1518         if ((rn | rm) & 8)
1519             tst(rn, rm, ShiftTypeAndAmount());
1520         else
1521             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
1522     }
1523 
vadd_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1524     void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1525     {
1526         m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
1527     }
1528 
vcmp_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rm)1529     void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1530     {
1531         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
1532     }
1533 
vcmpz_F64(FPDoubleRegisterID rd)1534     void vcmpz_F64(FPDoubleRegisterID rd)
1535     {
1536         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
1537     }
1538 
vcvt_F64_S32(FPDoubleRegisterID rd,FPSingleRegisterID rm)1539     void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)
1540     {
1541         // boolean values are 64bit (toInt, unsigned, roundZero)
1542         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
1543     }
1544 
vcvtr_S32_F64(FPSingleRegisterID rd,FPDoubleRegisterID rm)1545     void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1546     {
1547         // boolean values are 64bit (toInt, unsigned, roundZero)
1548         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
1549     }
1550 
vdiv_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1551     void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1552     {
1553         m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
1554     }
1555 
vldr(FPDoubleRegisterID rd,RegisterID rn,int32_t imm)1556     void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1557     {
1558         m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
1559     }
1560 
vmov(RegisterID rd,FPSingleRegisterID rn)1561     void vmov(RegisterID rd, FPSingleRegisterID rn)
1562     {
1563         ASSERT(!BadReg(rd));
1564         m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));
1565     }
1566 
vmov(FPSingleRegisterID rd,RegisterID rn)1567     void vmov(FPSingleRegisterID rd, RegisterID rn)
1568     {
1569         ASSERT(!BadReg(rn));
1570         m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0));
1571     }
1572 
1573     void vmrs(RegisterID reg = ARMRegisters::pc)
1574     {
1575         ASSERT(reg != ARMRegisters::sp);
1576         m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
1577     }
1578 
vmul_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1579     void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1580     {
1581         m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
1582     }
1583 
vstr(FPDoubleRegisterID rd,RegisterID rn,int32_t imm)1584     void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1585     {
1586         m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
1587     }
1588 
vsub_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1589     void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1590     {
1591         m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
1592     }
1593 
label()1594     JmpDst label()
1595     {
1596         return JmpDst(m_formatter.size());
1597     }
1598 
align(int alignment)1599     JmpDst align(int alignment)
1600     {
1601         while (!m_formatter.isAligned(alignment))
1602             bkpt();
1603 
1604         return label();
1605     }
1606 
getRelocatedAddress(void * code,JmpSrc jump)1607     static void* getRelocatedAddress(void* code, JmpSrc jump)
1608     {
1609         ASSERT(jump.m_offset != -1);
1610 
1611         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1612     }
1613 
getRelocatedAddress(void * code,JmpDst destination)1614     static void* getRelocatedAddress(void* code, JmpDst destination)
1615     {
1616         ASSERT(destination.m_offset != -1);
1617 
1618         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
1619     }
1620 
getDifferenceBetweenLabels(JmpDst src,JmpDst dst)1621     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1622     {
1623         return dst.m_offset - src.m_offset;
1624     }
1625 
getDifferenceBetweenLabels(JmpDst src,JmpSrc dst)1626     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1627     {
1628         return dst.m_offset - src.m_offset;
1629     }
1630 
getDifferenceBetweenLabels(JmpSrc src,JmpDst dst)1631     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
1632     {
1633         return dst.m_offset - src.m_offset;
1634     }
1635 
executableOffsetFor(int location)1636     int executableOffsetFor(int location)
1637     {
1638         if (!location)
1639             return 0;
1640         return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1];
1641     }
1642 
jumpSizeDelta(JumpType jumpType,JumpLinkType jumpLinkType)1643     int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JumpPaddingSizes[jumpType] - JumpSizes[jumpLinkType]; }
1644 
1645     // Assembler admin methods:
1646 
size()1647     size_t size() const
1648     {
1649         return m_formatter.size();
1650     }
1651 
linkRecordSourceComparator(const LinkRecord & a,const LinkRecord & b)1652     static bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
1653     {
1654         return a.from() < b.from();
1655     }
1656 
canCompact(JumpType jumpType)1657     bool canCompact(JumpType jumpType)
1658     {
1659         // The following cannot be compacted:
1660         //   JumpFixed: represents custom jump sequence
1661         //   JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size
1662         //   JumpConditionFixedSize: represents conditional jump that must remain a fixed size
1663         return (jumpType == JumpNoCondition) || (jumpType == JumpCondition);
1664     }
1665 
computeJumpType(JumpType jumpType,const uint8_t * from,const uint8_t * to)1666     JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
1667     {
1668         if (jumpType == JumpFixed)
1669             return LinkInvalid;
1670 
1671         // for patchable jump we must leave space for the longest code sequence
1672         if (jumpType == JumpNoConditionFixedSize)
1673             return LinkBX;
1674         if (jumpType == JumpConditionFixedSize)
1675             return LinkConditionalBX;
1676 
1677         const int paddingSize = JumpPaddingSizes[jumpType];
1678         bool mayTriggerErrata = false;
1679 
1680         if (jumpType == JumpCondition) {
1681             // 2-byte conditional T1
1682             const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT1]));
1683             if (canBeJumpT1(jumpT1Location, to))
1684                 return LinkJumpT1;
1685             // 4-byte conditional T3
1686             const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT3]));
1687             if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) {
1688                 if (!mayTriggerErrata)
1689                     return LinkJumpT3;
1690             }
1691             // 4-byte conditional T4 with IT
1692             const uint16_t* conditionalJumpT4Location =
1693             reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkConditionalJumpT4]));
1694             if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) {
1695                 if (!mayTriggerErrata)
1696                     return LinkConditionalJumpT4;
1697             }
1698         } else {
1699             // 2-byte unconditional T2
1700             const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT2]));
1701             if (canBeJumpT2(jumpT2Location, to))
1702                 return LinkJumpT2;
1703             // 4-byte unconditional T4
1704             const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT4]));
1705             if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) {
1706                 if (!mayTriggerErrata)
1707                     return LinkJumpT4;
1708             }
1709             // use long jump sequence
1710             return LinkBX;
1711         }
1712 
1713         ASSERT(jumpType == JumpCondition);
1714         return LinkConditionalBX;
1715     }
1716 
computeJumpType(LinkRecord & record,const uint8_t * from,const uint8_t * to)1717     JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
1718     {
1719         JumpLinkType linkType = computeJumpType(record.type(), from, to);
1720         record.setLinkType(linkType);
1721         return linkType;
1722     }
1723 
recordLinkOffsets(int32_t regionStart,int32_t regionEnd,int32_t offset)1724     void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
1725     {
1726         int32_t ptr = regionStart / sizeof(int32_t);
1727         const int32_t end = regionEnd / sizeof(int32_t);
1728         int32_t* offsets = static_cast<int32_t*>(m_formatter.data());
1729         while (ptr < end)
1730             offsets[ptr++] = offset;
1731     }
1732 
jumpsToLink()1733     Vector<LinkRecord>& jumpsToLink()
1734     {
1735         std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
1736         return m_jumpsToLink;
1737     }
1738 
link(LinkRecord & record,uint8_t * from,uint8_t * to)1739     void link(LinkRecord& record, uint8_t* from, uint8_t* to)
1740     {
1741         switch (record.linkType()) {
1742         case LinkJumpT1:
1743             linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1744             break;
1745         case LinkJumpT2:
1746             linkJumpT2(reinterpret_cast<uint16_t*>(from), to);
1747             break;
1748         case LinkJumpT3:
1749             linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1750             break;
1751         case LinkJumpT4:
1752             linkJumpT4(reinterpret_cast<uint16_t*>(from), to);
1753             break;
1754         case LinkConditionalJumpT4:
1755             linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1756             break;
1757         case LinkConditionalBX:
1758             linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to);
1759             break;
1760         case LinkBX:
1761             linkBX(reinterpret_cast<uint16_t*>(from), to);
1762             break;
1763         default:
1764             ASSERT_NOT_REACHED();
1765             break;
1766         }
1767     }
1768 
unlinkedCode()1769     void* unlinkedCode() { return m_formatter.data(); }
1770 
getCallReturnOffset(JmpSrc call)1771     static unsigned getCallReturnOffset(JmpSrc call)
1772     {
1773         ASSERT(call.m_offset >= 0);
1774         return call.m_offset;
1775     }
1776 
1777     // Linking & patching:
1778     //
1779     // 'link' and 'patch' methods are for use on unprotected code - such as the code
1780     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
1781     // code has been finalized it is (platform support permitting) within a non-
1782     // writable region of memory; to modify the code in an execute-only execuable
1783     // pool the 'repatch' and 'relink' methods should be used.
1784 
linkJump(JmpSrc from,JmpDst to)1785     void linkJump(JmpSrc from, JmpDst to)
1786     {
1787         ASSERT(to.m_offset != -1);
1788         ASSERT(from.m_offset != -1);
1789         m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, from.m_type, from.m_condition));
1790     }
1791 
linkJump(void * code,JmpSrc from,void * to)1792     static void linkJump(void* code, JmpSrc from, void* to)
1793     {
1794         ASSERT(from.m_offset != -1);
1795 
1796         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
1797         linkJumpAbsolute(location, to);
1798     }
1799 
1800     // bah, this mathod should really be static, since it is used by the LinkBuffer.
1801     // return a bool saying whether the link was successful?
linkCall(void * code,JmpSrc from,void * to)1802     static void linkCall(void* code, JmpSrc from, void* to)
1803     {
1804         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
1805         ASSERT(from.m_offset != -1);
1806         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1807 
1808         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
1809     }
1810 
linkPointer(void * code,JmpDst where,void * value)1811     static void linkPointer(void* code, JmpDst where, void* value)
1812     {
1813         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
1814     }
1815 
relinkJump(void * from,void * to)1816     static void relinkJump(void* from, void* to)
1817     {
1818         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1819         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
1820 
1821         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
1822 
1823         ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
1824     }
1825 
relinkCall(void * from,void * to)1826     static void relinkCall(void* from, void* to)
1827     {
1828         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1829         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1830 
1831         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
1832     }
1833 
repatchInt32(void * where,int32_t value)1834     static void repatchInt32(void* where, int32_t value)
1835     {
1836         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1837 
1838         setInt32(where, value);
1839     }
1840 
repatchPointer(void * where,void * value)1841     static void repatchPointer(void* where, void* value)
1842     {
1843         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1844 
1845         setPointer(where, value);
1846     }
1847 
1848 private:
1849     // VFP operations commonly take one or more 5-bit operands, typically representing a
1850     // floating point register number.  This will commonly be encoded in the instruction
1851     // in two parts, with one single bit field, and one 4-bit field.  In the case of
1852     // double precision operands the high bit of the register number will be encoded
1853     // separately, and for single precision operands the high bit of the register number
1854     // will be encoded individually.
1855     // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit
1856     // field to be encoded together in the instruction (the low 4-bits of a double
1857     // register number, or the high 4-bits of a single register number), and bit 4
1858     // contains the bit value to be encoded individually.
1859     struct VFPOperand {
VFPOperandVFPOperand1860         explicit VFPOperand(uint32_t value)
1861             : m_value(value)
1862         {
1863             ASSERT(!(m_value & ~0x1f));
1864         }
1865 
VFPOperandVFPOperand1866         VFPOperand(FPDoubleRegisterID reg)
1867             : m_value(reg)
1868         {
1869         }
1870 
VFPOperandVFPOperand1871         VFPOperand(RegisterID reg)
1872             : m_value(reg)
1873         {
1874         }
1875 
VFPOperandVFPOperand1876         VFPOperand(FPSingleRegisterID reg)
1877             : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top.
1878         {
1879         }
1880 
bits1VFPOperand1881         uint32_t bits1()
1882         {
1883             return m_value >> 4;
1884         }
1885 
bits4VFPOperand1886         uint32_t bits4()
1887         {
1888             return m_value & 0xf;
1889         }
1890 
1891         uint32_t m_value;
1892     };
1893 
vcvtOp(bool toInteger,bool isUnsigned,bool isRoundZero)1894     VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero)
1895     {
1896         // Cannot specify rounding when converting to float.
1897         ASSERT(toInteger || !isRoundZero);
1898 
1899         uint32_t op = 0x8;
1900         if (toInteger) {
1901             // opc2 indicates both toInteger & isUnsigned.
1902             op |= isUnsigned ? 0x4 : 0x5;
1903             // 'op' field in instruction is isRoundZero
1904             if (isRoundZero)
1905                 op |= 0x10;
1906         } else {
1907             // 'op' field in instruction is isUnsigned
1908             if (!isUnsigned)
1909                 op |= 0x10;
1910         }
1911         return VFPOperand(op);
1912     }
1913 
setInt32(void * code,uint32_t value)1914     static void setInt32(void* code, uint32_t value)
1915     {
1916         uint16_t* location = reinterpret_cast<uint16_t*>(code);
1917         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
1918 
1919         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
1920         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
1921         location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
1922         location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
1923         location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
1924         location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
1925 
1926         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
1927     }
1928 
setPointer(void * code,void * value)1929     static void setPointer(void* code, void* value)
1930     {
1931         setInt32(code, reinterpret_cast<uint32_t>(value));
1932     }
1933 
isB(void * address)1934     static bool isB(void* address)
1935     {
1936         uint16_t* instruction = static_cast<uint16_t*>(address);
1937         return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
1938     }
1939 
isBX(void * address)1940     static bool isBX(void* address)
1941     {
1942         uint16_t* instruction = static_cast<uint16_t*>(address);
1943         return (instruction[0] & 0xff87) == OP_BX;
1944     }
1945 
isMOV_imm_T3(void * address)1946     static bool isMOV_imm_T3(void* address)
1947     {
1948         uint16_t* instruction = static_cast<uint16_t*>(address);
1949         return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
1950     }
1951 
isMOVT(void * address)1952     static bool isMOVT(void* address)
1953     {
1954         uint16_t* instruction = static_cast<uint16_t*>(address);
1955         return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
1956     }
1957 
isNOP_T1(void * address)1958     static bool isNOP_T1(void* address)
1959     {
1960         uint16_t* instruction = static_cast<uint16_t*>(address);
1961         return instruction[0] == OP_NOP_T1;
1962     }
1963 
isNOP_T2(void * address)1964     static bool isNOP_T2(void* address)
1965     {
1966         uint16_t* instruction = static_cast<uint16_t*>(address);
1967         return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
1968     }
1969 
canBeJumpT1(const uint16_t * instruction,const void * target)1970     static bool canBeJumpT1(const uint16_t* instruction, const void* target)
1971     {
1972         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1973         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1974 
1975         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1976         // It does not appear to be documented in the ARM ARM (big surprise), but
1977         // for OP_B_T1 the branch displacement encoded in the instruction is 2
1978         // less than the actual displacement.
1979         relative -= 2;
1980         return ((relative << 23) >> 23) == relative;
1981     }
1982 
canBeJumpT2(const uint16_t * instruction,const void * target)1983     static bool canBeJumpT2(const uint16_t* instruction, const void* target)
1984     {
1985         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1986         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
1987 
1988         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
1989         // It does not appear to be documented in the ARM ARM (big surprise), but
1990         // for OP_B_T2 the branch displacement encoded in the instruction is 2
1991         // less than the actual displacement.
1992         relative -= 2;
1993         return ((relative << 20) >> 20) == relative;
1994     }
1995 
canBeJumpT3(const uint16_t * instruction,const void * target,bool & mayTriggerErrata)1996     static bool canBeJumpT3(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
1997     {
1998         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
1999         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2000 
2001         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2002         // From Cortex-A8 errata:
2003         // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
2004         // the target of the branch falls within the first region it is
2005         // possible for the processor to incorrectly determine the branch
2006         // instruction, and it is also possible in some cases for the processor
2007         // to enter a deadlock state.
2008         // The instruction is spanning two pages if it ends at an address ending 0x002
2009         bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
2010         mayTriggerErrata = spansTwo4K;
2011         // The target is in the first page if the jump branch back by [3..0x1002] bytes
2012         bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
2013         bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
2014         return ((relative << 11) >> 11) == relative && !wouldTriggerA8Errata;
2015     }
2016 
canBeJumpT4(const uint16_t * instruction,const void * target,bool & mayTriggerErrata)2017     static bool canBeJumpT4(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
2018     {
2019         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2020         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2021 
2022         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2023         // From Cortex-A8 errata:
2024         // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
2025         // the target of the branch falls within the first region it is
2026         // possible for the processor to incorrectly determine the branch
2027         // instruction, and it is also possible in some cases for the processor
2028         // to enter a deadlock state.
2029         // The instruction is spanning two pages if it ends at an address ending 0x002
2030         bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
2031         mayTriggerErrata = spansTwo4K;
2032         // The target is in the first page if the jump branch back by [3..0x1002] bytes
2033         bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
2034         bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
2035         return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata;
2036     }
2037 
linkJumpT1(Condition cond,uint16_t * instruction,void * target)2038     void linkJumpT1(Condition cond, uint16_t* instruction, void* target)
2039     {
2040         // FIMXE: this should be up in the MacroAssembler layer. :-(
2041         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2042         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2043         ASSERT(canBeJumpT1(instruction, target));
2044 
2045         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2046         // It does not appear to be documented in the ARM ARM (big surprise), but
2047         // for OP_B_T1 the branch displacement encoded in the instruction is 2
2048         // less than the actual displacement.
2049         relative -= 2;
2050 
2051         // All branch offsets should be an even distance.
2052         ASSERT(!(relative & 1));
2053         instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1);
2054     }
2055 
linkJumpT2(uint16_t * instruction,void * target)2056     static void linkJumpT2(uint16_t* instruction, void* target)
2057     {
2058         // FIMXE: this should be up in the MacroAssembler layer. :-(
2059         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2060         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2061         ASSERT(canBeJumpT2(instruction, target));
2062 
2063         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2064         // It does not appear to be documented in the ARM ARM (big surprise), but
2065         // for OP_B_T2 the branch displacement encoded in the instruction is 2
2066         // less than the actual displacement.
2067         relative -= 2;
2068 
2069         // All branch offsets should be an even distance.
2070         ASSERT(!(relative & 1));
2071         instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1);
2072     }
2073 
linkJumpT3(Condition cond,uint16_t * instruction,void * target)2074     void linkJumpT3(Condition cond, uint16_t* instruction, void* target)
2075     {
2076         // FIMXE: this should be up in the MacroAssembler layer. :-(
2077         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2078         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2079         bool scratch;
2080         UNUSED_PARAM(scratch);
2081         ASSERT(canBeJumpT3(instruction, target, scratch));
2082 
2083         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2084 
2085         // All branch offsets should be an even distance.
2086         ASSERT(!(relative & 1));
2087         instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12);
2088         instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1);
2089     }
2090 
linkJumpT4(uint16_t * instruction,void * target)2091     static void linkJumpT4(uint16_t* instruction, void* target)
2092     {
2093         // FIMXE: this should be up in the MacroAssembler layer. :-(
2094         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2095         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2096         bool scratch;
2097         UNUSED_PARAM(scratch);
2098         ASSERT(canBeJumpT4(instruction, target, scratch));
2099 
2100         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
2101         // ARM encoding for the top two bits below the sign bit is 'peculiar'.
2102         if (relative >= 0)
2103             relative ^= 0xC00000;
2104 
2105         // All branch offsets should be an even distance.
2106         ASSERT(!(relative & 1));
2107         instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
2108         instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
2109     }
2110 
linkConditionalJumpT4(Condition cond,uint16_t * instruction,void * target)2111     void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target)
2112     {
2113         // FIMXE: this should be up in the MacroAssembler layer. :-(
2114         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2115         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2116 
2117         instruction[-3] = ifThenElse(cond) | OP_IT;
2118         linkJumpT4(instruction, target);
2119     }
2120 
linkBX(uint16_t * instruction,void * target)2121     static void linkBX(uint16_t* instruction, void* target)
2122     {
2123         // FIMXE: this should be up in the MacroAssembler layer. :-(
2124         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2125         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2126 
2127         const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2128         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2129         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2130         instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2131         instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2132         instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2133         instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2134         instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2135     }
2136 
linkConditionalBX(Condition cond,uint16_t * instruction,void * target)2137     void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
2138     {
2139         // FIMXE: this should be up in the MacroAssembler layer. :-(
2140         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2141         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2142 
2143         linkBX(instruction, target);
2144         instruction[-6] = ifThenElse(cond, true, true) | OP_IT;
2145     }
2146 
linkJumpAbsolute(uint16_t * instruction,void * target)2147     static void linkJumpAbsolute(uint16_t* instruction, void* target)
2148     {
2149         // FIMXE: this should be up in the MacroAssembler layer. :-(
2150         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2151         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2152 
2153         ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
2154                || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
2155 
2156         bool scratch;
2157         if (canBeJumpT4(instruction, target, scratch)) {
2158             // There may be a better way to fix this, but right now put the NOPs first, since in the
2159             // case of an conditional branch this will be coming after an ITTT predicating *three*
2160             // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
2161             // variable wdith encoding - the previous instruction might *look* like an ITTT but
2162             // actually be the second half of a 2-word op.
2163             instruction[-5] = OP_NOP_T1;
2164             instruction[-4] = OP_NOP_T2a;
2165             instruction[-3] = OP_NOP_T2b;
2166             linkJumpT4(instruction, target);
2167         } else {
2168             const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2169             ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2170             ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2171             instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2172             instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2173             instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2174             instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2175             instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2176         }
2177     }
2178 
twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op,ARMThumbImmediate imm)2179     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
2180     {
2181         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
2182     }
2183 
twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd,ARMThumbImmediate imm)2184     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
2185     {
2186         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
2187     }
2188 
2189     class ARMInstructionFormatter {
2190     public:
oneWordOp5Reg3Imm8(OpcodeID op,RegisterID rd,uint8_t imm)2191         void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
2192         {
2193             m_buffer.putShort(op | (rd << 8) | imm);
2194         }
2195 
oneWordOp5Imm5Reg3Reg3(OpcodeID op,uint8_t imm,RegisterID reg1,RegisterID reg2)2196         void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
2197         {
2198             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
2199         }
2200 
oneWordOp7Reg3Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2,RegisterID reg3)2201         void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
2202         {
2203             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
2204         }
2205 
oneWordOp8Imm8(OpcodeID op,uint8_t imm)2206         void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
2207         {
2208             m_buffer.putShort(op | imm);
2209         }
2210 
oneWordOp8RegReg143(OpcodeID op,RegisterID reg1,RegisterID reg2)2211         void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
2212         {
2213             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
2214         }
oneWordOp9Imm7(OpcodeID op,uint8_t imm)2215         void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
2216         {
2217             m_buffer.putShort(op | imm);
2218         }
2219 
oneWordOp10Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2)2220         void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
2221         {
2222             m_buffer.putShort(op | (reg1 << 3) | reg2);
2223         }
2224 
twoWordOp12Reg4FourFours(OpcodeID1 op,RegisterID reg,FourFours ff)2225         void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
2226         {
2227             m_buffer.putShort(op | reg);
2228             m_buffer.putShort(ff.m_u.value);
2229         }
2230 
twoWordOp16FourFours(OpcodeID1 op,FourFours ff)2231         void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
2232         {
2233             m_buffer.putShort(op);
2234             m_buffer.putShort(ff.m_u.value);
2235         }
2236 
twoWordOp16Op16(OpcodeID1 op1,OpcodeID2 op2)2237         void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
2238         {
2239             m_buffer.putShort(op1);
2240             m_buffer.putShort(op2);
2241         }
2242 
twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op,int imm4,RegisterID rd,ARMThumbImmediate imm)2243         void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
2244         {
2245             ARMThumbImmediate newImm = imm;
2246             newImm.m_value.imm4 = imm4;
2247 
2248             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
2249             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
2250         }
2251 
twoWordOp12Reg4Reg4Imm12(OpcodeID1 op,RegisterID reg1,RegisterID reg2,uint16_t imm)2252         void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
2253         {
2254             m_buffer.putShort(op | reg1);
2255             m_buffer.putShort((reg2 << 12) | imm);
2256         }
2257 
2258         // Formats up instructions of the pattern:
2259         //    111111111B11aaaa:bbbb222SA2C2cccc
2260         // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
2261         // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
vfpOp(OpcodeID1 op1,OpcodeID2 op2,bool size,VFPOperand a,VFPOperand b,VFPOperand c)2262         void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
2263         {
2264             ASSERT(!(op1 & 0x004f));
2265             ASSERT(!(op2 & 0xf1af));
2266             m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4());
2267             m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4());
2268         }
2269 
2270         // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
2271         // (i.e. +/-(0..255) 32-bit words)
vfpMemOp(OpcodeID1 op1,OpcodeID2 op2,bool size,RegisterID rn,VFPOperand rd,int32_t imm)2272         void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
2273         {
2274             bool up = true;
2275             if (imm < 0) {
2276                 imm = -imm;
2277                 up = false;
2278             }
2279 
2280             uint32_t offset = imm;
2281             ASSERT(!(offset & ~0x3fc));
2282             offset >>= 2;
2283 
2284             m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn);
2285             m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset);
2286         }
2287 
2288         // Administrative methods:
2289 
size()2290         size_t size() const { return m_buffer.size(); }
isAligned(int alignment)2291         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
data()2292         void* data() const { return m_buffer.data(); }
executableCopy(ExecutablePool * allocator)2293         void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
2294 
2295 #ifndef NDEBUG
debugOffset()2296         unsigned debugOffset() { return m_formatter.debugOffset(); }
2297 #endif
2298 
2299     private:
2300         AssemblerBuffer m_buffer;
2301     } m_formatter;
2302 
2303     Vector<LinkRecord> m_jumpsToLink;
2304     Vector<int32_t> m_offsets;
2305 };
2306 
2307 } // namespace JSC
2308 
2309 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
2310 
2311 #endif // ARMAssembler_h
2312