1 /*
2  * Copyright (C) 2009, 2010, 2012, 2013 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 "MacroAssemblerCodeRef.h"
34 #include "AbstractMacroAssembler.h"
35 #include <wtf/Assertions.h>
36 #include <wtf/Vector.h>
37 #include <stdint.h>
38 
39 #if OS(IOS)
40 #include <libkern/OSCacheControl.h>
41 #endif
42 
43 #if OS(RTEMS)
44 #include <rtems/rtems/cache.h>
45 #endif
46 
47 namespace JSC {
48 
49 namespace ARMRegisters {
50     typedef enum {
51         r0,
52         r1,
53         r2,
54         r3,
55         r4,
56         r5,
57         r6,
58         r7, wr = r7,   // thumb work register
59         r8,
60         r9, sb = r9,   // static base
61         r10, sl = r10, // stack limit
62         r11, fp = r11, // frame pointer
63         r12, ip = r12,
64         r13, sp = r13,
65         r14, lr = r14,
66         r15, pc = r15,
67     } RegisterID;
68 
69     typedef enum {
70         s0,
71         s1,
72         s2,
73         s3,
74         s4,
75         s5,
76         s6,
77         s7,
78         s8,
79         s9,
80         s10,
81         s11,
82         s12,
83         s13,
84         s14,
85         s15,
86         s16,
87         s17,
88         s18,
89         s19,
90         s20,
91         s21,
92         s22,
93         s23,
94         s24,
95         s25,
96         s26,
97         s27,
98         s28,
99         s29,
100         s30,
101         s31,
102     } FPSingleRegisterID;
103 
104     typedef enum {
105         d0,
106         d1,
107         d2,
108         d3,
109         d4,
110         d5,
111         d6,
112         d7,
113         d8,
114         d9,
115         d10,
116         d11,
117         d12,
118         d13,
119         d14,
120         d15,
121         d16,
122         d17,
123         d18,
124         d19,
125         d20,
126         d21,
127         d22,
128         d23,
129         d24,
130         d25,
131         d26,
132         d27,
133         d28,
134         d29,
135         d30,
136         d31,
137     } FPDoubleRegisterID;
138 
139     typedef enum {
140         q0,
141         q1,
142         q2,
143         q3,
144         q4,
145         q5,
146         q6,
147         q7,
148         q8,
149         q9,
150         q10,
151         q11,
152         q12,
153         q13,
154         q14,
155         q15,
156         q16,
157         q17,
158         q18,
159         q19,
160         q20,
161         q21,
162         q22,
163         q23,
164         q24,
165         q25,
166         q26,
167         q27,
168         q28,
169         q29,
170         q30,
171         q31,
172     } FPQuadRegisterID;
173 
asSingle(FPDoubleRegisterID reg)174     inline FPSingleRegisterID asSingle(FPDoubleRegisterID reg)
175     {
176         ASSERT(reg < d16);
177         return (FPSingleRegisterID)(reg << 1);
178     }
179 
asDouble(FPSingleRegisterID reg)180     inline FPDoubleRegisterID asDouble(FPSingleRegisterID reg)
181     {
182         ASSERT(!(reg & 1));
183         return (FPDoubleRegisterID)(reg >> 1);
184     }
185 }
186 
187 class ARMv7Assembler;
188 class ARMThumbImmediate {
189     friend class ARMv7Assembler;
190 
191     typedef uint8_t ThumbImmediateType;
192     static const ThumbImmediateType TypeInvalid = 0;
193     static const ThumbImmediateType TypeEncoded = 1;
194     static const ThumbImmediateType TypeUInt16 = 2;
195 
196     typedef union {
197         int16_t asInt;
198         struct {
199             unsigned imm8 : 8;
200             unsigned imm3 : 3;
201             unsigned i    : 1;
202             unsigned imm4 : 4;
203         };
204         // If this is an encoded immediate, then it may describe a shift, or a pattern.
205         struct {
206             unsigned shiftValue7 : 7;
207             unsigned shiftAmount : 5;
208         };
209         struct {
210             unsigned immediate   : 8;
211             unsigned pattern     : 4;
212         };
213     } ThumbImmediateValue;
214 
215     // byte0 contains least significant bit; not using an array to make client code endian agnostic.
216     typedef union {
217         int32_t asInt;
218         struct {
219             uint8_t byte0;
220             uint8_t byte1;
221             uint8_t byte2;
222             uint8_t byte3;
223         };
224     } PatternBytes;
225 
countLeadingZerosPartial(uint32_t & value,int32_t & zeros,const int N)226     ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
227     {
228         if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */
229             value >>= N;             /* if any were set, lose the bottom N */
230         else                         /* if none of the top N bits are set, */
231             zeros += N;              /* then we have identified N leading zeros */
232     }
233 
countLeadingZeros(uint32_t value)234     static int32_t countLeadingZeros(uint32_t value)
235     {
236         if (!value)
237             return 32;
238 
239         int32_t zeros = 0;
240         countLeadingZerosPartial(value, zeros, 16);
241         countLeadingZerosPartial(value, zeros, 8);
242         countLeadingZerosPartial(value, zeros, 4);
243         countLeadingZerosPartial(value, zeros, 2);
244         countLeadingZerosPartial(value, zeros, 1);
245         return zeros;
246     }
247 
ARMThumbImmediate()248     ARMThumbImmediate()
249         : m_type(TypeInvalid)
250     {
251         m_value.asInt = 0;
252     }
253 
ARMThumbImmediate(ThumbImmediateType type,ThumbImmediateValue value)254     ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
255         : m_type(type)
256         , m_value(value)
257     {
258     }
259 
ARMThumbImmediate(ThumbImmediateType type,uint16_t value)260     ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
261         : m_type(TypeUInt16)
262     {
263         // Make sure this constructor is only reached with type TypeUInt16;
264         // this extra parameter makes the code a little clearer by making it
265         // explicit at call sites which type is being constructed
266         ASSERT_UNUSED(type, type == TypeUInt16);
267 
268         m_value.asInt = value;
269     }
270 
271 public:
makeEncodedImm(uint32_t value)272     static ARMThumbImmediate makeEncodedImm(uint32_t value)
273     {
274         ThumbImmediateValue encoding;
275         encoding.asInt = 0;
276 
277         // okay, these are easy.
278         if (value < 256) {
279             encoding.immediate = value;
280             encoding.pattern = 0;
281             return ARMThumbImmediate(TypeEncoded, encoding);
282         }
283 
284         int32_t leadingZeros = countLeadingZeros(value);
285         // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
286         ASSERT(leadingZeros < 24);
287 
288         // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
289         // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
290         // zero.  count(B) == 8, so the count of bits to be checked is 24 - count(Z).
291         int32_t rightShiftAmount = 24 - leadingZeros;
292         if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
293             // Shift the value down to the low byte position.  The assign to
294             // shiftValue7 drops the implicit top bit.
295             encoding.shiftValue7 = value >> rightShiftAmount;
296             // The endoded shift amount is the magnitude of a right rotate.
297             encoding.shiftAmount = 8 + leadingZeros;
298             return ARMThumbImmediate(TypeEncoded, encoding);
299         }
300 
301         PatternBytes bytes;
302         bytes.asInt = value;
303 
304         if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
305             encoding.immediate = bytes.byte0;
306             encoding.pattern = 3;
307             return ARMThumbImmediate(TypeEncoded, encoding);
308         }
309 
310         if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
311             encoding.immediate = bytes.byte0;
312             encoding.pattern = 1;
313             return ARMThumbImmediate(TypeEncoded, encoding);
314         }
315 
316         if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
317             encoding.immediate = bytes.byte1;
318             encoding.pattern = 2;
319             return ARMThumbImmediate(TypeEncoded, encoding);
320         }
321 
322         return ARMThumbImmediate();
323     }
324 
makeUInt12(int32_t value)325     static ARMThumbImmediate makeUInt12(int32_t value)
326     {
327         return (!(value & 0xfffff000))
328             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
329             : ARMThumbImmediate();
330     }
331 
makeUInt12OrEncodedImm(int32_t value)332     static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
333     {
334         // If this is not a 12-bit unsigned it, try making an encoded immediate.
335         return (!(value & 0xfffff000))
336             ? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
337             : makeEncodedImm(value);
338     }
339 
340     // The 'make' methods, above, return a !isValid() value if the argument
341     // cannot be represented as the requested type.  This methods  is called
342     // 'get' since the argument can always be represented.
makeUInt16(uint16_t value)343     static ARMThumbImmediate makeUInt16(uint16_t value)
344     {
345         return ARMThumbImmediate(TypeUInt16, value);
346     }
347 
isValid()348     bool isValid()
349     {
350         return m_type != TypeInvalid;
351     }
352 
asUInt16()353     uint16_t asUInt16() const { return m_value.asInt; }
354 
355     // These methods rely on the format of encoded byte values.
isUInt3()356     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
isUInt4()357     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
isUInt5()358     bool isUInt5() { return !(m_value.asInt & 0xffe0); }
isUInt6()359     bool isUInt6() { return !(m_value.asInt & 0xffc0); }
isUInt7()360     bool isUInt7() { return !(m_value.asInt & 0xff80); }
isUInt8()361     bool isUInt8() { return !(m_value.asInt & 0xff00); }
isUInt9()362     bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
isUInt10()363     bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
isUInt12()364     bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
isUInt16()365     bool isUInt16() { return m_type == TypeUInt16; }
getUInt3()366     uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
getUInt4()367     uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
getUInt5()368     uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
getUInt6()369     uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
getUInt7()370     uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
getUInt8()371     uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
getUInt9()372     uint16_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
getUInt10()373     uint16_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
getUInt12()374     uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
getUInt16()375     uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
376 
isEncodedImm()377     bool isEncodedImm() { return m_type == TypeEncoded; }
378 
379 private:
380     ThumbImmediateType m_type;
381     ThumbImmediateValue m_value;
382 };
383 
384 typedef enum {
385     SRType_LSL,
386     SRType_LSR,
387     SRType_ASR,
388     SRType_ROR,
389 
390     SRType_RRX = SRType_ROR
391 } ARMShiftType;
392 
393 class ShiftTypeAndAmount {
394     friend class ARMv7Assembler;
395 
396 public:
ShiftTypeAndAmount()397     ShiftTypeAndAmount()
398     {
399         m_u.type = (ARMShiftType)0;
400         m_u.amount = 0;
401     }
402 
ShiftTypeAndAmount(ARMShiftType type,unsigned amount)403     ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
404     {
405         m_u.type = type;
406         m_u.amount = amount & 31;
407     }
408 
lo4()409     unsigned lo4() { return m_u.lo4; }
hi4()410     unsigned hi4() { return m_u.hi4; }
411 
412 private:
413     union {
414         struct {
415             unsigned lo4 : 4;
416             unsigned hi4 : 4;
417         };
418         struct {
419             unsigned type   : 2;
420             unsigned amount : 6;
421         };
422     } m_u;
423 };
424 
425 class ARMv7Assembler {
426 public:
427     typedef ARMRegisters::RegisterID RegisterID;
428     typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
429     typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
430     typedef ARMRegisters::FPQuadRegisterID FPQuadRegisterID;
431     typedef ARMRegisters::FPDoubleRegisterID FPRegisterID;
432 
433     // (HS, LO, HI, LS) -> (AE, B, A, BE)
434     // (VS, VC) -> (O, NO)
435     typedef enum {
436         ConditionEQ,
437         ConditionNE,
438         ConditionHS, ConditionCS = ConditionHS,
439         ConditionLO, ConditionCC = ConditionLO,
440         ConditionMI,
441         ConditionPL,
442         ConditionVS,
443         ConditionVC,
444         ConditionHI,
445         ConditionLS,
446         ConditionGE,
447         ConditionLT,
448         ConditionGT,
449         ConditionLE,
450         ConditionAL,
451         ConditionInvalid
452     } Condition;
453 
454 #define JUMP_ENUM_WITH_SIZE(index, value) (((value) << 3) | (index))
455 #define JUMP_ENUM_SIZE(jump) ((jump) >> 3)
456     enum JumpType { JumpFixed = JUMP_ENUM_WITH_SIZE(0, 0),
457                     JumpNoCondition = JUMP_ENUM_WITH_SIZE(1, 5 * sizeof(uint16_t)),
458                     JumpCondition = JUMP_ENUM_WITH_SIZE(2, 6 * sizeof(uint16_t)),
459                     JumpNoConditionFixedSize = JUMP_ENUM_WITH_SIZE(3, 5 * sizeof(uint16_t)),
460                     JumpConditionFixedSize = JUMP_ENUM_WITH_SIZE(4, 6 * sizeof(uint16_t))
461     };
462     enum JumpLinkType {
463         LinkInvalid = JUMP_ENUM_WITH_SIZE(0, 0),
464         LinkJumpT1 = JUMP_ENUM_WITH_SIZE(1, sizeof(uint16_t)),
465         LinkJumpT2 = JUMP_ENUM_WITH_SIZE(2, sizeof(uint16_t)),
466         LinkJumpT3 = JUMP_ENUM_WITH_SIZE(3, 2 * sizeof(uint16_t)),
467         LinkJumpT4 = JUMP_ENUM_WITH_SIZE(4, 2 * sizeof(uint16_t)),
468         LinkConditionalJumpT4 = JUMP_ENUM_WITH_SIZE(5, 3 * sizeof(uint16_t)),
469         LinkBX = JUMP_ENUM_WITH_SIZE(6, 5 * sizeof(uint16_t)),
470         LinkConditionalBX = JUMP_ENUM_WITH_SIZE(7, 6 * sizeof(uint16_t))
471     };
472 
473     class LinkRecord {
474     public:
LinkRecord(intptr_t from,intptr_t to,JumpType type,Condition condition)475         LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
476         {
477             data.realTypes.m_from = from;
478             data.realTypes.m_to = to;
479             data.realTypes.m_type = type;
480             data.realTypes.m_linkType = LinkInvalid;
481             data.realTypes.m_condition = condition;
482         }
483         void operator=(const LinkRecord& other)
484         {
485             data.copyTypes.content[0] = other.data.copyTypes.content[0];
486             data.copyTypes.content[1] = other.data.copyTypes.content[1];
487             data.copyTypes.content[2] = other.data.copyTypes.content[2];
488         }
from()489         intptr_t from() const { return data.realTypes.m_from; }
setFrom(intptr_t from)490         void setFrom(intptr_t from) { data.realTypes.m_from = from; }
to()491         intptr_t to() const { return data.realTypes.m_to; }
type()492         JumpType type() const { return data.realTypes.m_type; }
linkType()493         JumpLinkType linkType() const { return data.realTypes.m_linkType; }
setLinkType(JumpLinkType linkType)494         void setLinkType(JumpLinkType linkType) { ASSERT(data.realTypes.m_linkType == LinkInvalid); data.realTypes.m_linkType = linkType; }
condition()495         Condition condition() const { return data.realTypes.m_condition; }
496     private:
497         union {
498             struct RealTypes {
499                 int32_t m_from : 31;
500                 int32_t m_to : 31;
501                 JumpType m_type : 8;
502                 JumpLinkType m_linkType : 8;
503                 Condition m_condition : 16;
504             } realTypes;
505             struct CopyTypes {
506                 uint32_t content[3];
507             } copyTypes;
508             COMPILE_ASSERT(sizeof(RealTypes) == sizeof(CopyTypes), LinkRecordCopyStructSizeEqualsRealStruct);
509         } data;
510     };
511 
ARMv7Assembler()512     ARMv7Assembler()
513         : m_indexOfLastWatchpoint(INT_MIN)
514         , m_indexOfTailOfLastWatchpoint(INT_MIN)
515     {
516     }
517 
518 
519     // Jump:
520     //
521     // A jump object is a reference to a jump instruction that has been planted
522     // into the code buffer - it is typically used to link the jump, setting the
523     // relative offset such that when executed it will jump to the desired
524     // destination.
525     template <typename LabelType>
526     class Jump {
527         template<class TemplateAssemblerType> friend class AbstractMacroAssembler;
528         friend class Call;
529         template <typename, template <typename> class> friend class LinkBufferBase;;
530     public:
Jump()531         Jump()
532         {
533         }
534 
535         // Fixme: this information should be stored in the instruction stream, not in the Jump object.
536         Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type = ARMv7Assembler::JumpNoCondition, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
m_label(jmp)537             : m_label(jmp)
538             , m_type(type)
539             , m_condition(condition)
540         {
541         }
542 
label()543         LabelType label() const
544         {
545             LabelType result;
546             result.m_label = m_label;
547             return result;
548         }
549 
link(AbstractMacroAssembler<ARMv7Assembler> * masm)550         void link(AbstractMacroAssembler<ARMv7Assembler>* masm) const
551         {
552             masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
553         }
554 
linkTo(LabelType label,AbstractMacroAssembler<ARMv7Assembler> * masm)555         void linkTo(LabelType label, AbstractMacroAssembler<ARMv7Assembler>* masm) const
556         {
557             masm->m_assembler.linkJump(m_label, label.label(), m_type, m_condition);
558         }
559 
isSet()560         bool isSet() const { return m_label.isSet(); }
561 
562     private:
563         AssemblerLabel m_label;
564         ARMv7Assembler::JumpType m_type;
565         ARMv7Assembler::Condition m_condition;
566     };
567 
568 private:
569 
570     // ARMv7, Appx-A.6.3
BadReg(RegisterID reg)571     static bool BadReg(RegisterID reg)
572     {
573         return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
574     }
575 
singleRegisterMask(FPSingleRegisterID rdNum,int highBitsShift,int lowBitShift)576     uint32_t singleRegisterMask(FPSingleRegisterID rdNum, int highBitsShift, int lowBitShift)
577     {
578         uint32_t rdMask = (rdNum >> 1) << highBitsShift;
579         if (rdNum & 1)
580             rdMask |= 1 << lowBitShift;
581         return rdMask;
582     }
583 
doubleRegisterMask(FPDoubleRegisterID rdNum,int highBitShift,int lowBitsShift)584     uint32_t doubleRegisterMask(FPDoubleRegisterID rdNum, int highBitShift, int lowBitsShift)
585     {
586         uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
587         if (rdNum & 16)
588             rdMask |= 1 << highBitShift;
589         return rdMask;
590     }
591 
592     typedef enum {
593         OP_ADD_reg_T1       = 0x1800,
594         OP_SUB_reg_T1       = 0x1A00,
595         OP_ADD_imm_T1       = 0x1C00,
596         OP_SUB_imm_T1       = 0x1E00,
597         OP_MOV_imm_T1       = 0x2000,
598         OP_CMP_imm_T1       = 0x2800,
599         OP_ADD_imm_T2       = 0x3000,
600         OP_SUB_imm_T2       = 0x3800,
601         OP_AND_reg_T1       = 0x4000,
602         OP_EOR_reg_T1       = 0x4040,
603         OP_TST_reg_T1       = 0x4200,
604         OP_RSB_imm_T1       = 0x4240,
605         OP_CMP_reg_T1       = 0x4280,
606         OP_ORR_reg_T1       = 0x4300,
607         OP_MVN_reg_T1       = 0x43C0,
608         OP_ADD_reg_T2       = 0x4400,
609         OP_MOV_reg_T1       = 0x4600,
610         OP_BLX              = 0x4700,
611         OP_BX               = 0x4700,
612         OP_STR_reg_T1       = 0x5000,
613         OP_STRH_reg_T1      = 0x5200,
614         OP_STRB_reg_T1      = 0x5400,
615         OP_LDRSB_reg_T1     = 0x5600,
616         OP_LDR_reg_T1       = 0x5800,
617         OP_LDRH_reg_T1      = 0x5A00,
618         OP_LDRB_reg_T1      = 0x5C00,
619         OP_LDRSH_reg_T1     = 0x5E00,
620         OP_STR_imm_T1       = 0x6000,
621         OP_LDR_imm_T1       = 0x6800,
622         OP_STRB_imm_T1      = 0x7000,
623         OP_LDRB_imm_T1      = 0x7800,
624         OP_STRH_imm_T1      = 0x8000,
625         OP_LDRH_imm_T1      = 0x8800,
626         OP_STR_imm_T2       = 0x9000,
627         OP_LDR_imm_T2       = 0x9800,
628         OP_ADD_SP_imm_T1    = 0xA800,
629         OP_ADD_SP_imm_T2    = 0xB000,
630         OP_SUB_SP_imm_T1    = 0xB080,
631         OP_BKPT             = 0xBE00,
632         OP_IT               = 0xBF00,
633         OP_NOP_T1           = 0xBF00,
634     } OpcodeID;
635 
636     typedef enum {
637         OP_B_T1         = 0xD000,
638         OP_B_T2         = 0xE000,
639         OP_AND_reg_T2   = 0xEA00,
640         OP_TST_reg_T2   = 0xEA10,
641         OP_ORR_reg_T2   = 0xEA40,
642         OP_ORR_S_reg_T2 = 0xEA50,
643         OP_ASR_imm_T1   = 0xEA4F,
644         OP_LSL_imm_T1   = 0xEA4F,
645         OP_LSR_imm_T1   = 0xEA4F,
646         OP_ROR_imm_T1   = 0xEA4F,
647         OP_MVN_reg_T2   = 0xEA6F,
648         OP_EOR_reg_T2   = 0xEA80,
649         OP_ADD_reg_T3   = 0xEB00,
650         OP_ADD_S_reg_T3 = 0xEB10,
651         OP_SUB_reg_T2   = 0xEBA0,
652         OP_SUB_S_reg_T2 = 0xEBB0,
653         OP_CMP_reg_T2   = 0xEBB0,
654         OP_VMOV_CtoD    = 0xEC00,
655         OP_VMOV_DtoC    = 0xEC10,
656         OP_FSTS         = 0xED00,
657         OP_VSTR         = 0xED00,
658         OP_FLDS         = 0xED10,
659         OP_VLDR         = 0xED10,
660         OP_VMOV_CtoS    = 0xEE00,
661         OP_VMOV_StoC    = 0xEE10,
662         OP_VMUL_T2      = 0xEE20,
663         OP_VADD_T2      = 0xEE30,
664         OP_VSUB_T2      = 0xEE30,
665         OP_VDIV         = 0xEE80,
666         OP_VABS_T2      = 0xEEB0,
667         OP_VCMP         = 0xEEB0,
668         OP_VCVT_FPIVFP  = 0xEEB0,
669         OP_VMOV_T2      = 0xEEB0,
670         OP_VMOV_IMM_T2  = 0xEEB0,
671         OP_VMRS         = 0xEEB0,
672         OP_VNEG_T2      = 0xEEB0,
673         OP_VSQRT_T1     = 0xEEB0,
674         OP_VCVTSD_T1    = 0xEEB0,
675         OP_VCVTDS_T1    = 0xEEB0,
676         OP_B_T3a        = 0xF000,
677         OP_B_T4a        = 0xF000,
678         OP_AND_imm_T1   = 0xF000,
679         OP_TST_imm      = 0xF010,
680         OP_ORR_imm_T1   = 0xF040,
681         OP_MOV_imm_T2   = 0xF040,
682         OP_MVN_imm      = 0xF060,
683         OP_EOR_imm_T1   = 0xF080,
684         OP_ADD_imm_T3   = 0xF100,
685         OP_ADD_S_imm_T3 = 0xF110,
686         OP_CMN_imm      = 0xF110,
687         OP_ADC_imm      = 0xF140,
688         OP_SUB_imm_T3   = 0xF1A0,
689         OP_SUB_S_imm_T3 = 0xF1B0,
690         OP_CMP_imm_T2   = 0xF1B0,
691         OP_RSB_imm_T2   = 0xF1C0,
692         OP_RSB_S_imm_T2 = 0xF1D0,
693         OP_ADD_imm_T4   = 0xF200,
694         OP_MOV_imm_T3   = 0xF240,
695         OP_SUB_imm_T4   = 0xF2A0,
696         OP_MOVT         = 0xF2C0,
697         OP_UBFX_T1      = 0xF3C0,
698         OP_NOP_T2a      = 0xF3AF,
699         OP_STRB_imm_T3  = 0xF800,
700         OP_STRB_reg_T2  = 0xF800,
701         OP_LDRB_imm_T3  = 0xF810,
702         OP_LDRB_reg_T2  = 0xF810,
703         OP_STRH_imm_T3  = 0xF820,
704         OP_STRH_reg_T2  = 0xF820,
705         OP_LDRH_reg_T2  = 0xF830,
706         OP_LDRH_imm_T3  = 0xF830,
707         OP_STR_imm_T4   = 0xF840,
708         OP_STR_reg_T2   = 0xF840,
709         OP_LDR_imm_T4   = 0xF850,
710         OP_LDR_reg_T2   = 0xF850,
711         OP_STRB_imm_T2  = 0xF880,
712         OP_LDRB_imm_T2  = 0xF890,
713         OP_STRH_imm_T2  = 0xF8A0,
714         OP_LDRH_imm_T2  = 0xF8B0,
715         OP_STR_imm_T3   = 0xF8C0,
716         OP_LDR_imm_T3   = 0xF8D0,
717         OP_LDRSB_reg_T2 = 0xF910,
718         OP_LDRSH_reg_T2 = 0xF930,
719         OP_LSL_reg_T2   = 0xFA00,
720         OP_LSR_reg_T2   = 0xFA20,
721         OP_ASR_reg_T2   = 0xFA40,
722         OP_ROR_reg_T2   = 0xFA60,
723         OP_CLZ          = 0xFAB0,
724         OP_SMULL_T1     = 0xFB80,
725 #if CPU(APPLE_ARMV7S)
726         OP_SDIV_T1      = 0xFB90,
727         OP_UDIV_T1      = 0xFBB0,
728 #endif
729     } OpcodeID1;
730 
731     typedef enum {
732         OP_VADD_T2b     = 0x0A00,
733         OP_VDIVb        = 0x0A00,
734         OP_FLDSb        = 0x0A00,
735         OP_VLDRb        = 0x0A00,
736         OP_VMOV_IMM_T2b = 0x0A00,
737         OP_VMOV_T2b     = 0x0A40,
738         OP_VMUL_T2b     = 0x0A00,
739         OP_FSTSb        = 0x0A00,
740         OP_VSTRb        = 0x0A00,
741         OP_VMOV_StoCb   = 0x0A10,
742         OP_VMOV_CtoSb   = 0x0A10,
743         OP_VMOV_DtoCb   = 0x0A10,
744         OP_VMOV_CtoDb   = 0x0A10,
745         OP_VMRSb        = 0x0A10,
746         OP_VABS_T2b     = 0x0A40,
747         OP_VCMPb        = 0x0A40,
748         OP_VCVT_FPIVFPb = 0x0A40,
749         OP_VNEG_T2b     = 0x0A40,
750         OP_VSUB_T2b     = 0x0A40,
751         OP_VSQRT_T1b    = 0x0A40,
752         OP_VCVTSD_T1b   = 0x0A40,
753         OP_VCVTDS_T1b   = 0x0A40,
754         OP_NOP_T2b      = 0x8000,
755         OP_B_T3b        = 0x8000,
756         OP_B_T4b        = 0x9000,
757     } OpcodeID2;
758 
759     struct FourFours {
FourFoursFourFours760         FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
761         {
762             m_u.f0 = f0;
763             m_u.f1 = f1;
764             m_u.f2 = f2;
765             m_u.f3 = f3;
766         }
767 
768         union {
769             unsigned value;
770             struct {
771                 unsigned f0 : 4;
772                 unsigned f1 : 4;
773                 unsigned f2 : 4;
774                 unsigned f3 : 4;
775             };
776         } m_u;
777     };
778 
779     class ARMInstructionFormatter;
780 
781     // false means else!
ifThenElseConditionBit(Condition condition,bool isIf)782     bool ifThenElseConditionBit(Condition condition, bool isIf)
783     {
784         return isIf ? (condition & 1) : !(condition & 1);
785     }
ifThenElse(Condition condition,bool inst2if,bool inst3if,bool inst4if)786     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
787     {
788         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
789             | (ifThenElseConditionBit(condition, inst3if) << 2)
790             | (ifThenElseConditionBit(condition, inst4if) << 1)
791             | 1;
792         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
793         return (condition << 4) | mask;
794     }
ifThenElse(Condition condition,bool inst2if,bool inst3if)795     uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
796     {
797         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
798             | (ifThenElseConditionBit(condition, inst3if) << 2)
799             | 2;
800         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
801         return (condition << 4) | mask;
802     }
ifThenElse(Condition condition,bool inst2if)803     uint8_t ifThenElse(Condition condition, bool inst2if)
804     {
805         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
806             | 4;
807         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
808         return (condition << 4) | mask;
809     }
810 
ifThenElse(Condition condition)811     uint8_t ifThenElse(Condition condition)
812     {
813         int mask = 8;
814         return (condition << 4) | mask;
815     }
816 
817 public:
818 
adc(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)819     void adc(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
820     {
821         // Rd can only be SP if Rn is also SP.
822         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
823         ASSERT(rd != ARMRegisters::pc);
824         ASSERT(rn != ARMRegisters::pc);
825         ASSERT(imm.isEncodedImm());
826 
827         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADC_imm, rn, rd, imm);
828     }
829 
add(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)830     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
831     {
832         // Rd can only be SP if Rn is also SP.
833         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
834         ASSERT(rd != ARMRegisters::pc);
835         ASSERT(rn != ARMRegisters::pc);
836         ASSERT(imm.isValid());
837 
838         if (rn == ARMRegisters::sp) {
839             ASSERT(!(imm.getUInt16() & 3));
840             if (!(rd & 8) && imm.isUInt10()) {
841                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, static_cast<uint8_t>(imm.getUInt10() >> 2));
842                 return;
843             } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
844                 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, static_cast<uint8_t>(imm.getUInt9() >> 2));
845                 return;
846             }
847         } else if (!((rd | rn) & 8)) {
848             if (imm.isUInt3()) {
849                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
850                 return;
851             } else if ((rd == rn) && imm.isUInt8()) {
852                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
853                 return;
854             }
855         }
856 
857         if (imm.isEncodedImm())
858             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
859         else {
860             ASSERT(imm.isUInt12());
861             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
862         }
863     }
864 
add(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)865     ALWAYS_INLINE void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
866     {
867         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
868         ASSERT(rd != ARMRegisters::pc);
869         ASSERT(rn != ARMRegisters::pc);
870         ASSERT(!BadReg(rm));
871         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
872     }
873 
874     // NOTE: In an IT block, add doesn't modify the flags register.
add(RegisterID rd,RegisterID rn,RegisterID rm)875     ALWAYS_INLINE void add(RegisterID rd, RegisterID rn, RegisterID rm)
876     {
877         if (rd == rn)
878             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
879         else if (rd == rm)
880             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
881         else if (!((rd | rn | rm) & 8))
882             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
883         else
884             add(rd, rn, rm, ShiftTypeAndAmount());
885     }
886 
887     // Not allowed in an IT (if then) block.
add_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)888     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
889     {
890         // Rd can only be SP if Rn is also SP.
891         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
892         ASSERT(rd != ARMRegisters::pc);
893         ASSERT(rn != ARMRegisters::pc);
894         ASSERT(imm.isEncodedImm());
895 
896         if (!((rd | rn) & 8)) {
897             if (imm.isUInt3()) {
898                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
899                 return;
900             } else if ((rd == rn) && imm.isUInt8()) {
901                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
902                 return;
903             }
904         }
905 
906         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
907     }
908 
909     // Not allowed in an IT (if then) block?
add_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)910     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
911     {
912         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
913         ASSERT(rd != ARMRegisters::pc);
914         ASSERT(rn != ARMRegisters::pc);
915         ASSERT(!BadReg(rm));
916         m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
917     }
918 
919     // Not allowed in an IT (if then) block.
add_S(RegisterID rd,RegisterID rn,RegisterID rm)920     ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
921     {
922         if (!((rd | rn | rm) & 8))
923             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
924         else
925             add_S(rd, rn, rm, ShiftTypeAndAmount());
926     }
927 
ARM_and(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)928     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
929     {
930         ASSERT(!BadReg(rd));
931         ASSERT(!BadReg(rn));
932         ASSERT(imm.isEncodedImm());
933         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
934     }
935 
ARM_and(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)936     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
937     {
938         ASSERT(!BadReg(rd));
939         ASSERT(!BadReg(rn));
940         ASSERT(!BadReg(rm));
941         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
942     }
943 
ARM_and(RegisterID rd,RegisterID rn,RegisterID rm)944     ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
945     {
946         if ((rd == rn) && !((rd | rm) & 8))
947             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
948         else if ((rd == rm) && !((rd | rn) & 8))
949             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
950         else
951             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
952     }
953 
asr(RegisterID rd,RegisterID rm,int32_t shiftAmount)954     ALWAYS_INLINE void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
955     {
956         ASSERT(!BadReg(rd));
957         ASSERT(!BadReg(rm));
958         ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
959         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
960     }
961 
asr(RegisterID rd,RegisterID rn,RegisterID rm)962     ALWAYS_INLINE void asr(RegisterID rd, RegisterID rn, RegisterID rm)
963     {
964         ASSERT(!BadReg(rd));
965         ASSERT(!BadReg(rn));
966         ASSERT(!BadReg(rm));
967         m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
968     }
969 
970     // Only allowed in IT (if then) block if last instruction.
b()971     ALWAYS_INLINE AssemblerLabel b()
972     {
973         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
974         return m_formatter.label();
975     }
976 
977     // Only allowed in IT (if then) block if last instruction.
blx(RegisterID rm)978     ALWAYS_INLINE AssemblerLabel blx(RegisterID rm)
979     {
980         ASSERT(rm != ARMRegisters::pc);
981         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
982         return m_formatter.label();
983     }
984 
985     // Only allowed in IT (if then) block if last instruction.
bx(RegisterID rm)986     ALWAYS_INLINE AssemblerLabel bx(RegisterID rm)
987     {
988         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
989         return m_formatter.label();
990     }
991 
992     void bkpt(uint8_t imm = 0)
993     {
994         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
995     }
996 
clz(RegisterID rd,RegisterID rm)997     ALWAYS_INLINE void clz(RegisterID rd, RegisterID rm)
998     {
999         ASSERT(!BadReg(rd));
1000         ASSERT(!BadReg(rm));
1001         m_formatter.twoWordOp12Reg4FourFours(OP_CLZ, rm, FourFours(0xf, rd, 8, rm));
1002     }
1003 
cmn(RegisterID rn,ARMThumbImmediate imm)1004     ALWAYS_INLINE void cmn(RegisterID rn, ARMThumbImmediate imm)
1005     {
1006         ASSERT(rn != ARMRegisters::pc);
1007         ASSERT(imm.isEncodedImm());
1008 
1009         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
1010     }
1011 
cmp(RegisterID rn,ARMThumbImmediate imm)1012     ALWAYS_INLINE void cmp(RegisterID rn, ARMThumbImmediate imm)
1013     {
1014         ASSERT(rn != ARMRegisters::pc);
1015         ASSERT(imm.isEncodedImm());
1016 
1017         if (!(rn & 8) && imm.isUInt8())
1018             m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
1019         else
1020             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
1021     }
1022 
cmp(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1023     ALWAYS_INLINE void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1024     {
1025         ASSERT(rn != ARMRegisters::pc);
1026         ASSERT(!BadReg(rm));
1027         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1028     }
1029 
cmp(RegisterID rn,RegisterID rm)1030     ALWAYS_INLINE void cmp(RegisterID rn, RegisterID rm)
1031     {
1032         if ((rn | rm) & 8)
1033             cmp(rn, rm, ShiftTypeAndAmount());
1034         else
1035             m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
1036     }
1037 
1038     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1039     ALWAYS_INLINE void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1040     {
1041         ASSERT(!BadReg(rd));
1042         ASSERT(!BadReg(rn));
1043         ASSERT(imm.isEncodedImm());
1044         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
1045     }
1046 
1047     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1048     ALWAYS_INLINE void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1049     {
1050         ASSERT(!BadReg(rd));
1051         ASSERT(!BadReg(rn));
1052         ASSERT(!BadReg(rm));
1053         m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1054     }
1055 
1056     // xor is not spelled with an 'e'. :-(
eor(RegisterID rd,RegisterID rn,RegisterID rm)1057     void eor(RegisterID rd, RegisterID rn, RegisterID rm)
1058     {
1059         if ((rd == rn) && !((rd | rm) & 8))
1060             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
1061         else if ((rd == rm) && !((rd | rn) & 8))
1062             m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
1063         else
1064             eor(rd, rn, rm, ShiftTypeAndAmount());
1065     }
1066 
it(Condition cond)1067     ALWAYS_INLINE void it(Condition cond)
1068     {
1069         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
1070     }
1071 
it(Condition cond,bool inst2if)1072     ALWAYS_INLINE void it(Condition cond, bool inst2if)
1073     {
1074         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
1075     }
1076 
it(Condition cond,bool inst2if,bool inst3if)1077     ALWAYS_INLINE void it(Condition cond, bool inst2if, bool inst3if)
1078     {
1079         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
1080     }
1081 
it(Condition cond,bool inst2if,bool inst3if,bool inst4if)1082     ALWAYS_INLINE void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
1083     {
1084         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
1085     }
1086 
1087     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
ldr(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1088     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1089     {
1090         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1091         ASSERT(imm.isUInt12());
1092 
1093         if (!((rt | rn) & 8) && imm.isUInt7())
1094             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1095         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1096             m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, static_cast<uint8_t>(imm.getUInt10() >> 2));
1097         else
1098             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
1099     }
1100 
ldrWide8BitImmediate(RegisterID rt,RegisterID rn,uint8_t immediate)1101     ALWAYS_INLINE void ldrWide8BitImmediate(RegisterID rt, RegisterID rn, uint8_t immediate)
1102     {
1103         ASSERT(rn != ARMRegisters::pc);
1104         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, immediate);
1105     }
1106 
ldrCompact(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1107     ALWAYS_INLINE void ldrCompact(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1108     {
1109         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1110         ASSERT(imm.isUInt7());
1111         ASSERT(!((rt | rn) & 8));
1112         m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1113     }
1114 
1115     // If index is set, this is a regular offset or a pre-indexed load;
1116     // if index is not set then is is a post-index load.
1117     //
1118     // If wback is set rn is updated - this is a pre or post index load,
1119     // if wback is not set this is a regular offset memory access.
1120     //
1121     // (-255 <= offset <= 255)
1122     // _reg = REG[rn]
1123     // _tmp = _reg + offset
1124     // MEM[index ? _tmp : _reg] = REG[rt]
1125     // if (wback) REG[rn] = _tmp
ldr(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1126     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1127     {
1128         ASSERT(rt != ARMRegisters::pc);
1129         ASSERT(rn != ARMRegisters::pc);
1130         ASSERT(index || wback);
1131         ASSERT(!wback | (rt != rn));
1132 
1133         bool add = true;
1134         if (offset < 0) {
1135             add = false;
1136             offset = -offset;
1137         }
1138         ASSERT((offset & ~0xff) == 0);
1139 
1140         offset |= (wback << 8);
1141         offset |= (add   << 9);
1142         offset |= (index << 10);
1143         offset |= (1 << 11);
1144 
1145         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
1146     }
1147 
1148     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1149     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1150     {
1151         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1152         ASSERT(!BadReg(rm));
1153         ASSERT(shift <= 3);
1154 
1155         if (!shift && !((rt | rn | rm) & 8))
1156             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
1157         else
1158             m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1159     }
1160 
1161     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
ldrh(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1162     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1163     {
1164         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1165         ASSERT(imm.isUInt12());
1166 
1167         if (!((rt | rn) & 8) && imm.isUInt6())
1168             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
1169         else
1170             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
1171     }
1172 
1173     // If index is set, this is a regular offset or a pre-indexed load;
1174     // if index is not set then is is a post-index load.
1175     //
1176     // If wback is set rn is updated - this is a pre or post index load,
1177     // if wback is not set this is a regular offset memory access.
1178     //
1179     // (-255 <= offset <= 255)
1180     // _reg = REG[rn]
1181     // _tmp = _reg + offset
1182     // MEM[index ? _tmp : _reg] = REG[rt]
1183     // if (wback) REG[rn] = _tmp
ldrh(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1184     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1185     {
1186         ASSERT(rt != ARMRegisters::pc);
1187         ASSERT(rn != ARMRegisters::pc);
1188         ASSERT(index || wback);
1189         ASSERT(!wback | (rt != rn));
1190 
1191         bool add = true;
1192         if (offset < 0) {
1193             add = false;
1194             offset = -offset;
1195         }
1196         ASSERT((offset & ~0xff) == 0);
1197 
1198         offset |= (wback << 8);
1199         offset |= (add   << 9);
1200         offset |= (index << 10);
1201         offset |= (1 << 11);
1202 
1203         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
1204     }
1205 
1206     ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1207     {
1208         ASSERT(!BadReg(rt));   // Memory hint
1209         ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
1210         ASSERT(!BadReg(rm));
1211         ASSERT(shift <= 3);
1212 
1213         if (!shift && !((rt | rn | rm) & 8))
1214             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
1215         else
1216             m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1217     }
1218 
ldrb(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1219     void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1220     {
1221         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1222         ASSERT(imm.isUInt12());
1223 
1224         if (!((rt | rn) & 8) && imm.isUInt5())
1225             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
1226         else
1227             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
1228     }
1229 
ldrb(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1230     void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1231     {
1232         ASSERT(rt != ARMRegisters::pc);
1233         ASSERT(rn != ARMRegisters::pc);
1234         ASSERT(index || wback);
1235         ASSERT(!wback | (rt != rn));
1236 
1237         bool add = true;
1238         if (offset < 0) {
1239             add = false;
1240             offset = -offset;
1241         }
1242 
1243         ASSERT(!(offset & ~0xff));
1244 
1245         offset |= (wback << 8);
1246         offset |= (add   << 9);
1247         offset |= (index << 10);
1248         offset |= (1 << 11);
1249 
1250         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
1251     }
1252 
1253     ALWAYS_INLINE void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1254     {
1255         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1256         ASSERT(!BadReg(rm));
1257         ASSERT(shift <= 3);
1258 
1259         if (!shift && !((rt | rn | rm) & 8))
1260             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
1261         else
1262             m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1263     }
1264 
1265     void ldrsb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1266     {
1267         ASSERT(rn != ARMRegisters::pc);
1268         ASSERT(!BadReg(rm));
1269         ASSERT(shift <= 3);
1270 
1271         if (!shift && !((rt | rn | rm) & 8))
1272             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSB_reg_T1, rm, rn, rt);
1273         else
1274             m_formatter.twoWordOp12Reg4FourFours(OP_LDRSB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1275     }
1276 
1277     void ldrsh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1278     {
1279         ASSERT(rn != ARMRegisters::pc);
1280         ASSERT(!BadReg(rm));
1281         ASSERT(shift <= 3);
1282 
1283         if (!shift && !((rt | rn | rm) & 8))
1284             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSH_reg_T1, rm, rn, rt);
1285         else
1286             m_formatter.twoWordOp12Reg4FourFours(OP_LDRSH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1287     }
1288 
lsl(RegisterID rd,RegisterID rm,int32_t shiftAmount)1289     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1290     {
1291         ASSERT(!BadReg(rd));
1292         ASSERT(!BadReg(rm));
1293         ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
1294         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1295     }
1296 
lsl(RegisterID rd,RegisterID rn,RegisterID rm)1297     ALWAYS_INLINE void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
1298     {
1299         ASSERT(!BadReg(rd));
1300         ASSERT(!BadReg(rn));
1301         ASSERT(!BadReg(rm));
1302         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1303     }
1304 
lsr(RegisterID rd,RegisterID rm,int32_t shiftAmount)1305     ALWAYS_INLINE void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1306     {
1307         ASSERT(!BadReg(rd));
1308         ASSERT(!BadReg(rm));
1309         ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
1310         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1311     }
1312 
lsr(RegisterID rd,RegisterID rn,RegisterID rm)1313     ALWAYS_INLINE void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
1314     {
1315         ASSERT(!BadReg(rd));
1316         ASSERT(!BadReg(rn));
1317         ASSERT(!BadReg(rm));
1318         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1319     }
1320 
movT3(RegisterID rd,ARMThumbImmediate imm)1321     ALWAYS_INLINE void movT3(RegisterID rd, ARMThumbImmediate imm)
1322     {
1323         ASSERT(imm.isValid());
1324         ASSERT(!imm.isEncodedImm());
1325         ASSERT(!BadReg(rd));
1326 
1327         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
1328     }
1329 
1330 #if OS(LINUX) || OS(QNX)
revertJumpTo_movT3movtcmpT2(void * instructionStart,RegisterID left,RegisterID right,uintptr_t imm)1331     static void revertJumpTo_movT3movtcmpT2(void* instructionStart, RegisterID left, RegisterID right, uintptr_t imm)
1332     {
1333         uint16_t* address = static_cast<uint16_t*>(instructionStart);
1334         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(imm));
1335         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(imm >> 16));
1336         address[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
1337         address[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(right, lo16);
1338         address[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
1339         address[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond(right, hi16);
1340         address[4] = OP_CMP_reg_T2 | left;
1341         cacheFlush(address, sizeof(uint16_t) * 5);
1342     }
1343 #else
revertJumpTo_movT3(void * instructionStart,RegisterID rd,ARMThumbImmediate imm)1344     static void revertJumpTo_movT3(void* instructionStart, RegisterID rd, ARMThumbImmediate imm)
1345     {
1346         ASSERT(imm.isValid());
1347         ASSERT(!imm.isEncodedImm());
1348         ASSERT(!BadReg(rd));
1349 
1350         uint16_t* address = static_cast<uint16_t*>(instructionStart);
1351         address[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, imm);
1352         address[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, imm);
1353         cacheFlush(address, sizeof(uint16_t) * 2);
1354     }
1355 #endif
1356 
mov(RegisterID rd,ARMThumbImmediate imm)1357     ALWAYS_INLINE void mov(RegisterID rd, ARMThumbImmediate imm)
1358     {
1359         ASSERT(imm.isValid());
1360         ASSERT(!BadReg(rd));
1361 
1362         if ((rd < 8) && imm.isUInt8())
1363             m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
1364         else if (imm.isEncodedImm())
1365             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
1366         else
1367             movT3(rd, imm);
1368     }
1369 
mov(RegisterID rd,RegisterID rm)1370     ALWAYS_INLINE void mov(RegisterID rd, RegisterID rm)
1371     {
1372         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
1373     }
1374 
movt(RegisterID rd,ARMThumbImmediate imm)1375     ALWAYS_INLINE void movt(RegisterID rd, ARMThumbImmediate imm)
1376     {
1377         ASSERT(imm.isUInt16());
1378         ASSERT(!BadReg(rd));
1379         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
1380     }
1381 
mvn(RegisterID rd,ARMThumbImmediate imm)1382     ALWAYS_INLINE void mvn(RegisterID rd, ARMThumbImmediate imm)
1383     {
1384         ASSERT(imm.isEncodedImm());
1385         ASSERT(!BadReg(rd));
1386 
1387         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
1388     }
1389 
mvn(RegisterID rd,RegisterID rm,ShiftTypeAndAmount shift)1390     ALWAYS_INLINE void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
1391     {
1392         ASSERT(!BadReg(rd));
1393         ASSERT(!BadReg(rm));
1394         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1395     }
1396 
mvn(RegisterID rd,RegisterID rm)1397     ALWAYS_INLINE void mvn(RegisterID rd, RegisterID rm)
1398     {
1399         if (!((rd | rm) & 8))
1400             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
1401         else
1402             mvn(rd, rm, ShiftTypeAndAmount());
1403     }
1404 
neg(RegisterID rd,RegisterID rm)1405     ALWAYS_INLINE void neg(RegisterID rd, RegisterID rm)
1406     {
1407         ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
1408         sub(rd, zero, rm);
1409     }
1410 
orr(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1411     ALWAYS_INLINE void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1412     {
1413         ASSERT(!BadReg(rd));
1414         ASSERT(!BadReg(rn));
1415         ASSERT(imm.isEncodedImm());
1416         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
1417     }
1418 
orr(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1419     ALWAYS_INLINE void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1420     {
1421         ASSERT(!BadReg(rd));
1422         ASSERT(!BadReg(rn));
1423         ASSERT(!BadReg(rm));
1424         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1425     }
1426 
orr(RegisterID rd,RegisterID rn,RegisterID rm)1427     void orr(RegisterID rd, RegisterID rn, RegisterID rm)
1428     {
1429         if ((rd == rn) && !((rd | rm) & 8))
1430             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1431         else if ((rd == rm) && !((rd | rn) & 8))
1432             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1433         else
1434             orr(rd, rn, rm, ShiftTypeAndAmount());
1435     }
1436 
orr_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1437     ALWAYS_INLINE void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1438     {
1439         ASSERT(!BadReg(rd));
1440         ASSERT(!BadReg(rn));
1441         ASSERT(!BadReg(rm));
1442         m_formatter.twoWordOp12Reg4FourFours(OP_ORR_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1443     }
1444 
orr_S(RegisterID rd,RegisterID rn,RegisterID rm)1445     void orr_S(RegisterID rd, RegisterID rn, RegisterID rm)
1446     {
1447         if ((rd == rn) && !((rd | rm) & 8))
1448             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1449         else if ((rd == rm) && !((rd | rn) & 8))
1450             m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1451         else
1452             orr_S(rd, rn, rm, ShiftTypeAndAmount());
1453     }
1454 
ror(RegisterID rd,RegisterID rm,int32_t shiftAmount)1455     ALWAYS_INLINE void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1456     {
1457         ASSERT(!BadReg(rd));
1458         ASSERT(!BadReg(rm));
1459         ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
1460         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1461     }
1462 
ror(RegisterID rd,RegisterID rn,RegisterID rm)1463     ALWAYS_INLINE void ror(RegisterID rd, RegisterID rn, RegisterID rm)
1464     {
1465         ASSERT(!BadReg(rd));
1466         ASSERT(!BadReg(rn));
1467         ASSERT(!BadReg(rm));
1468         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1469     }
1470 
1471 #if CPU(APPLE_ARMV7S)
sdiv(RegisterID rd,RegisterID rn,RegisterID rm)1472     ALWAYS_INLINE void sdiv(RegisterID rd, RegisterID rn, RegisterID rm)
1473     {
1474         ASSERT(!BadReg(rd));
1475         ASSERT(!BadReg(rn));
1476         ASSERT(!BadReg(rm));
1477         m_formatter.twoWordOp12Reg4FourFours(OP_SDIV_T1, rn, FourFours(0xf, rd, 0xf, rm));
1478     }
1479 #endif
1480 
smull(RegisterID rdLo,RegisterID rdHi,RegisterID rn,RegisterID rm)1481     ALWAYS_INLINE void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
1482     {
1483         ASSERT(!BadReg(rdLo));
1484         ASSERT(!BadReg(rdHi));
1485         ASSERT(!BadReg(rn));
1486         ASSERT(!BadReg(rm));
1487         ASSERT(rdLo != rdHi);
1488         m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
1489     }
1490 
1491     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
str(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1492     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1493     {
1494         ASSERT(rt != ARMRegisters::pc);
1495         ASSERT(rn != ARMRegisters::pc);
1496         ASSERT(imm.isUInt12());
1497 
1498         if (!((rt | rn) & 8) && imm.isUInt7())
1499             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1500         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1501             m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, static_cast<uint8_t>(imm.getUInt10() >> 2));
1502         else
1503             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
1504     }
1505 
1506     // If index is set, this is a regular offset or a pre-indexed store;
1507     // if index is not set then is is a post-index store.
1508     //
1509     // If wback is set rn is updated - this is a pre or post index store,
1510     // if wback is not set this is a regular offset memory access.
1511     //
1512     // (-255 <= offset <= 255)
1513     // _reg = REG[rn]
1514     // _tmp = _reg + offset
1515     // MEM[index ? _tmp : _reg] = REG[rt]
1516     // if (wback) REG[rn] = _tmp
str(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1517     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1518     {
1519         ASSERT(rt != ARMRegisters::pc);
1520         ASSERT(rn != ARMRegisters::pc);
1521         ASSERT(index || wback);
1522         ASSERT(!wback | (rt != rn));
1523 
1524         bool add = true;
1525         if (offset < 0) {
1526             add = false;
1527             offset = -offset;
1528         }
1529         ASSERT((offset & ~0xff) == 0);
1530 
1531         offset |= (wback << 8);
1532         offset |= (add   << 9);
1533         offset |= (index << 10);
1534         offset |= (1 << 11);
1535 
1536         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
1537     }
1538 
1539     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1540     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1541     {
1542         ASSERT(rn != ARMRegisters::pc);
1543         ASSERT(!BadReg(rm));
1544         ASSERT(shift <= 3);
1545 
1546         if (!shift && !((rt | rn | rm) & 8))
1547             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
1548         else
1549             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1550     }
1551 
1552     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
strb(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1553     ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1554     {
1555         ASSERT(rt != ARMRegisters::pc);
1556         ASSERT(rn != ARMRegisters::pc);
1557         ASSERT(imm.isUInt12());
1558 
1559         if (!((rt | rn) & 8) && imm.isUInt7())
1560             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STRB_imm_T1, imm.getUInt7() >> 2, rn, rt);
1561         else
1562             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T2, rn, rt, imm.getUInt12());
1563     }
1564 
1565     // If index is set, this is a regular offset or a pre-indexed store;
1566     // if index is not set then is is a post-index store.
1567     //
1568     // If wback is set rn is updated - this is a pre or post index store,
1569     // if wback is not set this is a regular offset memory access.
1570     //
1571     // (-255 <= offset <= 255)
1572     // _reg = REG[rn]
1573     // _tmp = _reg + offset
1574     // MEM[index ? _tmp : _reg] = REG[rt]
1575     // if (wback) REG[rn] = _tmp
strb(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1576     ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1577     {
1578         ASSERT(rt != ARMRegisters::pc);
1579         ASSERT(rn != ARMRegisters::pc);
1580         ASSERT(index || wback);
1581         ASSERT(!wback | (rt != rn));
1582 
1583         bool add = true;
1584         if (offset < 0) {
1585             add = false;
1586             offset = -offset;
1587         }
1588         ASSERT((offset & ~0xff) == 0);
1589 
1590         offset |= (wback << 8);
1591         offset |= (add   << 9);
1592         offset |= (index << 10);
1593         offset |= (1 << 11);
1594 
1595         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T3, rn, rt, offset);
1596     }
1597 
1598     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1599     ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1600     {
1601         ASSERT(rn != ARMRegisters::pc);
1602         ASSERT(!BadReg(rm));
1603         ASSERT(shift <= 3);
1604 
1605         if (!shift && !((rt | rn | rm) & 8))
1606             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STRB_reg_T1, rm, rn, rt);
1607         else
1608             m_formatter.twoWordOp12Reg4FourFours(OP_STRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
1609     }
1610 
1611     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
strh(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1612     ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1613     {
1614         ASSERT(rt != ARMRegisters::pc);
1615         ASSERT(rn != ARMRegisters::pc);
1616         ASSERT(imm.isUInt12());
1617 
1618         if (!((rt | rn) & 8) && imm.isUInt7())
1619             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STRH_imm_T1, imm.getUInt7() >> 2, rn, rt);
1620         else
1621             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRH_imm_T2, rn, rt, imm.getUInt12());
1622     }
1623 
1624     // If index is set, this is a regular offset or a pre-indexed store;
1625     // if index is not set then is is a post-index store.
1626     //
1627     // If wback is set rn is updated - this is a pre or post index store,
1628     // if wback is not set this is a regular offset memory access.
1629     //
1630     // (-255 <= offset <= 255)
1631     // _reg = REG[rn]
1632     // _tmp = _reg + offset
1633     // MEM[index ? _tmp : _reg] = REG[rt]
1634     // if (wback) REG[rn] = _tmp
strh(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1635     ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1636     {
1637         ASSERT(rt != ARMRegisters::pc);
1638         ASSERT(rn != ARMRegisters::pc);
1639         ASSERT(index || wback);
1640         ASSERT(!wback | (rt != rn));
1641 
1642         bool add = true;
1643         if (offset < 0) {
1644             add = false;
1645             offset = -offset;
1646         }
1647         ASSERT(!(offset & ~0xff));
1648 
1649         offset |= (wback << 8);
1650         offset |= (add   << 9);
1651         offset |= (index << 10);
1652         offset |= (1 << 11);
1653 
1654         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRH_imm_T3, rn, rt, offset);
1655     }
1656 
1657     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1658     ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
1659     {
1660         ASSERT(rn != ARMRegisters::pc);
1661         ASSERT(!BadReg(rm));
1662         ASSERT(shift <= 3);
1663 
1664         if (!shift && !((rt | rn | rm) & 8))
1665             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STRH_reg_T1, rm, rn, rt);
1666         else
1667             m_formatter.twoWordOp12Reg4FourFours(OP_STRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1668     }
1669 
sub(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1670     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1671     {
1672         // Rd can only be SP if Rn is also SP.
1673         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1674         ASSERT(rd != ARMRegisters::pc);
1675         ASSERT(rn != ARMRegisters::pc);
1676         ASSERT(imm.isValid());
1677 
1678         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1679             ASSERT(!(imm.getUInt16() & 3));
1680             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
1681             return;
1682         } else if (!((rd | rn) & 8)) {
1683             if (imm.isUInt3()) {
1684                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1685                 return;
1686             } else if ((rd == rn) && imm.isUInt8()) {
1687                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1688                 return;
1689             }
1690         }
1691 
1692         if (imm.isEncodedImm())
1693             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
1694         else {
1695             ASSERT(imm.isUInt12());
1696             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
1697         }
1698     }
1699 
sub(RegisterID rd,ARMThumbImmediate imm,RegisterID rn)1700     ALWAYS_INLINE void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
1701     {
1702         ASSERT(rd != ARMRegisters::pc);
1703         ASSERT(rn != ARMRegisters::pc);
1704         ASSERT(imm.isValid());
1705         ASSERT(imm.isUInt12());
1706 
1707         if (!((rd | rn) & 8) && !imm.getUInt12())
1708             m_formatter.oneWordOp10Reg3Reg3(OP_RSB_imm_T1, rn, rd);
1709         else
1710             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
1711     }
1712 
sub(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1713     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1714     {
1715         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1716         ASSERT(rd != ARMRegisters::pc);
1717         ASSERT(rn != ARMRegisters::pc);
1718         ASSERT(!BadReg(rm));
1719         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1720     }
1721 
1722     // NOTE: In an IT block, add doesn't modify the flags register.
sub(RegisterID rd,RegisterID rn,RegisterID rm)1723     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, RegisterID rm)
1724     {
1725         if (!((rd | rn | rm) & 8))
1726             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1727         else
1728             sub(rd, rn, rm, ShiftTypeAndAmount());
1729     }
1730 
1731     // Not allowed in an IT (if then) block.
sub_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1732     void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1733     {
1734         // Rd can only be SP if Rn is also SP.
1735         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1736         ASSERT(rd != ARMRegisters::pc);
1737         ASSERT(rn != ARMRegisters::pc);
1738         ASSERT(imm.isValid());
1739 
1740         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1741             ASSERT(!(imm.getUInt16() & 3));
1742             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
1743             return;
1744         } else if (!((rd | rn) & 8)) {
1745             if (imm.isUInt3()) {
1746                 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1747                 return;
1748             } else if ((rd == rn) && imm.isUInt8()) {
1749                 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1750                 return;
1751             }
1752         }
1753 
1754         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
1755     }
1756 
sub_S(RegisterID rd,ARMThumbImmediate imm,RegisterID rn)1757     ALWAYS_INLINE void sub_S(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
1758     {
1759         ASSERT(rd != ARMRegisters::pc);
1760         ASSERT(rn != ARMRegisters::pc);
1761         ASSERT(imm.isValid());
1762         ASSERT(imm.isUInt12());
1763 
1764         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_S_imm_T2, rn, rd, imm);
1765     }
1766 
1767     // Not allowed in an IT (if then) block?
sub_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1768     ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1769     {
1770         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1771         ASSERT(rd != ARMRegisters::pc);
1772         ASSERT(rn != ARMRegisters::pc);
1773         ASSERT(!BadReg(rm));
1774         m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1775     }
1776 
1777     // Not allowed in an IT (if then) block.
sub_S(RegisterID rd,RegisterID rn,RegisterID rm)1778     ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
1779     {
1780         if (!((rd | rn | rm) & 8))
1781             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1782         else
1783             sub_S(rd, rn, rm, ShiftTypeAndAmount());
1784     }
1785 
tst(RegisterID rn,ARMThumbImmediate imm)1786     ALWAYS_INLINE void tst(RegisterID rn, ARMThumbImmediate imm)
1787     {
1788         ASSERT(!BadReg(rn));
1789         ASSERT(imm.isEncodedImm());
1790 
1791         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
1792     }
1793 
tst(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1794     ALWAYS_INLINE void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1795     {
1796         ASSERT(!BadReg(rn));
1797         ASSERT(!BadReg(rm));
1798         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1799     }
1800 
tst(RegisterID rn,RegisterID rm)1801     ALWAYS_INLINE void tst(RegisterID rn, RegisterID rm)
1802     {
1803         if ((rn | rm) & 8)
1804             tst(rn, rm, ShiftTypeAndAmount());
1805         else
1806             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
1807     }
1808 
ubfx(RegisterID rd,RegisterID rn,unsigned lsb,unsigned width)1809     ALWAYS_INLINE void ubfx(RegisterID rd, RegisterID rn, unsigned lsb, unsigned width)
1810     {
1811         ASSERT(lsb < 32);
1812         ASSERT((width >= 1) && (width <= 32));
1813         ASSERT((lsb + width) <= 32);
1814         m_formatter.twoWordOp12Reg40Imm3Reg4Imm20Imm5(OP_UBFX_T1, rd, rn, (lsb & 0x1c) << 10, (lsb & 0x3) << 6, (width - 1) & 0x1f);
1815     }
1816 
1817 #if CPU(APPLE_ARMV7S)
udiv(RegisterID rd,RegisterID rn,RegisterID rm)1818     ALWAYS_INLINE void udiv(RegisterID rd, RegisterID rn, RegisterID rm)
1819     {
1820         ASSERT(!BadReg(rd));
1821         ASSERT(!BadReg(rn));
1822         ASSERT(!BadReg(rm));
1823         m_formatter.twoWordOp12Reg4FourFours(OP_UDIV_T1, rn, FourFours(0xf, rd, 0xf, rm));
1824     }
1825 #endif
1826 
vadd(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1827     void vadd(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1828     {
1829         m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
1830     }
1831 
vcmp(FPDoubleRegisterID rd,FPDoubleRegisterID rm)1832     void vcmp(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1833     {
1834         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
1835     }
1836 
vcmpz(FPDoubleRegisterID rd)1837     void vcmpz(FPDoubleRegisterID rd)
1838     {
1839         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
1840     }
1841 
vcvt_signedToFloatingPoint(FPDoubleRegisterID rd,FPSingleRegisterID rm)1842     void vcvt_signedToFloatingPoint(FPDoubleRegisterID rd, FPSingleRegisterID rm)
1843     {
1844         // boolean values are 64bit (toInt, unsigned, roundZero)
1845         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
1846     }
1847 
vcvt_floatingPointToSigned(FPSingleRegisterID rd,FPDoubleRegisterID rm)1848     void vcvt_floatingPointToSigned(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1849     {
1850         // boolean values are 64bit (toInt, unsigned, roundZero)
1851         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
1852     }
1853 
vcvt_unsignedToFloatingPoint(FPDoubleRegisterID rd,FPSingleRegisterID rm)1854     void vcvt_unsignedToFloatingPoint(FPDoubleRegisterID rd, FPSingleRegisterID rm)
1855     {
1856         // boolean values are 64bit (toInt, unsigned, roundZero)
1857         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, true, false), rd, rm);
1858     }
1859 
vcvt_floatingPointToUnsigned(FPSingleRegisterID rd,FPDoubleRegisterID rm)1860     void vcvt_floatingPointToUnsigned(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1861     {
1862         // boolean values are 64bit (toInt, unsigned, roundZero)
1863         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, true, true), rd, rm);
1864     }
1865 
vdiv(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1866     void vdiv(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1867     {
1868         m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
1869     }
1870 
vldr(FPDoubleRegisterID rd,RegisterID rn,int32_t imm)1871     void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1872     {
1873         m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
1874     }
1875 
flds(FPSingleRegisterID rd,RegisterID rn,int32_t imm)1876     void flds(FPSingleRegisterID rd, RegisterID rn, int32_t imm)
1877     {
1878         m_formatter.vfpMemOp(OP_FLDS, OP_FLDSb, false, rn, rd, imm);
1879     }
1880 
vmov(RegisterID rd,FPSingleRegisterID rn)1881     void vmov(RegisterID rd, FPSingleRegisterID rn)
1882     {
1883         ASSERT(!BadReg(rd));
1884         m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rn, rd, VFPOperand(0));
1885     }
1886 
vmov(FPSingleRegisterID rd,RegisterID rn)1887     void vmov(FPSingleRegisterID rd, RegisterID rn)
1888     {
1889         ASSERT(!BadReg(rn));
1890         m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rd, rn, VFPOperand(0));
1891     }
1892 
vmov(RegisterID rd1,RegisterID rd2,FPDoubleRegisterID rn)1893     void vmov(RegisterID rd1, RegisterID rd2, FPDoubleRegisterID rn)
1894     {
1895         ASSERT(!BadReg(rd1));
1896         ASSERT(!BadReg(rd2));
1897         m_formatter.vfpOp(OP_VMOV_DtoC, OP_VMOV_DtoCb, true, rd2, VFPOperand(rd1 | 16), rn);
1898     }
1899 
vmov(FPDoubleRegisterID rd,RegisterID rn1,RegisterID rn2)1900     void vmov(FPDoubleRegisterID rd, RegisterID rn1, RegisterID rn2)
1901     {
1902         ASSERT(!BadReg(rn1));
1903         ASSERT(!BadReg(rn2));
1904         m_formatter.vfpOp(OP_VMOV_CtoD, OP_VMOV_CtoDb, true, rn2, VFPOperand(rn1 | 16), rd);
1905     }
1906 
vmov(FPDoubleRegisterID rd,FPDoubleRegisterID rn)1907     void vmov(FPDoubleRegisterID rd, FPDoubleRegisterID rn)
1908     {
1909         m_formatter.vfpOp(OP_VMOV_T2, OP_VMOV_T2b, true, VFPOperand(0), rd, rn);
1910     }
1911 
1912     void vmrs(RegisterID reg = ARMRegisters::pc)
1913     {
1914         ASSERT(reg != ARMRegisters::sp);
1915         m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
1916     }
1917 
vmul(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1918     void vmul(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1919     {
1920         m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
1921     }
1922 
vstr(FPDoubleRegisterID rd,RegisterID rn,int32_t imm)1923     void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm)
1924     {
1925         m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
1926     }
1927 
fsts(FPSingleRegisterID rd,RegisterID rn,int32_t imm)1928     void fsts(FPSingleRegisterID rd, RegisterID rn, int32_t imm)
1929     {
1930         m_formatter.vfpMemOp(OP_FSTS, OP_FSTSb, false, rn, rd, imm);
1931     }
1932 
vsub(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1933     void vsub(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
1934     {
1935         m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
1936     }
1937 
vabs(FPDoubleRegisterID rd,FPDoubleRegisterID rm)1938     void vabs(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1939     {
1940         m_formatter.vfpOp(OP_VABS_T2, OP_VABS_T2b, true, VFPOperand(16), rd, rm);
1941     }
1942 
vneg(FPDoubleRegisterID rd,FPDoubleRegisterID rm)1943     void vneg(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1944     {
1945         m_formatter.vfpOp(OP_VNEG_T2, OP_VNEG_T2b, true, VFPOperand(1), rd, rm);
1946     }
1947 
vsqrt(FPDoubleRegisterID rd,FPDoubleRegisterID rm)1948     void vsqrt(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
1949     {
1950         m_formatter.vfpOp(OP_VSQRT_T1, OP_VSQRT_T1b, true, VFPOperand(17), rd, rm);
1951     }
1952 
vcvtds(FPDoubleRegisterID rd,FPSingleRegisterID rm)1953     void vcvtds(FPDoubleRegisterID rd, FPSingleRegisterID rm)
1954     {
1955         m_formatter.vfpOp(OP_VCVTDS_T1, OP_VCVTDS_T1b, false, VFPOperand(23), rd, rm);
1956     }
1957 
vcvtsd(FPSingleRegisterID rd,FPDoubleRegisterID rm)1958     void vcvtsd(FPSingleRegisterID rd, FPDoubleRegisterID rm)
1959     {
1960         m_formatter.vfpOp(OP_VCVTSD_T1, OP_VCVTSD_T1b, true, VFPOperand(23), rd, rm);
1961     }
1962 
nop()1963     void nop()
1964     {
1965         m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0);
1966     }
1967 
nopw()1968     void nopw()
1969     {
1970         m_formatter.twoWordOp16Op16(OP_NOP_T2a, OP_NOP_T2b);
1971     }
1972 
labelIgnoringWatchpoints()1973     AssemblerLabel labelIgnoringWatchpoints()
1974     {
1975         return m_formatter.label();
1976     }
1977 
labelForWatchpoint()1978     AssemblerLabel labelForWatchpoint()
1979     {
1980         AssemblerLabel result = m_formatter.label();
1981         if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint)
1982             result = label();
1983         m_indexOfLastWatchpoint = result.m_offset;
1984         m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize();
1985         return result;
1986     }
1987 
label()1988     AssemblerLabel label()
1989     {
1990         AssemblerLabel result = m_formatter.label();
1991         while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) {
1992             if (UNLIKELY(static_cast<int>(result.m_offset) + 4 <= m_indexOfTailOfLastWatchpoint))
1993                 nopw();
1994             else
1995                 nop();
1996             result = m_formatter.label();
1997         }
1998         return result;
1999     }
2000 
align(int alignment)2001     AssemblerLabel align(int alignment)
2002     {
2003         while (!m_formatter.isAligned(alignment))
2004             bkpt();
2005 
2006         return label();
2007     }
2008 
getRelocatedAddress(void * code,AssemblerLabel label)2009     static void* getRelocatedAddress(void* code, AssemblerLabel label)
2010     {
2011         ASSERT(label.isSet());
2012         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + label.m_offset);
2013     }
2014 
getDifferenceBetweenLabels(AssemblerLabel a,AssemblerLabel b)2015     static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
2016     {
2017         return b.m_offset - a.m_offset;
2018     }
2019 
executableOffsetFor(int location)2020     int executableOffsetFor(int location)
2021     {
2022         if (!location)
2023             return 0;
2024         return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1];
2025     }
2026 
jumpSizeDelta(JumpType jumpType,JumpLinkType jumpLinkType)2027     int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JUMP_ENUM_SIZE(jumpType) - JUMP_ENUM_SIZE(jumpLinkType); }
2028 
2029     // Assembler admin methods:
2030 
linkRecordSourceComparator(const LinkRecord & a,const LinkRecord & b)2031     static ALWAYS_INLINE bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
2032     {
2033         return a.from() < b.from();
2034     }
2035 
canCompact(JumpType jumpType)2036     bool canCompact(JumpType jumpType)
2037     {
2038         // The following cannot be compacted:
2039         //   JumpFixed: represents custom jump sequence
2040         //   JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size
2041         //   JumpConditionFixedSize: represents conditional jump that must remain a fixed size
2042         return (jumpType == JumpNoCondition) || (jumpType == JumpCondition);
2043     }
2044 
computeJumpType(JumpType jumpType,const uint8_t * from,const uint8_t * to)2045     JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
2046     {
2047         if (jumpType == JumpFixed)
2048             return LinkInvalid;
2049 
2050         // for patchable jump we must leave space for the longest code sequence
2051         if (jumpType == JumpNoConditionFixedSize)
2052             return LinkBX;
2053         if (jumpType == JumpConditionFixedSize)
2054             return LinkConditionalBX;
2055 
2056         const int paddingSize = JUMP_ENUM_SIZE(jumpType);
2057 
2058         if (jumpType == JumpCondition) {
2059             // 2-byte conditional T1
2060             const uint16_t* jumpT1Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1)));
2061             if (canBeJumpT1(jumpT1Location, to))
2062                 return LinkJumpT1;
2063             // 4-byte conditional T3
2064             const uint16_t* jumpT3Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3)));
2065             if (canBeJumpT3(jumpT3Location, to))
2066                 return LinkJumpT3;
2067             // 4-byte conditional T4 with IT
2068             const uint16_t* conditionalJumpT4Location =
2069             reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4)));
2070             if (canBeJumpT4(conditionalJumpT4Location, to))
2071                 return LinkConditionalJumpT4;
2072         } else {
2073             // 2-byte unconditional T2
2074             const uint16_t* jumpT2Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2)));
2075             if (canBeJumpT2(jumpT2Location, to))
2076                 return LinkJumpT2;
2077             // 4-byte unconditional T4
2078             const uint16_t* jumpT4Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4)));
2079             if (canBeJumpT4(jumpT4Location, to))
2080                 return LinkJumpT4;
2081             // use long jump sequence
2082             return LinkBX;
2083         }
2084 
2085         ASSERT(jumpType == JumpCondition);
2086         return LinkConditionalBX;
2087     }
2088 
computeJumpType(LinkRecord & record,const uint8_t * from,const uint8_t * to)2089     JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
2090     {
2091         JumpLinkType linkType = computeJumpType(record.type(), from, to);
2092         record.setLinkType(linkType);
2093         return linkType;
2094     }
2095 
recordLinkOffsets(int32_t regionStart,int32_t regionEnd,int32_t offset)2096     void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
2097     {
2098         int32_t ptr = regionStart / sizeof(int32_t);
2099         const int32_t end = regionEnd / sizeof(int32_t);
2100         int32_t* offsets = static_cast<int32_t*>(m_formatter.data());
2101         while (ptr < end)
2102             offsets[ptr++] = offset;
2103     }
2104 
jumpsToLink()2105     Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink()
2106     {
2107         std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
2108         return m_jumpsToLink;
2109     }
2110 
link(LinkRecord & record,uint8_t * from,uint8_t * to)2111     void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to)
2112     {
2113         switch (record.linkType()) {
2114         case LinkJumpT1:
2115             linkJumpT1(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to);
2116             break;
2117         case LinkJumpT2:
2118             linkJumpT2(reinterpret_cast_ptr<uint16_t*>(from), to);
2119             break;
2120         case LinkJumpT3:
2121             linkJumpT3(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to);
2122             break;
2123         case LinkJumpT4:
2124             linkJumpT4(reinterpret_cast_ptr<uint16_t*>(from), to);
2125             break;
2126         case LinkConditionalJumpT4:
2127             linkConditionalJumpT4(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to);
2128             break;
2129         case LinkConditionalBX:
2130             linkConditionalBX(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to);
2131             break;
2132         case LinkBX:
2133             linkBX(reinterpret_cast_ptr<uint16_t*>(from), to);
2134             break;
2135         default:
2136             RELEASE_ASSERT_NOT_REACHED();
2137             break;
2138         }
2139     }
2140 
unlinkedCode()2141     void* unlinkedCode() { return m_formatter.data(); }
codeSize()2142     size_t codeSize() const { return m_formatter.codeSize(); }
2143 
getCallReturnOffset(AssemblerLabel call)2144     static unsigned getCallReturnOffset(AssemblerLabel call)
2145     {
2146         ASSERT(call.isSet());
2147         return call.m_offset;
2148     }
2149 
2150     // Linking & patching:
2151     //
2152     // 'link' and 'patch' methods are for use on unprotected code - such as the code
2153     // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
2154     // code has been finalized it is (platform support permitting) within a non-
2155     // writable region of memory; to modify the code in an execute-only execuable
2156     // pool the 'repatch' and 'relink' methods should be used.
2157 
linkJump(AssemblerLabel from,AssemblerLabel to,JumpType type,Condition condition)2158     void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type, Condition condition)
2159     {
2160         ASSERT(to.isSet());
2161         ASSERT(from.isSet());
2162         m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, type, condition));
2163     }
2164 
linkJump(void * code,AssemblerLabel from,void * to)2165     static void linkJump(void* code, AssemblerLabel from, void* to)
2166     {
2167         ASSERT(from.isSet());
2168 
2169         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
2170         linkJumpAbsolute(location, to);
2171     }
2172 
linkCall(void * code,AssemblerLabel from,void * to)2173     static void linkCall(void* code, AssemblerLabel from, void* to)
2174     {
2175         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
2176         ASSERT(from.isSet());
2177         ASSERT_VALID_CODE_POINTER(to);
2178 
2179         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to, false);
2180     }
2181 
linkPointer(void * code,AssemblerLabel where,void * value)2182     static void linkPointer(void* code, AssemblerLabel where, void* value)
2183     {
2184         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value, false);
2185     }
2186 
relinkJump(void * from,void * to)2187     static void relinkJump(void* from, void* to)
2188     {
2189         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
2190         ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
2191 
2192         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
2193 
2194         cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
2195     }
2196 
relinkCall(void * from,void * to)2197     static void relinkCall(void* from, void* to)
2198     {
2199         ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
2200         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
2201 
2202         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to, true);
2203     }
2204 
readCallTarget(void * from)2205     static void* readCallTarget(void* from)
2206     {
2207         return readPointer(reinterpret_cast<uint16_t*>(from) - 1);
2208     }
2209 
repatchInt32(void * where,int32_t value)2210     static void repatchInt32(void* where, int32_t value)
2211     {
2212         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
2213 
2214         setInt32(where, value, true);
2215     }
2216 
repatchCompact(void * where,int32_t offset)2217     static void repatchCompact(void* where, int32_t offset)
2218     {
2219         ASSERT(offset >= -255 && offset <= 255);
2220 
2221         bool add = true;
2222         if (offset < 0) {
2223             add = false;
2224             offset = -offset;
2225         }
2226 
2227         offset |= (add << 9);
2228         offset |= (1 << 10);
2229         offset |= (1 << 11);
2230 
2231         uint16_t* location = reinterpret_cast<uint16_t*>(where);
2232         location[1] &= ~((1 << 12) - 1);
2233         location[1] |= offset;
2234         cacheFlush(location, sizeof(uint16_t) * 2);
2235     }
2236 
repatchPointer(void * where,void * value)2237     static void repatchPointer(void* where, void* value)
2238     {
2239         ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
2240 
2241         setPointer(where, value, true);
2242     }
2243 
readPointer(void * where)2244     static void* readPointer(void* where)
2245     {
2246         return reinterpret_cast<void*>(readInt32(where));
2247     }
2248 
replaceWithJump(void * instructionStart,void * to)2249     static void replaceWithJump(void* instructionStart, void* to)
2250     {
2251         ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));
2252         ASSERT(!(bitwise_cast<uintptr_t>(to) & 1));
2253 
2254 #if OS(LINUX) || OS(QNX)
2255         if (canBeJumpT4(reinterpret_cast<uint16_t*>(instructionStart), to)) {
2256             uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2;
2257             linkJumpT4(ptr, to);
2258             cacheFlush(ptr - 2, sizeof(uint16_t) * 2);
2259         } else {
2260             uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 5;
2261             linkBX(ptr, to);
2262             cacheFlush(ptr - 5, sizeof(uint16_t) * 5);
2263         }
2264 #else
2265         uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2;
2266         linkJumpT4(ptr, to);
2267         cacheFlush(ptr - 2, sizeof(uint16_t) * 2);
2268 #endif
2269     }
2270 
maxJumpReplacementSize()2271     static ptrdiff_t maxJumpReplacementSize()
2272     {
2273 #if OS(LINUX) || OS(QNX)
2274         return 10;
2275 #else
2276         return 4;
2277 #endif
2278     }
2279 
replaceWithLoad(void * instructionStart)2280     static void replaceWithLoad(void* instructionStart)
2281     {
2282         ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));
2283         uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart);
2284         switch (ptr[0] & 0xFFF0) {
2285         case OP_LDR_imm_T3:
2286             break;
2287         case OP_ADD_imm_T3:
2288             ASSERT(!(ptr[1] & 0xF000));
2289             ptr[0] &= 0x000F;
2290             ptr[0] |= OP_LDR_imm_T3;
2291             ptr[1] |= (ptr[1] & 0x0F00) << 4;
2292             ptr[1] &= 0xF0FF;
2293             cacheFlush(ptr, sizeof(uint16_t) * 2);
2294             break;
2295         default:
2296             RELEASE_ASSERT_NOT_REACHED();
2297         }
2298     }
2299 
replaceWithAddressComputation(void * instructionStart)2300     static void replaceWithAddressComputation(void* instructionStart)
2301     {
2302         ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));
2303         uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart);
2304         switch (ptr[0] & 0xFFF0) {
2305         case OP_LDR_imm_T3:
2306             ASSERT(!(ptr[1] & 0x0F00));
2307             ptr[0] &= 0x000F;
2308             ptr[0] |= OP_ADD_imm_T3;
2309             ptr[1] |= (ptr[1] & 0xF000) >> 4;
2310             ptr[1] &= 0x0FFF;
2311             cacheFlush(ptr, sizeof(uint16_t) * 2);
2312             break;
2313         case OP_ADD_imm_T3:
2314             break;
2315         default:
2316             RELEASE_ASSERT_NOT_REACHED();
2317         }
2318     }
2319 
debugOffset()2320     unsigned debugOffset() { return m_formatter.debugOffset(); }
2321 
2322 #if OS(LINUX)
linuxPageFlush(uintptr_t begin,uintptr_t end)2323     static inline void linuxPageFlush(uintptr_t begin, uintptr_t end)
2324     {
2325         asm volatile(
2326             "push    {r7}\n"
2327             "mov     r0, %0\n"
2328             "mov     r1, %1\n"
2329             "movw    r7, #0x2\n"
2330             "movt    r7, #0xf\n"
2331             "movs    r2, #0x0\n"
2332             "svc     0x0\n"
2333             "pop     {r7}\n"
2334             :
2335             : "r" (begin), "r" (end)
2336             : "r0", "r1", "r2");
2337     }
2338 #endif
2339 
cacheFlush(void * code,size_t size)2340     static void cacheFlush(void* code, size_t size)
2341     {
2342 #if OS(IOS)
2343         sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
2344 #elif OS(LINUX)
2345         size_t page = pageSize();
2346         uintptr_t current = reinterpret_cast<uintptr_t>(code);
2347         uintptr_t end = current + size;
2348         uintptr_t firstPageEnd = (current & ~(page - 1)) + page;
2349 
2350         if (end <= firstPageEnd) {
2351             linuxPageFlush(current, end);
2352             return;
2353         }
2354 
2355         linuxPageFlush(current, firstPageEnd);
2356 
2357         for (current = firstPageEnd; current + page < end; current += page)
2358             linuxPageFlush(current, current + page);
2359 
2360         linuxPageFlush(current, end);
2361 #elif OS(WINCE)
2362         CacheRangeFlush(code, size, CACHE_SYNC_ALL);
2363 #elif OS(QNX)
2364 #if !ENABLE(ASSEMBLER_WX_EXCLUSIVE)
2365         msync(code, size, MS_INVALIDATE_ICACHE);
2366 #elif OS(RTEMS)
2367         rtems_cache_flush_multiple_data_lines(code, size);
2368 #else
2369         UNUSED_PARAM(code);
2370         UNUSED_PARAM(size);
2371 #endif
2372 #elif OS(FREEBSD) && COMPILER(CLANG)
2373 	__clear_cache(code, reinterpret_cast<char*>(code) + size);
2374 #else
2375 #error "The cacheFlush support is missing on this platform."
2376 #endif
2377     }
2378 
2379 private:
2380     // VFP operations commonly take one or more 5-bit operands, typically representing a
2381     // floating point register number.  This will commonly be encoded in the instruction
2382     // in two parts, with one single bit field, and one 4-bit field.  In the case of
2383     // double precision operands the high bit of the register number will be encoded
2384     // separately, and for single precision operands the high bit of the register number
2385     // will be encoded individually.
2386     // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit
2387     // field to be encoded together in the instruction (the low 4-bits of a double
2388     // register number, or the high 4-bits of a single register number), and bit 4
2389     // contains the bit value to be encoded individually.
2390     struct VFPOperand {
VFPOperandVFPOperand2391         explicit VFPOperand(uint32_t value)
2392             : m_value(value)
2393         {
2394             ASSERT(!(m_value & ~0x1f));
2395         }
2396 
VFPOperandVFPOperand2397         VFPOperand(FPDoubleRegisterID reg)
2398             : m_value(reg)
2399         {
2400         }
2401 
VFPOperandVFPOperand2402         VFPOperand(RegisterID reg)
2403             : m_value(reg)
2404         {
2405         }
2406 
VFPOperandVFPOperand2407         VFPOperand(FPSingleRegisterID reg)
2408             : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top.
2409         {
2410         }
2411 
bits1VFPOperand2412         uint32_t bits1()
2413         {
2414             return m_value >> 4;
2415         }
2416 
bits4VFPOperand2417         uint32_t bits4()
2418         {
2419             return m_value & 0xf;
2420         }
2421 
2422         uint32_t m_value;
2423     };
2424 
vcvtOp(bool toInteger,bool isUnsigned,bool isRoundZero)2425     VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero)
2426     {
2427         // Cannot specify rounding when converting to float.
2428         ASSERT(toInteger || !isRoundZero);
2429 
2430         uint32_t op = 0x8;
2431         if (toInteger) {
2432             // opc2 indicates both toInteger & isUnsigned.
2433             op |= isUnsigned ? 0x4 : 0x5;
2434             // 'op' field in instruction is isRoundZero
2435             if (isRoundZero)
2436                 op |= 0x10;
2437         } else {
2438             ASSERT(!isRoundZero);
2439             // 'op' field in instruction is isUnsigned
2440             if (!isUnsigned)
2441                 op |= 0x10;
2442         }
2443         return VFPOperand(op);
2444     }
2445 
setInt32(void * code,uint32_t value,bool flush)2446     static void setInt32(void* code, uint32_t value, bool flush)
2447     {
2448         uint16_t* location = reinterpret_cast<uint16_t*>(code);
2449         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
2450 
2451         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value));
2452         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16));
2453         location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2454         location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16);
2455         location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2456         location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
2457 
2458         if (flush)
2459             cacheFlush(location - 4, 4 * sizeof(uint16_t));
2460     }
2461 
readInt32(void * code)2462     static int32_t readInt32(void* code)
2463     {
2464         uint16_t* location = reinterpret_cast<uint16_t*>(code);
2465         ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
2466 
2467         ARMThumbImmediate lo16;
2468         ARMThumbImmediate hi16;
2469         decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(lo16, location[-4]);
2470         decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(lo16, location[-3]);
2471         decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(hi16, location[-2]);
2472         decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(hi16, location[-1]);
2473         uint32_t result = hi16.asUInt16();
2474         result <<= 16;
2475         result |= lo16.asUInt16();
2476         return static_cast<int32_t>(result);
2477     }
2478 
setUInt7ForLoad(void * code,ARMThumbImmediate imm)2479     static void setUInt7ForLoad(void* code, ARMThumbImmediate imm)
2480     {
2481         // Requires us to have planted a LDR_imm_T1
2482         ASSERT(imm.isValid());
2483         ASSERT(imm.isUInt7());
2484         uint16_t* location = reinterpret_cast<uint16_t*>(code);
2485         location[0] &= ~((static_cast<uint16_t>(0x7f) >> 2) << 6);
2486         location[0] |= (imm.getUInt7() >> 2) << 6;
2487         cacheFlush(location, sizeof(uint16_t));
2488     }
2489 
setPointer(void * code,void * value,bool flush)2490     static void setPointer(void* code, void* value, bool flush)
2491     {
2492         // ### Deliberate "loss" of precision here. On 64-bit hosts void* is wider
2493         // than uint32_t, but the target is 32-bit ARM anyway.
2494         setInt32(code, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(value)), flush);
2495     }
2496 
isB(void * address)2497     static bool isB(void* address)
2498     {
2499         uint16_t* instruction = static_cast<uint16_t*>(address);
2500         return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b);
2501     }
2502 
isBX(void * address)2503     static bool isBX(void* address)
2504     {
2505         uint16_t* instruction = static_cast<uint16_t*>(address);
2506         return (instruction[0] & 0xff87) == OP_BX;
2507     }
2508 
isMOV_imm_T3(void * address)2509     static bool isMOV_imm_T3(void* address)
2510     {
2511         uint16_t* instruction = static_cast<uint16_t*>(address);
2512         return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0);
2513     }
2514 
isMOVT(void * address)2515     static bool isMOVT(void* address)
2516     {
2517         uint16_t* instruction = static_cast<uint16_t*>(address);
2518         return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0);
2519     }
2520 
isNOP_T1(void * address)2521     static bool isNOP_T1(void* address)
2522     {
2523         uint16_t* instruction = static_cast<uint16_t*>(address);
2524         return instruction[0] == OP_NOP_T1;
2525     }
2526 
isNOP_T2(void * address)2527     static bool isNOP_T2(void* address)
2528     {
2529         uint16_t* instruction = static_cast<uint16_t*>(address);
2530         return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b);
2531     }
2532 
makeRelative(const void * target,const void * source)2533     static int32_t makeRelative(const void *target, const void *source)
2534     {
2535         intptr_t difference = reinterpret_cast<intptr_t>(target) - reinterpret_cast<intptr_t>(source);
2536         return static_cast<int32_t>(difference);
2537     }
2538 
canBeJumpT1(const uint16_t * instruction,const void * target)2539     static bool canBeJumpT1(const uint16_t* instruction, const void* target)
2540     {
2541         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2542         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2543 
2544         auto relative = makeRelative(target, instruction);
2545         // It does not appear to be documented in the ARM ARM (big surprise), but
2546         // for OP_B_T1 the branch displacement encoded in the instruction is 2
2547         // less than the actual displacement.
2548         relative -= 2;
2549         return ((relative << 23) >> 23) == relative;
2550     }
2551 
canBeJumpT2(const uint16_t * instruction,const void * target)2552     static bool canBeJumpT2(const uint16_t* instruction, const void* target)
2553     {
2554         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2555         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2556 
2557         auto relative = makeRelative(target, instruction);
2558         // It does not appear to be documented in the ARM ARM (big surprise), but
2559         // for OP_B_T2 the branch displacement encoded in the instruction is 2
2560         // less than the actual displacement.
2561         relative -= 2;
2562         return ((relative << 20) >> 20) == relative;
2563     }
2564 
canBeJumpT3(const uint16_t * instruction,const void * target)2565     static bool canBeJumpT3(const uint16_t* instruction, const void* target)
2566     {
2567         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2568         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2569 
2570         auto relative = makeRelative(target, instruction);
2571         return ((relative << 11) >> 11) == relative;
2572     }
2573 
canBeJumpT4(const uint16_t * instruction,const void * target)2574     static bool canBeJumpT4(const uint16_t* instruction, const void* target)
2575     {
2576         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2577         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2578 
2579         auto relative = makeRelative(target, instruction);
2580         return ((relative << 7) >> 7) == relative;
2581     }
2582 
linkJumpT1(Condition cond,uint16_t * instruction,void * target)2583     void linkJumpT1(Condition cond, uint16_t* instruction, void* target)
2584     {
2585         // FIMXE: this should be up in the MacroAssembler layer. :-(
2586         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2587         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2588         ASSERT(canBeJumpT1(instruction, target));
2589 
2590         auto relative = makeRelative(target, instruction);
2591         // It does not appear to be documented in the ARM ARM (big surprise), but
2592         // for OP_B_T1 the branch displacement encoded in the instruction is 2
2593         // less than the actual displacement.
2594         relative -= 2;
2595 
2596         // All branch offsets should be an even distance.
2597         ASSERT(!(relative & 1));
2598         instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1);
2599     }
2600 
linkJumpT2(uint16_t * instruction,void * target)2601     static void linkJumpT2(uint16_t* instruction, void* target)
2602     {
2603         // FIMXE: this should be up in the MacroAssembler layer. :-(
2604         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2605         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2606         ASSERT(canBeJumpT2(instruction, target));
2607 
2608         auto relative = makeRelative(target, instruction);
2609         // It does not appear to be documented in the ARM ARM (big surprise), but
2610         // for OP_B_T2 the branch displacement encoded in the instruction is 2
2611         // less than the actual displacement.
2612         relative -= 2;
2613 
2614         // All branch offsets should be an even distance.
2615         ASSERT(!(relative & 1));
2616         instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1);
2617     }
2618 
linkJumpT3(Condition cond,uint16_t * instruction,void * target)2619     void linkJumpT3(Condition cond, uint16_t* instruction, void* target)
2620     {
2621         // FIMXE: this should be up in the MacroAssembler layer. :-(
2622         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2623         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2624         ASSERT(canBeJumpT3(instruction, target));
2625 
2626         auto relative = makeRelative(target, instruction);
2627 
2628         // All branch offsets should be an even distance.
2629         ASSERT(!(relative & 1));
2630         instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12);
2631         instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1);
2632     }
2633 
linkJumpT4(uint16_t * instruction,void * target)2634     static void linkJumpT4(uint16_t* instruction, void* target)
2635     {
2636         // FIMXE: this should be up in the MacroAssembler layer. :-(
2637         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2638         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2639         ASSERT(canBeJumpT4(instruction, target));
2640 
2641         auto relative = makeRelative(target, instruction);
2642         // ARM encoding for the top two bits below the sign bit is 'peculiar'.
2643         if (relative >= 0)
2644             relative ^= 0xC00000;
2645 
2646         // All branch offsets should be an even distance.
2647         ASSERT(!(relative & 1));
2648         instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
2649         instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
2650     }
2651 
linkConditionalJumpT4(Condition cond,uint16_t * instruction,void * target)2652     void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target)
2653     {
2654         // FIMXE: this should be up in the MacroAssembler layer. :-(
2655         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2656         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2657 
2658         instruction[-3] = ifThenElse(cond) | OP_IT;
2659         linkJumpT4(instruction, target);
2660     }
2661 
linkBX(uint16_t * instruction,void * target)2662     static void linkBX(uint16_t* instruction, void* target)
2663     {
2664         // FIMXE: this should be up in the MacroAssembler layer. :-(
2665         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2666         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2667 
2668         const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2669         ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2670         ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2671         instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2672         instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2673         instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2674         instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2675         instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2676     }
2677 
linkConditionalBX(Condition cond,uint16_t * instruction,void * target)2678     void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
2679     {
2680         // FIMXE: this should be up in the MacroAssembler layer. :-(
2681         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2682         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2683 
2684         linkBX(instruction, target);
2685         instruction[-6] = ifThenElse(cond, true, true) | OP_IT;
2686     }
2687 
linkJumpAbsolute(uint16_t * instruction,void * target)2688     static void linkJumpAbsolute(uint16_t* instruction, void* target)
2689     {
2690         // FIMXE: this should be up in the MacroAssembler layer. :-(
2691         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
2692         ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
2693 
2694         ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
2695                || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
2696 
2697         if (canBeJumpT4(instruction, target)) {
2698             // There may be a better way to fix this, but right now put the NOPs first, since in the
2699             // case of an conditional branch this will be coming after an ITTT predicating *three*
2700             // instructions!  Looking backwards to modify the ITTT to an IT is not easy, due to
2701             // variable wdith encoding - the previous instruction might *look* like an ITTT but
2702             // actually be the second half of a 2-word op.
2703             instruction[-5] = OP_NOP_T1;
2704             instruction[-4] = OP_NOP_T2a;
2705             instruction[-3] = OP_NOP_T2b;
2706             linkJumpT4(instruction, target);
2707         } else {
2708             const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
2709             ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
2710             ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
2711             instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
2712             instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
2713             instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
2714             instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
2715             instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
2716         }
2717     }
2718 
twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op,ARMThumbImmediate imm)2719     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
2720     {
2721         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
2722     }
2723 
decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(ARMThumbImmediate & result,uint16_t value)2724     static void decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(ARMThumbImmediate& result, uint16_t value)
2725     {
2726         result.m_value.i = (value >> 10) & 1;
2727         result.m_value.imm4 = value & 15;
2728     }
2729 
twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd,ARMThumbImmediate imm)2730     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
2731     {
2732         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
2733     }
2734 
decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(ARMThumbImmediate & result,uint16_t value)2735     static void decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(ARMThumbImmediate& result, uint16_t value)
2736     {
2737         result.m_value.imm3 = (value >> 12) & 7;
2738         result.m_value.imm8 = value & 255;
2739     }
2740 
2741     class ARMInstructionFormatter {
2742     public:
oneWordOp5Reg3Imm8(OpcodeID op,RegisterID rd,uint8_t imm)2743         ALWAYS_INLINE void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
2744         {
2745             m_buffer.putShort(op | (rd << 8) | imm);
2746         }
2747 
oneWordOp5Imm5Reg3Reg3(OpcodeID op,uint8_t imm,RegisterID reg1,RegisterID reg2)2748         ALWAYS_INLINE void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
2749         {
2750             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
2751         }
2752 
oneWordOp7Reg3Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2,RegisterID reg3)2753         ALWAYS_INLINE void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
2754         {
2755             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
2756         }
2757 
oneWordOp8Imm8(OpcodeID op,uint8_t imm)2758         ALWAYS_INLINE void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
2759         {
2760             m_buffer.putShort(op | imm);
2761         }
2762 
oneWordOp8RegReg143(OpcodeID op,RegisterID reg1,RegisterID reg2)2763         ALWAYS_INLINE void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
2764         {
2765             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
2766         }
2767 
oneWordOp9Imm7(OpcodeID op,uint8_t imm)2768         ALWAYS_INLINE void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
2769         {
2770             m_buffer.putShort(op | imm);
2771         }
2772 
oneWordOp10Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2)2773         ALWAYS_INLINE void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
2774         {
2775             m_buffer.putShort(op | (reg1 << 3) | reg2);
2776         }
2777 
twoWordOp12Reg4FourFours(OpcodeID1 op,RegisterID reg,FourFours ff)2778         ALWAYS_INLINE void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
2779         {
2780             m_buffer.putShort(op | reg);
2781             m_buffer.putShort(ff.m_u.value);
2782         }
2783 
twoWordOp16FourFours(OpcodeID1 op,FourFours ff)2784         ALWAYS_INLINE void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
2785         {
2786             m_buffer.putShort(op);
2787             m_buffer.putShort(ff.m_u.value);
2788         }
2789 
twoWordOp16Op16(OpcodeID1 op1,OpcodeID2 op2)2790         ALWAYS_INLINE void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
2791         {
2792             m_buffer.putShort(op1);
2793             m_buffer.putShort(op2);
2794         }
2795 
twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op,int imm4,RegisterID rd,ARMThumbImmediate imm)2796         ALWAYS_INLINE void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
2797         {
2798             ARMThumbImmediate newImm = imm;
2799             newImm.m_value.imm4 = imm4;
2800 
2801             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm));
2802             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
2803         }
2804 
twoWordOp12Reg4Reg4Imm12(OpcodeID1 op,RegisterID reg1,RegisterID reg2,uint16_t imm)2805         ALWAYS_INLINE void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
2806         {
2807             m_buffer.putShort(op | reg1);
2808             m_buffer.putShort((reg2 << 12) | imm);
2809         }
2810 
twoWordOp12Reg40Imm3Reg4Imm20Imm5(OpcodeID1 op,RegisterID reg1,RegisterID reg2,uint16_t imm1,uint16_t imm2,uint16_t imm3)2811         ALWAYS_INLINE void twoWordOp12Reg40Imm3Reg4Imm20Imm5(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm1, uint16_t imm2, uint16_t imm3)
2812         {
2813             m_buffer.putShort(op | reg1);
2814             m_buffer.putShort((imm1 << 12) | (reg2 << 8) | (imm2 << 6) | imm3);
2815         }
2816 
2817         // Formats up instructions of the pattern:
2818         //    111111111B11aaaa:bbbb222SA2C2cccc
2819         // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
2820         // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
vfpOp(OpcodeID1 op1,OpcodeID2 op2,bool size,VFPOperand a,VFPOperand b,VFPOperand c)2821         ALWAYS_INLINE void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
2822         {
2823             ASSERT(!(op1 & 0x004f));
2824             ASSERT(!(op2 & 0xf1af));
2825             m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4());
2826             m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4());
2827         }
2828 
2829         // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
2830         // (i.e. +/-(0..255) 32-bit words)
vfpMemOp(OpcodeID1 op1,OpcodeID2 op2,bool size,RegisterID rn,VFPOperand rd,int32_t imm)2831         ALWAYS_INLINE void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
2832         {
2833             bool up = true;
2834             if (imm < 0) {
2835                 imm = -imm;
2836                 up = false;
2837             }
2838 
2839             uint32_t offset = imm;
2840             ASSERT(!(offset & ~0x3fc));
2841             offset >>= 2;
2842 
2843             m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn);
2844             m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset);
2845         }
2846 
2847         // Administrative methods:
2848 
codeSize()2849         size_t codeSize() const { return m_buffer.codeSize(); }
label()2850         AssemblerLabel label() const { return m_buffer.label(); }
isAligned(int alignment)2851         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
data()2852         void* data() const { return m_buffer.data(); }
2853 
debugOffset()2854         unsigned debugOffset() { return m_buffer.debugOffset(); }
2855 
2856     private:
2857         AssemblerBuffer m_buffer;
2858     } m_formatter;
2859 
2860     Vector<LinkRecord, 0, UnsafeVectorOverflow> m_jumpsToLink;
2861     int m_indexOfLastWatchpoint;
2862     int m_indexOfTailOfLastWatchpoint;
2863 };
2864 
2865 #undef JUMP_ENUM_WITH_SIZE
2866 #undef JUMP_ENUM_SIZE
2867 
2868 } // namespace JSC
2869 
2870 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
2871 
2872 #endif // ARMAssembler_h
2873