2
* Copyright (C) 2009 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
13
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
#ifndef ARMAssembler_h
27
#define ARMAssembler_h
29
#include <wtf/Platform.h>
31
#if ENABLE(ASSEMBLER) && PLATFORM(ARM_THUMB2)
33
#include "AssemblerBuffer.h"
34
#include <wtf/Assertions.h>
35
#include <wtf/Vector.h>
40
namespace ARMRegisters {
49
r7, wr = r7, // thumb work register
51
r9, sb = r9, // static base
52
r10, sl = r10, // stack limit
53
r11, fp = r11, // frame pointer
163
class ARMv7Assembler;
164
class ARMThumbImmediate {
165
friend class ARMv7Assembler;
167
typedef uint8_t ThumbImmediateType;
168
static const ThumbImmediateType TypeInvalid = 0;
169
static const ThumbImmediateType TypeEncoded = 1;
170
static const ThumbImmediateType TypeUInt16 = 2;
180
// If this is an encoded immediate, then it may describe a shift, or a pattern.
182
unsigned shiftValue7 : 7;
183
unsigned shiftAmount : 5;
186
unsigned immediate : 8;
187
unsigned pattern : 4;
189
} ThumbImmediateValue;
191
// byte0 contains least significant bit; not using an array to make client code endian agnostic.
202
ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N)
204
if (value & ~((1<<N)-1)) /* check for any of the top N bits (of 2N bits) are set */ \
205
value >>= N; /* if any were set, lose the bottom N */ \
206
else /* if none of the top N bits are set, */ \
207
zeros += N; /* then we have identified N leading zeros */
210
static int32_t countLeadingZeros(uint32_t value)
216
countLeadingZerosPartial(value, zeros, 16);
217
countLeadingZerosPartial(value, zeros, 8);
218
countLeadingZerosPartial(value, zeros, 4);
219
countLeadingZerosPartial(value, zeros, 2);
220
countLeadingZerosPartial(value, zeros, 1);
225
: m_type(TypeInvalid)
230
ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value)
236
ARMThumbImmediate(ThumbImmediateType type, uint16_t value)
239
m_value.asInt = value;
243
static ARMThumbImmediate makeEncodedImm(uint32_t value)
245
ThumbImmediateValue encoding;
248
// okay, these are easy.
250
encoding.immediate = value;
251
encoding.pattern = 0;
252
return ARMThumbImmediate(TypeEncoded, encoding);
255
int32_t leadingZeros = countLeadingZeros(value);
256
// if there were 24 or more leading zeros, then we'd have hit the (value < 256) case.
257
ASSERT(leadingZeros < 24);
259
// Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32,
260
// Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for
261
// zero. count(B) == 8, so the count of bits to be checked is 24 - count(Z).
262
int32_t rightShiftAmount = 24 - leadingZeros;
263
if (value == ((value >> rightShiftAmount) << rightShiftAmount)) {
264
// Shift the value down to the low byte position. The assign to
265
// shiftValue7 drops the implicit top bit.
266
encoding.shiftValue7 = value >> rightShiftAmount;
267
// The endoded shift amount is the magnitude of a right rotate.
268
encoding.shiftAmount = 8 + leadingZeros;
269
return ARMThumbImmediate(TypeEncoded, encoding);
275
if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) {
276
encoding.immediate = bytes.byte0;
277
encoding.pattern = 3;
278
return ARMThumbImmediate(TypeEncoded, encoding);
281
if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) {
282
encoding.immediate = bytes.byte0;
283
encoding.pattern = 1;
284
return ARMThumbImmediate(TypeEncoded, encoding);
287
if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) {
288
encoding.immediate = bytes.byte0;
289
encoding.pattern = 2;
290
return ARMThumbImmediate(TypeEncoded, encoding);
293
return ARMThumbImmediate();
296
static ARMThumbImmediate makeUInt12(int32_t value)
298
return (!(value & 0xfffff000))
299
? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
300
: ARMThumbImmediate();
303
static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value)
305
// If this is not a 12-bit unsigned it, try making an encoded immediate.
306
return (!(value & 0xfffff000))
307
? ARMThumbImmediate(TypeUInt16, (uint16_t)value)
308
: makeEncodedImm(value);
311
// The 'make' methods, above, return a !isValid() value if the argument
312
// cannot be represented as the requested type. This methods is called
313
// 'get' since the argument can always be represented.
314
static ARMThumbImmediate makeUInt16(uint16_t value)
316
return ARMThumbImmediate(TypeUInt16, value);
321
return m_type != TypeInvalid;
324
// These methods rely on the format of encoded byte values.
325
bool isUInt3() { return !(m_value.asInt & 0xfff8); }
326
bool isUInt4() { return !(m_value.asInt & 0xfff0); }
327
bool isUInt5() { return !(m_value.asInt & 0xffe0); }
328
bool isUInt6() { return !(m_value.asInt & 0xffc0); }
329
bool isUInt7() { return !(m_value.asInt & 0xff80); }
330
bool isUInt8() { return !(m_value.asInt & 0xff00); }
331
bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); }
332
bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); }
333
bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); }
334
bool isUInt16() { return m_type == TypeUInt16; }
335
uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; }
336
uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; }
337
uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; }
338
uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
339
uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
340
uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
341
uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
342
uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
343
uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
344
uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
346
bool isEncodedImm() { return m_type == TypeEncoded; }
349
ThumbImmediateType m_type;
350
ThumbImmediateValue m_value;
360
SRType_RRX = SRType_ROR
363
class ARMv7Assembler;
364
class ShiftTypeAndAmount {
365
friend class ARMv7Assembler;
370
m_u.type = (ARMShiftType)0;
374
ShiftTypeAndAmount(ARMShiftType type, unsigned amount)
377
m_u.amount = amount & 31;
380
unsigned lo4() { return m_u.lo4; }
381
unsigned hi4() { return m_u.hi4; }
398
Some features of the Thumb instruction set are deprecated in ARMv7. Deprecated features affecting
399
instructions supported by ARMv7-M are as follows:
400
ā¢ use of the PC as <Rd> or <Rm> in a 16-bit ADD (SP plus register) instruction
401
ā¢ use of the SP as <Rm> in a 16-bit ADD (SP plus register) instruction
402
ā¢ use of the SP as <Rm> in a 16-bit CMP (register) instruction
403
ā¢ use of MOV (register) instructions in which <Rd> is the SP or PC and <Rm> is also the SP or PC.
404
ā¢ use of <Rn> as the lowest-numbered register in the register list of a 16-bit STM instruction with base
408
class ARMv7Assembler {
410
typedef ARMRegisters::RegisterID RegisterID;
411
typedef ARMRegisters::FPRegisterID FPRegisterID;
413
// (HS, LO, HI, LS) -> (AE, B, A, BE)
414
// (VS, VC) -> (O, NO)
432
ConditionCS = ConditionHS,
433
ConditionCC = ConditionLO,
437
friend class ARMv7Assembler;
438
friend class ARMInstructionFormatter;
455
friend class ARMv7Assembler;
456
friend class ARMInstructionFormatter;
464
bool isUsed() const { return m_used; }
465
void used() { m_used = true; }
471
ASSERT(m_offset == offset);
481
bool BadReg(RegisterID reg)
483
return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc);
486
bool isSingleRegister(FPRegisterID reg)
488
// Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
492
bool isDoubleRegister(FPRegisterID reg)
494
// Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc).
495
return !(reg & ~(31 << 1));
498
bool isQuadRegister(FPRegisterID reg)
500
return !(reg & ~(31 << 2));
503
uint32_t singleRegisterNum(FPRegisterID reg)
505
ASSERT(isSingleRegister(reg));
509
uint32_t doubleRegisterNum(FPRegisterID reg)
511
ASSERT(isDoubleRegister(reg));
515
uint32_t quadRegisterNum(FPRegisterID reg)
517
ASSERT(isQuadRegister(reg));
521
uint32_t singleRegisterMask(FPRegisterID rd, int highBitsShift, int lowBitShift)
523
uint32_t rdNum = singleRegisterNum(rd);
524
uint32_t rdMask = (rdNum >> 1) << highBitsShift;
526
rdMask |= 1 << lowBitShift;
530
uint32_t doubleRegisterMask(FPRegisterID rd, int highBitShift, int lowBitsShift)
532
uint32_t rdNum = doubleRegisterNum(rd);
533
uint32_t rdMask = (rdNum & 0xf) << lowBitsShift;
535
rdMask |= 1 << highBitShift;
540
OP_ADD_reg_T1 = 0x1800,
541
OP_ADD_S_reg_T1 = 0x1800,
542
OP_SUB_reg_T1 = 0x1A00,
543
OP_SUB_S_reg_T1 = 0x1A00,
544
OP_ADD_imm_T1 = 0x1C00,
545
OP_ADD_S_imm_T1 = 0x1C00,
546
OP_SUB_imm_T1 = 0x1E00,
547
OP_SUB_S_imm_T1 = 0x1E00,
548
OP_MOV_imm_T1 = 0x2000,
549
OP_CMP_imm_T1 = 0x2800,
550
OP_ADD_imm_T2 = 0x3000,
551
OP_ADD_S_imm_T2 = 0x3000,
552
OP_SUB_imm_T2 = 0x3800,
553
OP_SUB_S_imm_T2 = 0x3800,
554
OP_AND_reg_T1 = 0x4000,
555
OP_EOR_reg_T1 = 0x4040,
556
OP_TST_reg_T1 = 0x4200,
557
OP_CMP_reg_T1 = 0x4280,
558
OP_ORR_reg_T1 = 0x4300,
559
OP_MVN_reg_T1 = 0x43C0,
560
OP_ADD_reg_T2 = 0x4400,
561
OP_MOV_reg_T1 = 0x4600,
564
OP_LDRH_reg_T1 = 0x5A00,
565
OP_STR_reg_T1 = 0x5000,
566
OP_LDR_reg_T1 = 0x5800,
567
OP_STR_imm_T1 = 0x6000,
568
OP_LDR_imm_T1 = 0x6800,
569
OP_LDRH_imm_T1 = 0x8800,
570
OP_STR_imm_T2 = 0x9000,
571
OP_LDR_imm_T2 = 0x9800,
572
OP_ADD_SP_imm_T1 = 0xA800,
573
OP_ADD_SP_imm_T2 = 0xB000,
574
OP_SUB_SP_imm_T1 = 0xB080,
580
OP_AND_reg_T2 = 0xEA00,
581
OP_TST_reg_T2 = 0xEA10,
582
OP_ORR_reg_T2 = 0xEA40,
583
OP_ASR_imm_T1 = 0xEA4F,
584
OP_LSL_imm_T1 = 0xEA4F,
585
OP_LSR_imm_T1 = 0xEA4F,
586
OP_ROR_imm_T1 = 0xEA4F,
587
OP_MVN_reg_T2 = 0xEA6F,
588
OP_EOR_reg_T2 = 0xEA80,
589
OP_ADD_reg_T3 = 0xEB00,
590
OP_ADD_S_reg_T3 = 0xEB10,
591
OP_SUB_reg_T2 = 0xEBA0,
592
OP_SUB_S_reg_T2 = 0xEBB0,
593
OP_CMP_reg_T2 = 0xEBB0,
595
OP_AND_imm_T1 = 0xF000,
597
OP_ORR_imm_T1 = 0xF040,
598
OP_MOV_imm_T2 = 0xF040,
600
OP_EOR_imm_T1 = 0xF080,
601
OP_ADD_imm_T3 = 0xF100,
602
OP_ADD_S_imm_T3 = 0xF110,
604
OP_SUB_imm_T3 = 0xF1A0,
605
OP_SUB_S_imm_T3 = 0xF1B0,
606
OP_CMP_imm_T2 = 0xF1B0,
607
OP_ADD_imm_T4 = 0xF200,
608
OP_MOV_imm_T3 = 0xF240,
609
OP_SUB_imm_T4 = 0xF2A0,
611
OP_LDRH_reg_T2 = 0xF830,
612
OP_LDRH_imm_T3 = 0xF830,
613
OP_STR_imm_T4 = 0xF840,
614
OP_STR_reg_T2 = 0xF840,
615
OP_LDR_imm_T4 = 0xF850,
616
OP_LDR_reg_T2 = 0xF850,
617
OP_LDRH_imm_T2 = 0xF8B0,
618
OP_STR_imm_T3 = 0xF8C0,
619
OP_LDR_imm_T3 = 0xF8D0,
620
OP_LSL_reg_T2 = 0xFA00,
621
OP_LSR_reg_T2 = 0xFA20,
622
OP_ASR_reg_T2 = 0xFA40,
623
OP_ROR_reg_T2 = 0xFA60,
624
OP_SMULL_T1 = 0xFB80,
632
FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0)
651
class ARMInstructionFormatter;
654
bool ifThenElseConditionBit(Condition condition, bool isIf)
656
return isIf ? (condition & 1) : !(condition & 1);
658
uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
660
int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
661
| (ifThenElseConditionBit(condition, inst3if) << 2)
662
| (ifThenElseConditionBit(condition, inst4if) << 1)
664
ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
665
return (condition << 4) | mask;
667
uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
669
int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
670
| (ifThenElseConditionBit(condition, inst3if) << 2)
672
ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
673
return (condition << 4) | mask;
675
uint8_t ifThenElse(Condition condition, bool inst2if)
677
int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
679
ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
680
return (condition << 4) | mask;
683
uint8_t ifThenElse(Condition condition)
686
ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
687
return (condition << 4) | mask;
692
void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
694
// Rd can only be SP if Rn is also SP.
695
ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
696
ASSERT(rd != ARMRegisters::pc);
697
ASSERT(rn != ARMRegisters::pc);
698
ASSERT(imm.isValid());
700
if (rn == ARMRegisters::sp) {
701
if (!(rd & 8) && imm.isUInt10()) {
702
m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
704
} else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
705
m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
708
} else if (!((rd | rn) & 8)) {
710
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
712
} else if ((rd == rn) && imm.isUInt8()) {
713
m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8());
718
if (imm.isEncodedImm())
719
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm);
721
ASSERT(imm.isUInt12());
722
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm);
726
void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
728
ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
729
ASSERT(rd != ARMRegisters::pc);
730
ASSERT(rn != ARMRegisters::pc);
732
m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
735
// NOTE: In an IT block, add doesn't modify the flags register.
736
void add(RegisterID rd, RegisterID rn, RegisterID rm)
739
m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
741
m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd);
742
else if (!((rd | rn | rm) & 8))
743
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
745
add(rd, rn, rm, ShiftTypeAndAmount());
748
// Not allowed in an IT (if then) block.
749
void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
751
// Rd can only be SP if Rn is also SP.
752
ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
753
ASSERT(rd != ARMRegisters::pc);
754
ASSERT(rn != ARMRegisters::pc);
755
ASSERT(imm.isEncodedImm());
757
if (!((rd | rn) & 8)) {
759
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
761
} else if ((rd == rn) && imm.isUInt8()) {
762
m_formatter.oneWordOp5Reg3Imm8(OP_ADD_S_imm_T2, rd, imm.getUInt8());
767
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm);
770
// Not allowed in an IT (if then) block?
771
void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
773
ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
774
ASSERT(rd != ARMRegisters::pc);
775
ASSERT(rn != ARMRegisters::pc);
777
m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
780
// Not allowed in an IT (if then) block.
781
void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
783
if (!((rd | rn | rm) & 8))
784
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_reg_T1, rm, rn, rd);
786
add_S(rd, rn, rm, ShiftTypeAndAmount());
789
void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
793
ASSERT(imm.isEncodedImm());
794
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
797
void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
802
m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
805
void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
807
if ((rd == rn) && !((rd | rm) & 8))
808
m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
809
else if ((rd == rm) && !((rd | rn) & 8))
810
m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd);
812
ARM_and(rd, rn, rm, ShiftTypeAndAmount());
815
void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
819
ShiftTypeAndAmount shift(SRType_ASR, shiftAmount);
820
m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
823
void asr(RegisterID rd, RegisterID rn, RegisterID rm)
828
m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
831
// Only allowed in IT (if then) block if last instruction.
834
m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
835
return JmpSrc(m_formatter.size());
838
// Only allowed in IT (if then) block if last instruction.
839
JmpSrc blx(RegisterID rm)
841
ASSERT(rm != ARMRegisters::pc);
842
m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
843
return JmpSrc(m_formatter.size());
846
// Only allowed in IT (if then) block if last instruction.
847
JmpSrc bx(RegisterID rm)
849
m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
850
return JmpSrc(m_formatter.size());
853
void bkpt(uint8_t imm=0)
855
m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
858
void cmn(RegisterID rn, ARMThumbImmediate imm)
860
ASSERT(rn != ARMRegisters::pc);
861
ASSERT(imm.isEncodedImm());
863
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
866
void cmp(RegisterID rn, ARMThumbImmediate imm)
868
ASSERT(rn != ARMRegisters::pc);
869
ASSERT(imm.isEncodedImm());
871
if (!(rn & 8) && imm.isUInt8())
872
m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8());
874
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
877
void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
879
ASSERT(rn != ARMRegisters::pc);
881
m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
884
void cmp(RegisterID rn, RegisterID rm)
887
cmp(rn, rm, ShiftTypeAndAmount());
889
m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn);
892
// xor is not spelled with an 'e'. :-(
893
void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
897
ASSERT(imm.isEncodedImm());
898
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm);
901
// xor is not spelled with an 'e'. :-(
902
void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
907
m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
910
// xor is not spelled with an 'e'. :-(
911
void eor(RegisterID rd, RegisterID rn, RegisterID rm)
913
if ((rd == rn) && !((rd | rm) & 8))
914
m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd);
915
else if ((rd == rm) && !((rd | rn) & 8))
916
m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd);
918
eor(rd, rn, rm, ShiftTypeAndAmount());
921
void it(Condition cond)
923
m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
926
void it(Condition cond, bool inst2if)
928
m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
931
void it(Condition cond, bool inst2if, bool inst3if)
933
m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
936
void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
938
m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
941
// rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
942
void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
944
ASSERT(rn != ARMRegisters::pc); // LDR (literal)
945
ASSERT(imm.isUInt12());
947
if (!((rt | rn) & 8) && imm.isUInt7())
948
m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
949
else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
950
m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
952
m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
955
// If index is set, this is a regular offset or a pre-indexed load;
956
// if index is not set then is is a post-index load.
958
// If wback is set rn is updated - this is a pre or post index load,
959
// if wback is not set this is a regular offset memory access.
961
// (-255 <= offset <= 255)
963
// _tmp = _reg + offset
964
// MEM[index ? _tmp : _reg] = REG[rt]
965
// if (wback) REG[rn] = _tmp
966
void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
968
ASSERT(rt != ARMRegisters::pc);
969
ASSERT(rn != ARMRegisters::pc);
970
ASSERT(index || wback);
971
ASSERT(!wback | (rt != rn));
978
ASSERT((offset & ~0xff) == 0);
980
offset |= (wback << 8);
981
offset |= (add << 9);
982
offset |= (index << 10);
985
m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset);
988
// rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
989
void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
991
ASSERT(rn != ARMRegisters::pc); // LDR (literal)
995
if (!shift && !((rt | rn | rm) & 8))
996
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt);
998
m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1001
// rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1002
void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1004
ASSERT(rn != ARMRegisters::pc); // LDR (literal)
1005
ASSERT(imm.isUInt12());
1007
if (!((rt | rn) & 8) && imm.isUInt6())
1008
m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt);
1010
m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12());
1013
// If index is set, this is a regular offset or a pre-indexed load;
1014
// if index is not set then is is a post-index load.
1016
// If wback is set rn is updated - this is a pre or post index load,
1017
// if wback is not set this is a regular offset memory access.
1019
// (-255 <= offset <= 255)
1021
// _tmp = _reg + offset
1022
// MEM[index ? _tmp : _reg] = REG[rt]
1023
// if (wback) REG[rn] = _tmp
1024
void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1026
ASSERT(rt != ARMRegisters::pc);
1027
ASSERT(rn != ARMRegisters::pc);
1028
ASSERT(index || wback);
1029
ASSERT(!wback | (rt != rn));
1036
ASSERT((offset & ~0xff) == 0);
1038
offset |= (wback << 8);
1039
offset |= (add << 9);
1040
offset |= (index << 10);
1041
offset |= (1 << 11);
1043
m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
1046
void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1048
ASSERT(!BadReg(rt)); // Memory hint
1049
ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
1050
ASSERT(!BadReg(rm));
1053
if (!shift && !((rt | rn | rm) & 8))
1054
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt);
1056
m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
1059
void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1061
ASSERT(!BadReg(rd));
1062
ASSERT(!BadReg(rm));
1063
ShiftTypeAndAmount shift(SRType_LSL, shiftAmount);
1064
m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1067
void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
1069
ASSERT(!BadReg(rd));
1070
ASSERT(!BadReg(rn));
1071
ASSERT(!BadReg(rm));
1072
m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1075
void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1077
ASSERT(!BadReg(rd));
1078
ASSERT(!BadReg(rm));
1079
ShiftTypeAndAmount shift(SRType_LSR, shiftAmount);
1080
m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1083
void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
1085
ASSERT(!BadReg(rd));
1086
ASSERT(!BadReg(rn));
1087
ASSERT(!BadReg(rm));
1088
m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1091
void movT3(RegisterID rd, ARMThumbImmediate imm)
1093
ASSERT(imm.isValid());
1094
ASSERT(!imm.isEncodedImm());
1095
ASSERT(!BadReg(rd));
1097
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
1100
void mov(RegisterID rd, ARMThumbImmediate imm)
1102
ASSERT(imm.isValid());
1103
ASSERT(!BadReg(rd));
1105
if ((rd < 8) && imm.isUInt8())
1106
m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8());
1107
else if (imm.isEncodedImm())
1108
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm);
1113
void mov(RegisterID rd, RegisterID rm)
1115
m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
1118
void movt(RegisterID rd, ARMThumbImmediate imm)
1120
ASSERT(imm.isUInt16());
1121
ASSERT(!BadReg(rd));
1122
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
1125
void mvn(RegisterID rd, ARMThumbImmediate imm)
1127
ASSERT(imm.isEncodedImm());
1128
ASSERT(!BadReg(rd));
1130
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
1133
void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
1135
ASSERT(!BadReg(rd));
1136
ASSERT(!BadReg(rm));
1137
m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1140
void mvn(RegisterID rd, RegisterID rm)
1142
if (!((rd | rm) & 8))
1143
m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
1145
mvn(rd, rm, ShiftTypeAndAmount());
1148
void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1150
ASSERT(!BadReg(rd));
1151
ASSERT(!BadReg(rn));
1152
ASSERT(imm.isEncodedImm());
1153
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
1156
void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1158
ASSERT(!BadReg(rd));
1159
ASSERT(!BadReg(rn));
1160
ASSERT(!BadReg(rm));
1161
m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1164
void orr(RegisterID rd, RegisterID rn, RegisterID rm)
1166
if ((rd == rn) && !((rd | rm) & 8))
1167
m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd);
1168
else if ((rd == rm) && !((rd | rn) & 8))
1169
m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd);
1171
orr(rd, rn, rm, ShiftTypeAndAmount());
1174
void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
1176
ASSERT(!BadReg(rd));
1177
ASSERT(!BadReg(rm));
1178
ShiftTypeAndAmount shift(SRType_ROR, shiftAmount);
1179
m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1182
void ror(RegisterID rd, RegisterID rn, RegisterID rm)
1184
ASSERT(!BadReg(rd));
1185
ASSERT(!BadReg(rn));
1186
ASSERT(!BadReg(rm));
1187
m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
1190
void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
1192
ASSERT(!BadReg(rdLo));
1193
ASSERT(!BadReg(rdHi));
1194
ASSERT(!BadReg(rn));
1195
ASSERT(!BadReg(rm));
1196
ASSERT(rdLo != rdHi);
1197
m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm));
1200
// rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1201
void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
1203
ASSERT(rt != ARMRegisters::pc);
1204
ASSERT(rn != ARMRegisters::pc);
1205
ASSERT(imm.isUInt12());
1207
if (!((rt | rn) & 8) && imm.isUInt7())
1208
m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
1209
else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
1210
m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
1212
m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
1215
// If index is set, this is a regular offset or a pre-indexed store;
1216
// if index is not set then is is a post-index store.
1218
// If wback is set rn is updated - this is a pre or post index store,
1219
// if wback is not set this is a regular offset memory access.
1221
// (-255 <= offset <= 255)
1223
// _tmp = _reg + offset
1224
// MEM[index ? _tmp : _reg] = REG[rt]
1225
// if (wback) REG[rn] = _tmp
1226
void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
1228
ASSERT(rt != ARMRegisters::pc);
1229
ASSERT(rn != ARMRegisters::pc);
1230
ASSERT(index || wback);
1231
ASSERT(!wback | (rt != rn));
1238
ASSERT((offset & ~0xff) == 0);
1240
offset |= (wback << 8);
1241
offset |= (add << 9);
1242
offset |= (index << 10);
1243
offset |= (1 << 11);
1245
m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset);
1248
// rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
1249
void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
1251
ASSERT(rn != ARMRegisters::pc);
1252
ASSERT(!BadReg(rm));
1255
if (!shift && !((rt | rn | rm) & 8))
1256
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt);
1258
m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
1261
void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1263
// Rd can only be SP if Rn is also SP.
1264
ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1265
ASSERT(rd != ARMRegisters::pc);
1266
ASSERT(rn != ARMRegisters::pc);
1267
ASSERT(imm.isValid());
1269
if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1270
m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1272
} else if (!((rd | rn) & 8)) {
1273
if (imm.isUInt3()) {
1274
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1276
} else if ((rd == rn) && imm.isUInt8()) {
1277
m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8());
1282
if (imm.isEncodedImm())
1283
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm);
1285
ASSERT(imm.isUInt12());
1286
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm);
1290
void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1292
ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1293
ASSERT(rd != ARMRegisters::pc);
1294
ASSERT(rn != ARMRegisters::pc);
1295
ASSERT(!BadReg(rm));
1296
m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1299
// NOTE: In an IT block, add doesn't modify the flags register.
1300
void sub(RegisterID rd, RegisterID rn, RegisterID rm)
1302
if (!((rd | rn | rm) & 8))
1303
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
1305
sub(rd, rn, rm, ShiftTypeAndAmount());
1308
// Not allowed in an IT (if then) block.
1309
void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
1311
// Rd can only be SP if Rn is also SP.
1312
ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1313
ASSERT(rd != ARMRegisters::pc);
1314
ASSERT(rn != ARMRegisters::pc);
1315
ASSERT(imm.isValid());
1317
if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
1318
m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
1320
} else if (!((rd | rn) & 8)) {
1321
if (imm.isUInt3()) {
1322
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd);
1324
} else if ((rd == rn) && imm.isUInt8()) {
1325
m_formatter.oneWordOp5Reg3Imm8(OP_SUB_S_imm_T2, rd, imm.getUInt8());
1330
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
1333
// Not allowed in an IT (if then) block?
1334
void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1336
ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
1337
ASSERT(rd != ARMRegisters::pc);
1338
ASSERT(rn != ARMRegisters::pc);
1339
ASSERT(!BadReg(rm));
1340
m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
1343
// Not allowed in an IT (if then) block.
1344
void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
1346
if (!((rd | rn | rm) & 8))
1347
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_reg_T1, rm, rn, rd);
1349
sub_S(rd, rn, rm, ShiftTypeAndAmount());
1352
void tst(RegisterID rn, ARMThumbImmediate imm)
1354
ASSERT(!BadReg(rn));
1355
ASSERT(imm.isEncodedImm());
1357
m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
1360
void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
1362
ASSERT(!BadReg(rn));
1363
ASSERT(!BadReg(rm));
1364
m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
1367
void tst(RegisterID rn, RegisterID rm)
1370
tst(rn, rm, ShiftTypeAndAmount());
1372
m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
1375
void vadd_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1377
m_formatter.vfpOp(0x0b00ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1380
void vcmp_F64(FPRegisterID rd, FPRegisterID rm)
1382
m_formatter.vfpOp(0x0bc0eeb4 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rm, 21, 16));
1385
void vcvt_F64_S32(FPRegisterID fd, FPRegisterID sm)
1387
m_formatter.vfpOp(0x0bc0eeb8 | doubleRegisterMask(fd, 6, 28) | singleRegisterMask(sm, 16, 21));
1390
void vcvt_S32_F64(FPRegisterID sd, FPRegisterID fm)
1392
m_formatter.vfpOp(0x0bc0eebd | singleRegisterMask(sd, 28, 6) | doubleRegisterMask(fm, 21, 16));
1395
void vldr(FPRegisterID rd, RegisterID rn, int32_t imm)
1397
vmem(rd, rn, imm, true);
1400
void vmov(RegisterID rd, FPRegisterID sn)
1402
m_formatter.vfpOp(0x0a10ee10 | (rd << 28) | singleRegisterMask(sn, 0, 23));
1405
void vmov(FPRegisterID sn, RegisterID rd)
1407
m_formatter.vfpOp(0x0a10ee00 | (rd << 28) | singleRegisterMask(sn, 0, 23));
1410
// move FPSCR flags to APSR.
1411
void vmrs_APSR_nzcv_FPSCR()
1413
m_formatter.vfpOp(0xfa10eef1);
1416
void vmul_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1418
m_formatter.vfpOp(0x0b00ee20 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1421
void vstr(FPRegisterID rd, RegisterID rn, int32_t imm)
1423
vmem(rd, rn, imm, false);
1426
void vsub_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm)
1428
m_formatter.vfpOp(0x0b40ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16));
1434
return JmpDst(m_formatter.size());
1437
JmpDst align(int alignment)
1439
while (!m_formatter.isAligned(alignment))
1445
static void* getRelocatedAddress(void* code, JmpSrc jump)
1447
ASSERT(jump.m_offset != -1);
1449
return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1452
static void* getRelocatedAddress(void* code, JmpDst destination)
1454
ASSERT(destination.m_offset != -1);
1456
return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
1459
static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1461
return dst.m_offset - src.m_offset;
1464
static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1466
return dst.m_offset - src.m_offset;
1469
static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
1471
return dst.m_offset - src.m_offset;
1474
// Assembler admin methods:
1478
return m_formatter.size();
1481
void* executableCopy(ExecutablePool* allocator)
1483
void* copy = m_formatter.executableCopy(allocator);
1488
static unsigned getCallReturnOffset(JmpSrc call)
1490
ASSERT(call.m_offset >= 0);
1491
return call.m_offset;
1494
// Linking & patching:
1496
// 'link' and 'patch' methods are for use on unprotected code - such as the code
1497
// within the AssemblerBuffer, and code being patched by the patch buffer. Once
1498
// code has been finalized it is (platform support permitting) within a non-
1499
// writable region of memory; to modify the code in an execute-only execuable
1500
// pool the 'repatch' and 'relink' methods should be used.
1502
void linkJump(JmpSrc from, JmpDst to)
1504
ASSERT(to.m_offset != -1);
1505
ASSERT(from.m_offset != -1);
1507
uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(m_formatter.data()) + from.m_offset);
1508
intptr_t relative = to.m_offset - from.m_offset;
1510
linkWithOffset(location, relative);
1513
static void linkJump(void* code, JmpSrc from, void* to)
1515
ASSERT(from.m_offset != -1);
1517
uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
1518
intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(location);
1520
linkWithOffset(location, relative);
1523
// bah, this mathod should really be static, since it is used by the LinkBuffer.
1524
// return a bool saying whether the link was successful?
1525
static void linkCall(void* code, JmpSrc from, void* to)
1527
ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
1528
ASSERT(from.m_offset != -1);
1529
ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1531
setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
1534
static void linkPointer(void* code, JmpDst where, void* value)
1536
setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
1539
static void relinkJump(void* from, void* to)
1541
ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1542
ASSERT(!(reinterpret_cast<intptr_t>(to) & 1));
1544
intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
1545
linkWithOffset(reinterpret_cast<uint16_t*>(from), relative);
1547
ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 2, 2 * sizeof(uint16_t));
1550
static void relinkCall(void* from, void* to)
1552
ASSERT(!(reinterpret_cast<intptr_t>(from) & 1));
1553
ASSERT(reinterpret_cast<intptr_t>(to) & 1);
1555
setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
1557
ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 4 * sizeof(uint16_t));
1560
static void repatchInt32(void* where, int32_t value)
1562
ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1564
setInt32(where, value);
1566
ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
1569
static void repatchPointer(void* where, void* value)
1571
ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1573
setPointer(where, value);
1575
ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t));
1578
static void repatchLoadPtrToLEA(void* where)
1580
ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
1582
uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
1583
ASSERT((*loadOp & 0xfff0) == OP_LDR_reg_T2);
1585
*loadOp = OP_ADD_reg_T3 | (*loadOp & 0xf);
1586
ExecutableAllocator::cacheFlush(loadOp, sizeof(uint16_t));
1591
// Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
1592
// (i.e. +/-(0..255) 32-bit words)
1593
void vmem(FPRegisterID rd, RegisterID rn, int32_t imm, bool isLoad)
1605
// offset is effectively leftshifted by 2 already (the bottom two bits are zero, and not
1606
// reperesented in the instruction. Left shift by 14, to mov it into position 0x00AA0000.
1607
ASSERT((offset & ~(0xff << 2)) == 0);
1610
m_formatter.vfpOp(0x0b00ed00 | offset | (up << 7) | (isLoad << 4) | doubleRegisterMask(rd, 6, 28) | rn);
1613
static void setInt32(void* code, uint32_t value)
1615
uint16_t* location = reinterpret_cast<uint16_t*>(code);
1617
uint16_t lo16 = value;
1618
uint16_t hi16 = value >> 16;
1620
spliceHi5(location - 4, lo16);
1621
spliceLo11(location - 3, lo16);
1622
spliceHi5(location - 2, hi16);
1623
spliceLo11(location - 1, hi16);
1625
ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
1628
static void setPointer(void* code, void* value)
1630
setInt32(code, reinterpret_cast<uint32_t>(value));
1633
// Linking & patching:
1634
// This method assumes that the JmpSrc being linked is a T4 b instruction.
1635
static void linkWithOffset(uint16_t* instruction, intptr_t relative)
1637
// Currently branches > 16m = mostly deathy.
1638
if (((relative << 7) >> 7) != relative) {
1639
// FIXME: This CRASH means we cannot turn the JIT on by default on arm-v7.
1640
fprintf(stderr, "Error: Cannot link T4b.\n");
1644
// ARM encoding for the top two bits below the sign bit is 'peculiar'.
1646
relative ^= 0xC00000;
1648
// All branch offsets should be an even distance.
1649
ASSERT(!(relative & 1));
1651
int word1 = ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
1652
int word2 = ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
1654
instruction[-2] = OP_B_T4a | word1;
1655
instruction[-1] = OP_B_T4b | word2;
1658
// These functions can be used to splice 16-bit immediates back into previously generated instructions.
1659
static void spliceHi5(uint16_t* where, uint16_t what)
1661
uint16_t pattern = (what >> 12) | ((what & 0x0800) >> 1);
1662
*where = (*where & 0xFBF0) | pattern;
1664
static void spliceLo11(uint16_t* where, uint16_t what)
1666
uint16_t pattern = ((what & 0x0700) << 4) | (what & 0x00FF);
1667
*where = (*where & 0x8F00) | pattern;
1670
class ARMInstructionFormatter {
1672
void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
1674
m_buffer.putShort(op | (rd << 8) | imm);
1677
void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
1679
m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
1682
void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
1684
m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
1687
void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
1689
m_buffer.putShort(op | imm);
1692
void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
1694
m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
1696
void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
1698
m_buffer.putShort(op | imm);
1701
void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
1703
m_buffer.putShort(op | (reg1 << 3) | reg2);
1706
void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
1708
m_buffer.putShort(op | reg);
1709
m_buffer.putShort(ff.m_u.value);
1712
void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
1714
m_buffer.putShort(op);
1715
m_buffer.putShort(ff.m_u.value);
1718
void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
1720
m_buffer.putShort(op1);
1721
m_buffer.putShort(op2);
1724
void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
1726
m_buffer.putShort(op | (imm.m_value.i << 10) | imm4);
1727
m_buffer.putShort((imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8);
1730
void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
1732
m_buffer.putShort(op | reg1);
1733
m_buffer.putShort((reg2 << 12) | imm);
1736
void vfpOp(int32_t op)
1738
m_buffer.putInt(op);
1742
// Administrative methods:
1744
size_t size() const { return m_buffer.size(); }
1745
bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
1746
void* data() const { return m_buffer.data(); }
1747
void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
1750
AssemblerBuffer m_buffer;
1756
#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM_THUMB2)
1758
#endif // ARMAssembler_h