Merge "ART: Add 16-bit Thumb2 ROR, NEGS and CMP for high registers."
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 62026f3..9de9abf 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -2731,11 +2731,9 @@
Register temp = locations->GetTemp(0).AsRegister<Register>();
// temp = reg1 / reg2 (integer division)
- // temp = temp * reg2
- // dest = reg1 - temp
+ // dest = reg1 - temp * reg2
__ sdiv(temp, reg1, reg2);
- __ mul(temp, temp, reg2);
- __ sub(out.AsRegister<Register>(), reg1, ShifterOperand(temp));
+ __ mls(out.AsRegister<Register>(), temp, reg2, reg1);
} else {
InvokeRuntimeCallingConvention calling_convention;
DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegister<Register>());
@@ -2905,7 +2903,7 @@
// If the shift is > 32 bits, override the high part
__ subs(temp, o_l, ShifterOperand(kArmBitsPerWord));
__ it(PL);
- __ Lsl(o_h, low, temp, false, PL);
+ __ Lsl(o_h, low, temp, PL);
// Shift the low part
__ Lsl(o_l, low, o_l);
} else if (op->IsShr()) {
@@ -2919,7 +2917,7 @@
// If the shift is > 32 bits, override the low part
__ subs(temp, o_h, ShifterOperand(kArmBitsPerWord));
__ it(PL);
- __ Asr(o_l, high, temp, false, PL);
+ __ Asr(o_l, high, temp, PL);
// Shift the high part
__ Asr(o_h, high, o_h);
} else {
@@ -2931,7 +2929,7 @@
__ orr(o_l, o_l, ShifterOperand(temp));
__ subs(temp, o_h, ShifterOperand(kArmBitsPerWord));
__ it(PL);
- __ Lsr(o_l, high, temp, false, PL);
+ __ Lsr(o_l, high, temp, PL);
__ Lsr(o_h, high, o_h);
}
break;
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index 0e3e08c..807beda 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -137,10 +137,14 @@
if (rs_ == kNoRegister) {
// Immediate shift.
if (shift_ == RRX) {
+ DCHECK_EQ(immed_, 0u);
// RRX is encoded as an ROR with imm 0.
return ROR << 4 | static_cast<uint32_t>(rm_);
} else {
- uint32_t imm3 = immed_ >> 2;
+ DCHECK((1 <= immed_ && immed_ <= 31) ||
+ (immed_ == 0u && shift_ == LSL) ||
+ (immed_ == 32u && (shift_ == ASR || shift_ == LSR)));
+ uint32_t imm3 = (immed_ >> 2) & 7 /* 0b111*/;
uint32_t imm2 = immed_ & 3U /* 0b11 */;
return imm3 << 12 | imm2 << 6 | shift_ << 4 |
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index ef60fef..7825457 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -375,6 +375,13 @@
kItE = kItElse
};
+// Set condition codes request.
+enum SetCc {
+ kCcDontCare, // Allows prioritizing 16-bit instructions on Thumb2 whether they set CCs or not.
+ kCcSet,
+ kCcKeep,
+};
+
constexpr uint32_t kNoItCondition = 3;
constexpr uint32_t kInvalidModifiedImmediate = -1;
@@ -392,25 +399,61 @@
virtual bool IsThumb() const = 0;
// Data-processing instructions.
- virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void and_(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
- virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void ands(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ and_(rd, rn, so, cond, kCcSet);
+ }
- virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
- virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void eor(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
- virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
- virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void eors(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ eor(rd, rn, so, cond, kCcSet);
+ }
- virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void sub(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
- virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ sub(rd, rn, so, cond, kCcSet);
+ }
- virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
- virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ rsb(rd, rn, so, cond, kCcSet);
+ }
- virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void add(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ add(rd, rn, so, cond, kCcSet);
+ }
+
+ virtual void adc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ virtual void adcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ adc(rd, rn, so, cond, kCcSet);
+ }
+
+ virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ virtual void sbcs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ sbc(rd, rn, so, cond, kCcSet);
+ }
+
+ virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ virtual void rscs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ rsc(rd, rn, so, cond, kCcSet);
+ }
virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
@@ -420,16 +463,33 @@
virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
- virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
- virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void orr(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
- virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
- virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ orr(rd, rn, so, cond, kCcSet);
+ }
- virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void mov(Register rd, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
- virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
- virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0;
+ virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) {
+ mov(rd, so, cond, kCcSet);
+ }
+
+ virtual void bic(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ virtual void bics(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) {
+ bic(rd, rn, so, cond, kCcSet);
+ }
+
+ virtual void mvn(Register rd, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) {
+ mvn(rd, so, cond, kCcSet);
+ }
// Miscellaneous data-processing instructions.
virtual void clz(Register rd, Register rm, Condition cond = AL) = 0;
@@ -697,25 +757,68 @@
// Convenience shift instructions. Use mov instruction with shifter operand
// for variants setting the status flags or using a register shift count.
- virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) = 0;
- virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) = 0;
- virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) = 0;
- virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) = 0;
- virtual void Rrx(Register rd, Register rm, bool setcc = false,
- Condition cond = AL) = 0;
+ virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
- virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) = 0;
- virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) = 0;
- virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) = 0;
- virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) = 0;
+ void Lsls(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
+ Lsl(rd, rm, shift_imm, cond, kCcSet);
+ }
+
+ virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ void Lsrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
+ Lsr(rd, rm, shift_imm, cond, kCcSet);
+ }
+
+ virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ void Asrs(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
+ Asr(rd, rm, shift_imm, cond, kCcSet);
+ }
+
+ virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ void Rors(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL) {
+ Ror(rd, rm, shift_imm, cond, kCcSet);
+ }
+
+ virtual void Rrx(Register rd, Register rm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ void Rrxs(Register rd, Register rm, Condition cond = AL) {
+ Rrx(rd, rm, cond, kCcSet);
+ }
+
+ virtual void Lsl(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ void Lsls(Register rd, Register rm, Register rn, Condition cond = AL) {
+ Lsl(rd, rm, rn, cond, kCcSet);
+ }
+
+ virtual void Lsr(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ void Lsrs(Register rd, Register rm, Register rn, Condition cond = AL) {
+ Lsr(rd, rm, rn, cond, kCcSet);
+ }
+
+ virtual void Asr(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ void Asrs(Register rd, Register rm, Register rn, Condition cond = AL) {
+ Asr(rd, rm, rn, cond, kCcSet);
+ }
+
+ virtual void Ror(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) = 0;
+
+ void Rors(Register rd, Register rm, Register rn, Condition cond = AL) {
+ Ror(rd, rm, rn, cond, kCcSet);
+ }
// Returns whether the `immediate` can fit in a `ShifterOperand`. If yes,
// `shifter_op` contains the operand.
diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc
index 6e60ddc..d91ddee 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -57,126 +57,94 @@
}
void Arm32Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), AND, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), AND, set_cc, rn, rd, so);
}
void Arm32Assembler::eor(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), EOR, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), EOR, set_cc, rn, rd, so);
}
void Arm32Assembler::sub(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), SUB, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), SUB, set_cc, rn, rd, so);
}
void Arm32Assembler::rsb(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), RSB, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), RSB, set_cc, rn, rd, so);
}
-void Arm32Assembler::rsbs(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), RSB, 1, rn, rd, so);
-}
-
-
void Arm32Assembler::add(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), ADD, 0, rn, rd, so);
-}
-
-
-void Arm32Assembler::adds(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), ADD, 1, rn, rd, so);
-}
-
-
-void Arm32Assembler::subs(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), SUB, 1, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), ADD, set_cc, rn, rd, so);
}
void Arm32Assembler::adc(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), ADC, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), ADC, set_cc, rn, rd, so);
}
void Arm32Assembler::sbc(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), SBC, set_cc, rn, rd, so);
}
void Arm32Assembler::rsc(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), RSC, set_cc, rn, rd, so);
}
void Arm32Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) {
CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
- EmitType01(cond, so.type(), TST, 1, rn, R0, so);
+ EmitType01(cond, so.type(), TST, kCcSet, rn, R0, so);
}
void Arm32Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) {
CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
- EmitType01(cond, so.type(), TEQ, 1, rn, R0, so);
+ EmitType01(cond, so.type(), TEQ, kCcSet, rn, R0, so);
}
void Arm32Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) {
- EmitType01(cond, so.type(), CMP, 1, rn, R0, so);
+ EmitType01(cond, so.type(), CMP, kCcSet, rn, R0, so);
}
void Arm32Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) {
- EmitType01(cond, so.type(), CMN, 1, rn, R0, so);
+ EmitType01(cond, so.type(), CMN, kCcSet, rn, R0, so);
}
-void Arm32Assembler::orr(Register rd, Register rn,
- const ShifterOperand& so, Condition cond) {
- EmitType01(cond, so.type(), ORR, 0, rn, rd, so);
+void Arm32Assembler::orr(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), ORR, set_cc, rn, rd, so);
}
-void Arm32Assembler::orrs(Register rd, Register rn,
- const ShifterOperand& so, Condition cond) {
- EmitType01(cond, so.type(), ORR, 1, rn, rd, so);
-}
-
-
-void Arm32Assembler::mov(Register rd, const ShifterOperand& so, Condition cond) {
- EmitType01(cond, so.type(), MOV, 0, R0, rd, so);
-}
-
-
-void Arm32Assembler::movs(Register rd, const ShifterOperand& so, Condition cond) {
- EmitType01(cond, so.type(), MOV, 1, R0, rd, so);
+void Arm32Assembler::mov(Register rd, const ShifterOperand& so,
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), MOV, set_cc, R0, rd, so);
}
void Arm32Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitType01(cond, so.type(), BIC, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), BIC, set_cc, rn, rd, so);
}
-void Arm32Assembler::mvn(Register rd, const ShifterOperand& so, Condition cond) {
- EmitType01(cond, so.type(), MVN, 0, R0, rd, so);
-}
-
-
-void Arm32Assembler::mvns(Register rd, const ShifterOperand& so, Condition cond) {
- EmitType01(cond, so.type(), MVN, 1, R0, rd, so);
+void Arm32Assembler::mvn(Register rd, const ShifterOperand& so,
+ Condition cond, SetCc set_cc) {
+ EmitType01(cond, so.type(), MVN, set_cc, R0, rd, so);
}
@@ -573,7 +541,7 @@
void Arm32Assembler::MarkExceptionHandler(Label* label) {
- EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0));
+ EmitType01(AL, 1, TST, kCcSet, PC, R0, ShifterOperand(0));
Label l;
b(&l);
EmitBranch(AL, label, false);
@@ -590,7 +558,7 @@
void Arm32Assembler::EmitType01(Condition cond,
int type,
Opcode opcode,
- int set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so) {
@@ -599,7 +567,7 @@
int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
type << kTypeShift |
static_cast<int32_t>(opcode) << kOpcodeShift |
- set_cc << kSShift |
+ (set_cc == kCcSet ? 1 : 0) << kSShift |
static_cast<int32_t>(rn) << kRnShift |
static_cast<int32_t>(rd) << kRdShift |
so.encodingArm();
@@ -1158,96 +1126,60 @@
void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CHECK_LE(shift_imm, 31u);
- if (setcc) {
- movs(rd, ShifterOperand(rm, LSL, shift_imm), cond);
- } else {
- mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
- }
+ mov(rd, ShifterOperand(rm, LSL, shift_imm), cond, set_cc);
}
void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CHECK(1u <= shift_imm && shift_imm <= 32u);
if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
- if (setcc) {
- movs(rd, ShifterOperand(rm, LSR, shift_imm), cond);
- } else {
- mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
- }
+ mov(rd, ShifterOperand(rm, LSR, shift_imm), cond, set_cc);
}
void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CHECK(1u <= shift_imm && shift_imm <= 32u);
if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
- if (setcc) {
- movs(rd, ShifterOperand(rm, ASR, shift_imm), cond);
- } else {
- mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
- }
+ mov(rd, ShifterOperand(rm, ASR, shift_imm), cond, set_cc);
}
void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CHECK(1u <= shift_imm && shift_imm <= 31u);
- if (setcc) {
- movs(rd, ShifterOperand(rm, ROR, shift_imm), cond);
- } else {
- mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
- }
+ mov(rd, ShifterOperand(rm, ROR, shift_imm), cond, set_cc);
}
-void Arm32Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) {
- if (setcc) {
- movs(rd, ShifterOperand(rm, ROR, 0), cond);
- } else {
- mov(rd, ShifterOperand(rm, ROR, 0), cond);
- }
+void Arm32Assembler::Rrx(Register rd, Register rm, Condition cond, SetCc set_cc) {
+ mov(rd, ShifterOperand(rm, ROR, 0), cond, set_cc);
}
void Arm32Assembler::Lsl(Register rd, Register rm, Register rn,
- bool setcc, Condition cond) {
- if (setcc) {
- movs(rd, ShifterOperand(rm, LSL, rn), cond);
- } else {
- mov(rd, ShifterOperand(rm, LSL, rn), cond);
- }
+ Condition cond, SetCc set_cc) {
+ mov(rd, ShifterOperand(rm, LSL, rn), cond, set_cc);
}
void Arm32Assembler::Lsr(Register rd, Register rm, Register rn,
- bool setcc, Condition cond) {
- if (setcc) {
- movs(rd, ShifterOperand(rm, LSR, rn), cond);
- } else {
- mov(rd, ShifterOperand(rm, LSR, rn), cond);
- }
+ Condition cond, SetCc set_cc) {
+ mov(rd, ShifterOperand(rm, LSR, rn), cond, set_cc);
}
void Arm32Assembler::Asr(Register rd, Register rm, Register rn,
- bool setcc, Condition cond) {
- if (setcc) {
- movs(rd, ShifterOperand(rm, ASR, rn), cond);
- } else {
- mov(rd, ShifterOperand(rm, ASR, rn), cond);
- }
+ Condition cond, SetCc set_cc) {
+ mov(rd, ShifterOperand(rm, ASR, rn), cond, set_cc);
}
void Arm32Assembler::Ror(Register rd, Register rm, Register rn,
- bool setcc, Condition cond) {
- if (setcc) {
- movs(rd, ShifterOperand(rm, ROR, rn), cond);
- } else {
- mov(rd, ShifterOperand(rm, ROR, rn), cond);
- }
+ Condition cond, SetCc set_cc) {
+ mov(rd, ShifterOperand(rm, ROR, rn), cond, set_cc);
}
void Arm32Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
@@ -1434,24 +1366,24 @@
Condition cond) {
ShifterOperand shifter_op;
if (ShifterOperandCanHoldArm32(value, &shifter_op)) {
- adds(rd, rn, shifter_op, cond);
+ add(rd, rn, shifter_op, cond, kCcSet);
} else if (ShifterOperandCanHoldArm32(-value, &shifter_op)) {
- subs(rd, rn, shifter_op, cond);
+ sub(rd, rn, shifter_op, cond, kCcSet);
} else {
CHECK(rn != IP);
if (ShifterOperandCanHoldArm32(~value, &shifter_op)) {
mvn(IP, shifter_op, cond);
- adds(rd, rn, ShifterOperand(IP), cond);
+ add(rd, rn, ShifterOperand(IP), cond, kCcSet);
} else if (ShifterOperandCanHoldArm32(~(-value), &shifter_op)) {
mvn(IP, shifter_op, cond);
- subs(rd, rn, ShifterOperand(IP), cond);
+ sub(rd, rn, ShifterOperand(IP), cond, kCcSet);
} else {
movw(IP, Low16Bits(value), cond);
uint16_t value_high = High16Bits(value);
if (value_high != 0) {
movt(IP, value_high, cond);
}
- adds(rd, rn, ShifterOperand(IP), cond);
+ add(rd, rn, ShifterOperand(IP), cond, kCcSet);
}
}
}
diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h
index 1c38eec..b96bb74 100644
--- a/compiler/utils/arm/assembler_arm32.h
+++ b/compiler/utils/arm/assembler_arm32.h
@@ -39,25 +39,29 @@
}
// Data-processing instructions.
- void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void and_(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void eor(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void sub(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void add(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void adc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-
- void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
@@ -67,16 +71,17 @@
void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void orr(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void mov(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void movs(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void mov(Register rd, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void bic(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void mvn(Register rd, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
// Miscellaneous data-processing instructions.
void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
@@ -204,25 +209,25 @@
void bl(Label* label, Condition cond = AL) OVERRIDE;
void blx(Register rm, Condition cond = AL) OVERRIDE;
void bx(Register rm, Condition cond = AL) OVERRIDE;
- void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Rrx(Register rd, Register rm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
+ virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Rrx(Register rd, Register rm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Asr(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Ror(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) OVERRIDE;
+ virtual void Lsl(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Lsr(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Asr(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Ror(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
void Push(Register rd, Condition cond = AL) OVERRIDE;
void Pop(Register rd, Condition cond = AL) OVERRIDE;
@@ -305,7 +310,7 @@
void EmitType01(Condition cond,
int type,
Opcode opcode,
- int set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so);
diff --git a/compiler/utils/arm/assembler_arm32_test.cc b/compiler/utils/arm/assembler_arm32_test.cc
index efd517b..e6412ac 100644
--- a/compiler/utils/arm/assembler_arm32_test.cc
+++ b/compiler/utils/arm/assembler_arm32_test.cc
@@ -42,7 +42,8 @@
class AssemblerArm32Test : public AssemblerArmTest<arm::Arm32Assembler,
arm::Register, arm::SRegister,
- uint32_t, arm::ShifterOperand, arm::Condition> {
+ uint32_t, arm::ShifterOperand, arm::Condition,
+ arm::SetCc> {
protected:
std::string GetArchitectureString() OVERRIDE {
return "arm";
@@ -125,6 +126,10 @@
conditions_.push_back(arm::Condition::AL);
}
+ set_ccs_.push_back(arm::kCcDontCare);
+ set_ccs_.push_back(arm::kCcSet);
+ set_ccs_.push_back(arm::kCcKeep);
+
shifter_operands_.push_back(arm::ShifterOperand(0));
shifter_operands_.push_back(arm::ShifterOperand(1));
shifter_operands_.push_back(arm::ShifterOperand(2));
@@ -240,6 +245,15 @@
return oss.str();
}
+ std::vector<arm::SetCc>& GetSetCcs() OVERRIDE {
+ return set_ccs_;
+ }
+
+ std::string GetSetCcString(arm::SetCc s) OVERRIDE {
+ // For arm32, kCcDontCare defaults to not setting condition codes.
+ return s == arm::kCcSet ? "s" : "";
+ }
+
arm::Register GetPCRegister() OVERRIDE {
return arm::R15;
}
@@ -369,12 +383,12 @@
size_t cond_index = after_cond.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
cond_index = after_cond_filter.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond_filter.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond_filter.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
if (EvalFilterString(after_cond_filter)) {
continue;
@@ -384,6 +398,30 @@
}
}
+ void TemplateHelper(std::function<void(arm::SetCc)> f, int depth ATTRIBUTE_UNUSED,
+ bool without_pc ATTRIBUTE_UNUSED, std::string fmt, std::string filter,
+ std::ostringstream& oss) {
+ for (arm::SetCc s : GetSetCcs()) {
+ std::string after_cond = fmt;
+ std::string after_cond_filter = filter;
+
+ size_t cond_index = after_cond.find(SET_CC_TOKEN);
+ if (cond_index != std::string::npos) {
+ after_cond.replace(cond_index, ConstexprStrLen(SET_CC_TOKEN), GetSetCcString(s));
+ }
+
+ cond_index = after_cond_filter.find(SET_CC_TOKEN);
+ if (cond_index != std::string::npos) {
+ after_cond_filter.replace(cond_index, ConstexprStrLen(SET_CC_TOKEN), GetSetCcString(s));
+ }
+ if (EvalFilterString(after_cond_filter)) {
+ continue;
+ }
+
+ ExecuteAndPrint([&] () { f(s); }, after_cond, oss);
+ }
+ }
+
template <typename... Args>
void TemplateHelper(std::function<void(arm::Register, Args...)> f, int depth, bool without_pc,
std::string fmt, std::string filter, std::ostringstream& oss) {
@@ -449,12 +487,12 @@
size_t cond_index = after_cond.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
cond_index = after_cond_filter.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond_filter.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond_filter.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
if (EvalFilterString(after_cond_filter)) {
continue;
@@ -466,25 +504,51 @@
}
}
- template <typename T1, typename T2>
- std::function<void(T1, T2)> GetBoundFunction2(void (arm::Arm32Assembler::*f)(T1, T2)) {
+ template <typename... Args>
+ void TemplateHelper(std::function<void(arm::SetCc, Args...)> f, int depth, bool without_pc,
+ std::string fmt, std::string filter, std::ostringstream& oss) {
+ for (arm::SetCc s : GetSetCcs()) {
+ std::string after_cond = fmt;
+ std::string after_cond_filter = filter;
+
+ size_t cond_index = after_cond.find(SET_CC_TOKEN);
+ if (cond_index != std::string::npos) {
+ after_cond.replace(cond_index, ConstexprStrLen(SET_CC_TOKEN), GetSetCcString(s));
+ }
+
+ cond_index = after_cond_filter.find(SET_CC_TOKEN);
+ if (cond_index != std::string::npos) {
+ after_cond_filter.replace(cond_index, ConstexprStrLen(SET_CC_TOKEN), GetSetCcString(s));
+ }
+ if (EvalFilterString(after_cond_filter)) {
+ continue;
+ }
+
+ auto lambda = [&] (Args... args) { f(s, args...); }; // NOLINT [readability/braces] [4]
+ TemplateHelper(std::function<void(Args...)>(lambda), depth, without_pc,
+ after_cond, after_cond_filter, oss);
+ }
+ }
+
+ template <typename Assembler, typename T1, typename T2>
+ std::function<void(T1, T2)> GetBoundFunction2(void (Assembler::*f)(T1, T2)) {
return std::bind(f, GetAssembler(), _1, _2);
}
- template <typename T1, typename T2, typename T3>
- std::function<void(T1, T2, T3)> GetBoundFunction3(void (arm::Arm32Assembler::*f)(T1, T2, T3)) {
+ template <typename Assembler, typename T1, typename T2, typename T3>
+ std::function<void(T1, T2, T3)> GetBoundFunction3(void (Assembler::*f)(T1, T2, T3)) {
return std::bind(f, GetAssembler(), _1, _2, _3);
}
- template <typename T1, typename T2, typename T3, typename T4>
+ template <typename Assembler, typename T1, typename T2, typename T3, typename T4>
std::function<void(T1, T2, T3, T4)> GetBoundFunction4(
- void (arm::Arm32Assembler::*f)(T1, T2, T3, T4)) {
+ void (Assembler::*f)(T1, T2, T3, T4)) {
return std::bind(f, GetAssembler(), _1, _2, _3, _4);
}
- template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ template <typename Assembler, typename T1, typename T2, typename T3, typename T4, typename T5>
std::function<void(T1, T2, T3, T4, T5)> GetBoundFunction5(
- void (arm::Arm32Assembler::*f)(T1, T2, T3, T4, T5)) {
+ void (Assembler::*f)(T1, T2, T3, T4, T5)) {
return std::bind(f, GetAssembler(), _1, _2, _3, _4, _5);
}
@@ -503,26 +567,26 @@
DriverStr(oss.str(), test_name);
}
- template <typename... Args>
- void T2Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
+ template <typename Assembler, typename... Args>
+ void T2Helper(void (Assembler::*f)(Args...), bool without_pc, std::string fmt,
std::string test_name, std::string filter = "") {
GenericTemplateHelper(GetBoundFunction2(f), without_pc, fmt, test_name, filter);
}
- template <typename... Args>
- void T3Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
+ template <typename Assembler, typename... Args>
+ void T3Helper(void (Assembler::*f)(Args...), bool without_pc, std::string fmt,
std::string test_name, std::string filter = "") {
GenericTemplateHelper(GetBoundFunction3(f), without_pc, fmt, test_name, filter);
}
- template <typename... Args>
- void T4Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
+ template <typename Assembler, typename... Args>
+ void T4Helper(void (Assembler::*f)(Args...), bool without_pc, std::string fmt,
std::string test_name, std::string filter = "") {
GenericTemplateHelper(GetBoundFunction4(f), without_pc, fmt, test_name, filter);
}
- template <typename... Args>
- void T5Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
+ template <typename Assembler, typename... Args>
+ void T5Helper(void (Assembler::*f)(Args...), bool without_pc, std::string fmt,
std::string test_name, std::string filter = "") {
GenericTemplateHelper(GetBoundFunction5(f), without_pc, fmt, test_name, filter);
}
@@ -573,6 +637,7 @@
std::vector<arm::Register*> registers_;
std::vector<arm::Condition> conditions_;
+ std::vector<arm::SetCc> set_ccs_;
std::vector<arm::ShifterOperand> shifter_operands_;
};
@@ -656,15 +721,23 @@
}
TEST_F(AssemblerArm32Test, And) {
- T4Helper(&arm::Arm32Assembler::and_, true, "and{cond} {reg1}, {reg2}, {shift}", "and");
+ T5Helper(&arm::Arm32Assembler::and_, true, "and{cond}{s} {reg1}, {reg2}, {shift}", "and");
+}
+
+TEST_F(AssemblerArm32Test, Ands) {
+ T4Helper(&arm::Arm32Assembler::ands, true, "and{cond}s {reg1}, {reg2}, {shift}", "ands");
}
TEST_F(AssemblerArm32Test, Eor) {
- T4Helper(&arm::Arm32Assembler::eor, true, "eor{cond} {reg1}, {reg2}, {shift}", "eor");
+ T5Helper(&arm::Arm32Assembler::eor, true, "eor{cond}{s} {reg1}, {reg2}, {shift}", "eor");
+}
+
+TEST_F(AssemblerArm32Test, Eors) {
+ T4Helper(&arm::Arm32Assembler::eors, true, "eor{cond}s {reg1}, {reg2}, {shift}", "eors");
}
TEST_F(AssemblerArm32Test, Orr) {
- T4Helper(&arm::Arm32Assembler::orr, true, "orr{cond} {reg1}, {reg2}, {shift}", "orr");
+ T5Helper(&arm::Arm32Assembler::orr, true, "orr{cond}{s} {reg1}, {reg2}, {shift}", "orr");
}
TEST_F(AssemblerArm32Test, Orrs) {
@@ -672,11 +745,15 @@
}
TEST_F(AssemblerArm32Test, Bic) {
- T4Helper(&arm::Arm32Assembler::bic, true, "bic{cond} {reg1}, {reg2}, {shift}", "bic");
+ T5Helper(&arm::Arm32Assembler::bic, true, "bic{cond}{s} {reg1}, {reg2}, {shift}", "bic");
+}
+
+TEST_F(AssemblerArm32Test, Bics) {
+ T4Helper(&arm::Arm32Assembler::bics, true, "bic{cond}s {reg1}, {reg2}, {shift}", "bics");
}
TEST_F(AssemblerArm32Test, Mov) {
- T3Helper(&arm::Arm32Assembler::mov, true, "mov{cond} {reg1}, {shift}", "mov");
+ T4Helper(&arm::Arm32Assembler::mov, true, "mov{cond}{s} {reg1}, {shift}", "mov");
}
TEST_F(AssemblerArm32Test, Movs) {
@@ -684,7 +761,7 @@
}
TEST_F(AssemblerArm32Test, Mvn) {
- T3Helper(&arm::Arm32Assembler::mvn, true, "mvn{cond} {reg1}, {shift}", "mvn");
+ T4Helper(&arm::Arm32Assembler::mvn, true, "mvn{cond}{s} {reg1}, {shift}", "mvn");
}
TEST_F(AssemblerArm32Test, Mvns) {
@@ -692,7 +769,7 @@
}
TEST_F(AssemblerArm32Test, Add) {
- T4Helper(&arm::Arm32Assembler::add, false, "add{cond} {reg1}, {reg2}, {shift}", "add");
+ T5Helper(&arm::Arm32Assembler::add, false, "add{cond}{s} {reg1}, {reg2}, {shift}", "add");
}
TEST_F(AssemblerArm32Test, Adds) {
@@ -700,11 +777,15 @@
}
TEST_F(AssemblerArm32Test, Adc) {
- T4Helper(&arm::Arm32Assembler::adc, false, "adc{cond} {reg1}, {reg2}, {shift}", "adc");
+ T5Helper(&arm::Arm32Assembler::adc, false, "adc{cond}{s} {reg1}, {reg2}, {shift}", "adc");
+}
+
+TEST_F(AssemblerArm32Test, Adcs) {
+ T4Helper(&arm::Arm32Assembler::adcs, false, "adc{cond}s {reg1}, {reg2}, {shift}", "adcs");
}
TEST_F(AssemblerArm32Test, Sub) {
- T4Helper(&arm::Arm32Assembler::sub, false, "sub{cond} {reg1}, {reg2}, {shift}", "sub");
+ T5Helper(&arm::Arm32Assembler::sub, false, "sub{cond}{s} {reg1}, {reg2}, {shift}", "sub");
}
TEST_F(AssemblerArm32Test, Subs) {
@@ -712,11 +793,15 @@
}
TEST_F(AssemblerArm32Test, Sbc) {
- T4Helper(&arm::Arm32Assembler::sbc, false, "sbc{cond} {reg1}, {reg2}, {shift}", "sbc");
+ T5Helper(&arm::Arm32Assembler::sbc, false, "sbc{cond}{s} {reg1}, {reg2}, {shift}", "sbc");
+}
+
+TEST_F(AssemblerArm32Test, Sbcs) {
+ T4Helper(&arm::Arm32Assembler::sbcs, false, "sbc{cond}s {reg1}, {reg2}, {shift}", "sbcs");
}
TEST_F(AssemblerArm32Test, Rsb) {
- T4Helper(&arm::Arm32Assembler::rsb, true, "rsb{cond} {reg1}, {reg2}, {shift}", "rsb");
+ T5Helper(&arm::Arm32Assembler::rsb, true, "rsb{cond}{s} {reg1}, {reg2}, {shift}", "rsb");
}
TEST_F(AssemblerArm32Test, Rsbs) {
@@ -724,7 +809,11 @@
}
TEST_F(AssemblerArm32Test, Rsc) {
- T4Helper(&arm::Arm32Assembler::rsc, true, "rsc{cond} {reg1}, {reg2}, {shift}", "rsc");
+ T5Helper(&arm::Arm32Assembler::rsc, true, "rsc{cond}{s} {reg1}, {reg2}, {shift}", "rsc");
+}
+
+TEST_F(AssemblerArm32Test, Rscs) {
+ T4Helper(&arm::Arm32Assembler::rscs, false, "rsc{cond}s {reg1}, {reg2}, {shift}", "rscs");
}
/* TODO: Need better filter support.
diff --git a/compiler/utils/arm/assembler_arm_test.h b/compiler/utils/arm/assembler_arm_test.h
index 838abb6..a85a05e 100644
--- a/compiler/utils/arm/assembler_arm_test.h
+++ b/compiler/utils/arm/assembler_arm_test.h
@@ -21,7 +21,13 @@
namespace art {
-template<typename Ass, typename Reg, typename FPReg, typename Imm, typename SOp, typename Cond>
+template<typename Ass,
+ typename Reg,
+ typename FPReg,
+ typename Imm,
+ typename SOp,
+ typename Cond,
+ typename SetCc>
class AssemblerArmTest : public AssemblerTest<Ass, Reg, FPReg, Imm> {
public:
typedef AssemblerTest<Ass, Reg, FPReg, Imm> Base;
@@ -94,7 +100,7 @@
size_t cond_index = after_cond.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
for (Imm i : immediates1) {
@@ -185,7 +191,7 @@
size_t cond_index = after_cond.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
for (std::pair<Imm, Imm>& pair : immediates) {
@@ -271,7 +277,7 @@
size_t cond_index = after_cond.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
for (auto reg1 : reg1_registers) {
@@ -337,7 +343,7 @@
size_t cond_index = after_cond.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
for (auto reg1 : reg1_registers) {
@@ -401,7 +407,7 @@
size_t cond_index = after_cond.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
for (const SOp& shift : shifts) {
@@ -457,7 +463,7 @@
size_t cond_index = after_cond.find(COND_TOKEN);
if (cond_index != std::string::npos) {
- after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+ after_cond.replace(cond_index, ConstexprStrLen(COND_TOKEN), GetConditionString(c));
}
for (const SOp& shift : shifts) {
@@ -511,6 +517,9 @@
virtual std::vector<Cond>& GetConditions() = 0;
virtual std::string GetConditionString(Cond c) = 0;
+ virtual std::vector<SetCc>& GetSetCcs() = 0;
+ virtual std::string GetSetCcString(SetCc s) = 0;
+
virtual std::vector<SOp>& GetShiftOperands() = 0;
virtual std::string GetShiftString(SOp sop) = 0;
@@ -534,6 +543,7 @@
static constexpr const char* REG3_TOKEN = "{reg3}";
static constexpr const char* REG4_TOKEN = "{reg4}";
static constexpr const char* COND_TOKEN = "{cond}";
+ static constexpr const char* SET_CC_TOKEN = "{s}";
static constexpr const char* SHIFT_TOKEN = "{shift}";
private:
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 4e918e9..90ed10c 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -417,128 +417,96 @@
}
void Thumb2Assembler::and_(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, AND, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, AND, set_cc, rn, rd, so);
}
void Thumb2Assembler::eor(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, EOR, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, EOR, set_cc, rn, rd, so);
}
void Thumb2Assembler::sub(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, SUB, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, SUB, set_cc, rn, rd, so);
}
void Thumb2Assembler::rsb(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, RSB, 0, rn, rd, so);
-}
-
-
-void Thumb2Assembler::rsbs(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, RSB, 1, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, RSB, set_cc, rn, rd, so);
}
void Thumb2Assembler::add(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, ADD, 0, rn, rd, so);
-}
-
-
-void Thumb2Assembler::adds(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, ADD, 1, rn, rd, so);
-}
-
-
-void Thumb2Assembler::subs(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, SUB, 1, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, ADD, set_cc, rn, rd, so);
}
void Thumb2Assembler::adc(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, ADC, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, ADC, set_cc, rn, rd, so);
}
void Thumb2Assembler::sbc(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, SBC, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, SBC, set_cc, rn, rd, so);
}
void Thumb2Assembler::rsc(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, RSC, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, RSC, set_cc, rn, rd, so);
}
void Thumb2Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) {
CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker.
- EmitDataProcessing(cond, TST, 1, rn, R0, so);
+ EmitDataProcessing(cond, TST, kCcSet, rn, R0, so);
}
void Thumb2Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) {
CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker.
- EmitDataProcessing(cond, TEQ, 1, rn, R0, so);
+ EmitDataProcessing(cond, TEQ, kCcSet, rn, R0, so);
}
void Thumb2Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) {
- EmitDataProcessing(cond, CMP, 1, rn, R0, so);
+ EmitDataProcessing(cond, CMP, kCcSet, rn, R0, so);
}
void Thumb2Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) {
- EmitDataProcessing(cond, CMN, 1, rn, R0, so);
+ EmitDataProcessing(cond, CMN, kCcSet, rn, R0, so);
}
-void Thumb2Assembler::orr(Register rd, Register rn,
- const ShifterOperand& so, Condition cond) {
- EmitDataProcessing(cond, ORR, 0, rn, rd, so);
+void Thumb2Assembler::orr(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, ORR, set_cc, rn, rd, so);
}
-void Thumb2Assembler::orrs(Register rd, Register rn,
- const ShifterOperand& so, Condition cond) {
- EmitDataProcessing(cond, ORR, 1, rn, rd, so);
-}
-
-
-void Thumb2Assembler::mov(Register rd, const ShifterOperand& so, Condition cond) {
- EmitDataProcessing(cond, MOV, 0, R0, rd, so);
-}
-
-
-void Thumb2Assembler::movs(Register rd, const ShifterOperand& so, Condition cond) {
- EmitDataProcessing(cond, MOV, 1, R0, rd, so);
+void Thumb2Assembler::mov(Register rd, const ShifterOperand& so,
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, MOV, set_cc, R0, rd, so);
}
void Thumb2Assembler::bic(Register rd, Register rn, const ShifterOperand& so,
- Condition cond) {
- EmitDataProcessing(cond, BIC, 0, rn, rd, so);
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, BIC, set_cc, rn, rd, so);
}
-void Thumb2Assembler::mvn(Register rd, const ShifterOperand& so, Condition cond) {
- EmitDataProcessing(cond, MVN, 0, R0, rd, so);
-}
-
-
-void Thumb2Assembler::mvns(Register rd, const ShifterOperand& so, Condition cond) {
- EmitDataProcessing(cond, MVN, 1, R0, rd, so);
+void Thumb2Assembler::mvn(Register rd, const ShifterOperand& so,
+ Condition cond, SetCc set_cc) {
+ EmitDataProcessing(cond, MVN, set_cc, R0, rd, so);
}
@@ -1054,7 +1022,7 @@
void Thumb2Assembler::MarkExceptionHandler(Label* label) {
- EmitDataProcessing(AL, TST, 1, PC, R0, ShifterOperand(0));
+ EmitDataProcessing(AL, TST, kCcSet, PC, R0, ShifterOperand(0));
Label l;
b(&l);
EmitBranch(AL, label, false, false);
@@ -1075,9 +1043,9 @@
}
-bool Thumb2Assembler::Is32BitDataProcessing(Condition cond ATTRIBUTE_UNUSED,
+bool Thumb2Assembler::Is32BitDataProcessing(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so) {
@@ -1086,7 +1054,7 @@
}
// Check special case for SP relative ADD and SUB immediate.
- if ((opcode == ADD || opcode == SUB) && rn == SP && so.IsImmediate()) {
+ if ((opcode == ADD || opcode == SUB) && rn == SP && so.IsImmediate() && set_cc != kCcSet) {
// If the immediate is in range, use 16 bit.
if (rd == SP) {
if (so.GetImmediate() < (1 << 9)) { // 9 bit immediate.
@@ -1099,8 +1067,10 @@
}
}
- bool can_contain_high_register = (opcode == MOV)
- || ((opcode == ADD) && (rn == rd) && !set_cc);
+ bool can_contain_high_register =
+ (opcode == CMP) ||
+ (opcode == MOV && set_cc != kCcSet) ||
+ ((opcode == ADD) && (rn == rd) && set_cc != kCcSet);
if (IsHighRegister(rd) || IsHighRegister(rn)) {
if (!can_contain_high_register) {
@@ -1146,39 +1116,80 @@
}
if (so.IsImmediate()) {
- if (rn_is_valid && rn != rd) {
- // The only thumb1 instruction with a register and an immediate are ADD and SUB. The
- // immediate must be 3 bits.
- if (opcode != ADD && opcode != SUB) {
+ if (opcode == RSB) {
+ DCHECK(rn_is_valid);
+ if (so.GetImmediate() != 0u) {
return true;
- } else {
- // Check that the immediate is 3 bits for ADD and SUB.
- if (so.GetImmediate() >= 8) {
+ }
+ } else if (rn_is_valid && rn != rd) {
+ // The only thumb1 instructions with a register and an immediate are ADD and SUB
+ // with a 3-bit immediate, and RSB with zero immediate.
+ if (opcode == ADD || opcode == SUB) {
+ if (!IsUint<3>(so.GetImmediate())) {
return true;
}
+ } else {
+ return true;
}
} else {
// ADD, SUB, CMP and MOV may be thumb1 only if the immediate is 8 bits.
if (!(opcode == ADD || opcode == SUB || opcode == MOV || opcode == CMP)) {
return true;
} else {
- if (so.GetImmediate() > 255) {
+ if (!IsUint<8>(so.GetImmediate())) {
return true;
}
}
}
- }
-
- // Check for register shift operand.
- if (so.IsRegister() && so.IsShift()) {
- if (opcode != MOV) {
- return true;
- }
- // Check for MOV with an ROR.
- if (so.GetShift() == ROR) {
- if (so.GetImmediate() != 0) {
+ } else {
+ DCHECK(so.IsRegister());
+ if (so.IsShift()) {
+ // Shift operand - check if it is a MOV convertible to a 16-bit shift instruction.
+ if (opcode != MOV) {
return true;
}
+ // Check for MOV with an ROR/RRX. There is no 16-bit ROR immediate and no 16-bit RRX.
+ if (so.GetShift() == ROR || so.GetShift() == RRX) {
+ return true;
+ }
+ // 16-bit shifts set condition codes if and only if outside IT block,
+ // i.e. if and only if cond == AL.
+ if ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet) {
+ return true;
+ }
+ } else {
+ // Register operand without shift.
+ switch (opcode) {
+ case ADD:
+ // The 16-bit ADD that cannot contain high registers can set condition codes
+ // if and only if outside IT block, i.e. if and only if cond == AL.
+ if (!can_contain_high_register &&
+ ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet)) {
+ return true;
+ }
+ break;
+ case AND:
+ case BIC:
+ case EOR:
+ case ORR:
+ case MVN:
+ case ADC:
+ case SUB:
+ case SBC:
+ // These 16-bit opcodes set condition codes if and only if outside IT block,
+ // i.e. if and only if cond == AL.
+ if ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet) {
+ return true;
+ }
+ break;
+ case RSB:
+ case RSC:
+ // No 16-bit RSB/RSC Rd, Rm, Rn. It would be equivalent to SUB/SBC Rd, Rn, Rm.
+ return true;
+ case CMP:
+ default:
+ break;
+ }
}
}
@@ -1189,7 +1200,7 @@
void Thumb2Assembler::Emit32BitDataProcessing(Condition cond ATTRIBUTE_UNUSED,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so) {
@@ -1203,10 +1214,10 @@
case ADC: thumb_opcode = 10U /* 0b1010 */; break;
case SBC: thumb_opcode = 11U /* 0b1011 */; break;
case RSC: break;
- case TST: thumb_opcode = 0U /* 0b0000 */; set_cc = true; rd = PC; break;
- case TEQ: thumb_opcode = 4U /* 0b0100 */; set_cc = true; rd = PC; break;
- case CMP: thumb_opcode = 13U /* 0b1101 */; set_cc = true; rd = PC; break;
- case CMN: thumb_opcode = 8U /* 0b1000 */; set_cc = true; rd = PC; break;
+ case TST: thumb_opcode = 0U /* 0b0000 */; DCHECK(set_cc == kCcSet); rd = PC; break;
+ case TEQ: thumb_opcode = 4U /* 0b0100 */; DCHECK(set_cc == kCcSet); rd = PC; break;
+ case CMP: thumb_opcode = 13U /* 0b1101 */; DCHECK(set_cc == kCcSet); rd = PC; break;
+ case CMN: thumb_opcode = 8U /* 0b1000 */; DCHECK(set_cc == kCcSet); rd = PC; break;
case ORR: thumb_opcode = 2U /* 0b0010 */; break;
case MOV: thumb_opcode = 2U /* 0b0010 */; rn = PC; break;
case BIC: thumb_opcode = 1U /* 0b0001 */; break;
@@ -1224,7 +1235,7 @@
if (so.IsImmediate()) {
// Check special cases.
if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) {
- if (!set_cc) {
+ if (set_cc != kCcSet) {
if (opcode == SUB) {
thumb_opcode = 5U;
} else if (opcode == ADD) {
@@ -1238,7 +1249,7 @@
uint32_t imm8 = imm & 0xff;
encoding = B31 | B30 | B29 | B28 |
- (set_cc ? B20 : B25) |
+ (set_cc == kCcSet ? B20 : B25) |
thumb_opcode << 21 |
rn << 16 |
rd << 8 |
@@ -1254,7 +1265,7 @@
}
encoding = B31 | B30 | B29 | B28 |
thumb_opcode << 21 |
- (set_cc ? B20 : 0) |
+ (set_cc == kCcSet ? B20 : 0) |
rn << 16 |
rd << 8 |
imm;
@@ -1263,7 +1274,7 @@
// Register (possibly shifted)
encoding = B31 | B30 | B29 | B27 | B25 |
thumb_opcode << 21 |
- (set_cc ? B20 : 0) |
+ (set_cc == kCcSet ? B20 : 0) |
rn << 16 |
rd << 8 |
so.encodingThumb();
@@ -1274,7 +1285,7 @@
void Thumb2Assembler::Emit16BitDataProcessing(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so) {
@@ -1304,19 +1315,25 @@
rn = so.GetRegister();
switch (so.GetShift()) {
- case LSL: thumb_opcode = 0U /* 0b00 */; break;
- case LSR: thumb_opcode = 1U /* 0b01 */; break;
- case ASR: thumb_opcode = 2U /* 0b10 */; break;
- case ROR:
- // ROR doesn't allow immediates.
- thumb_opcode = 7U /* 0b111 */;
- dp_opcode = 1U /* 0b01 */;
- opcode_shift = 6;
- use_immediate = false;
+ case LSL:
+ DCHECK_LE(immediate, 31u);
+ thumb_opcode = 0U /* 0b00 */;
break;
- case RRX: break;
+ case LSR:
+ DCHECK(1 <= immediate && immediate <= 32);
+ immediate &= 31; // 32 is encoded as 0.
+ thumb_opcode = 1U /* 0b01 */;
+ break;
+ case ASR:
+ DCHECK(1 <= immediate && immediate <= 32);
+ immediate &= 31; // 32 is encoded as 0.
+ thumb_opcode = 2U /* 0b10 */;
+ break;
+ case ROR: // No 16-bit ROR immediate.
+ case RRX: // No 16-bit RRX.
default:
- break;
+ LOG(FATAL) << "Unexpected shift: " << so.GetShift();
+ UNREACHABLE();
}
} else {
if (so.IsImmediate()) {
@@ -1334,6 +1351,9 @@
case ADC:
case SBC:
case BIC: {
+ // Sets condition codes if and only if outside IT block,
+ // check that it complies with set_cc.
+ DCHECK((cond == AL) ? set_cc != kCcKeep : set_cc != kCcSet);
if (rn == rd) {
rn = so.GetRegister();
} else {
@@ -1348,9 +1368,17 @@
rn = so.GetRegister();
break;
}
- case TST:
- case TEQ:
case MVN: {
+ // Sets condition codes if and only if outside IT block,
+ // check that it complies with set_cc.
+ DCHECK((cond == AL) ? set_cc != kCcKeep : set_cc != kCcSet);
+ CHECK_EQ(rn, 0);
+ rn = so.GetRegister();
+ break;
+ }
+ case TST:
+ case TEQ: {
+ DCHECK(set_cc == kCcSet);
CHECK_EQ(rn, 0);
rn = so.GetRegister();
break;
@@ -1371,6 +1399,7 @@
case TST: thumb_opcode = 8U /* 0b1000 */; CHECK(!use_immediate); break;
case MVN: thumb_opcode = 15U /* 0b1111 */; CHECK(!use_immediate); break;
case CMP: {
+ DCHECK(set_cc == kCcSet);
if (use_immediate) {
// T2 encoding.
dp_opcode = 0;
@@ -1378,6 +1407,13 @@
thumb_opcode = 5U /* 0b101 */;
rd_shift = 8;
rn_shift = 8;
+ } else if (IsHighRegister(rd) || IsHighRegister(rn)) {
+ // Special cmp for high registers.
+ dp_opcode = 1U /* 0b01 */;
+ opcode_shift = 7;
+ // Put the top bit of rd into the bottom bit of the opcode.
+ thumb_opcode = 10U /* 0b0001010 */ | static_cast<uint32_t>(rd) >> 3;
+ rd = static_cast<Register>(static_cast<uint32_t>(rd) & 7U /* 0b111 */);
} else {
thumb_opcode = 10U /* 0b1010 */;
}
@@ -1399,7 +1435,7 @@
rn_shift = 8;
} else {
rn = so.GetRegister();
- if (IsHighRegister(rn) || IsHighRegister(rd)) {
+ if (set_cc != kCcSet) {
// Special mov for high registers.
dp_opcode = 1U /* 0b01 */;
opcode_shift = 7;
@@ -1407,6 +1443,8 @@
thumb_opcode = 12U /* 0b0001100 */ | static_cast<uint32_t>(rd) >> 3;
rd = static_cast<Register>(static_cast<uint32_t>(rd) & 7U /* 0b111 */);
} else {
+ DCHECK(!IsHighRegister(rn));
+ DCHECK(!IsHighRegister(rd));
thumb_opcode = 0;
}
}
@@ -1436,9 +1474,9 @@
// ADD and SUB are complex enough to warrant their own emitter.
-void Thumb2Assembler::Emit16BitAddSub(Condition cond ATTRIBUTE_UNUSED,
+void Thumb2Assembler::Emit16BitAddSub(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so) {
@@ -1449,7 +1487,7 @@
uint8_t immediate_shift = 0;
bool use_immediate = false;
uint32_t immediate = 0; // Should be at most 9 bits but keep the full immediate for CHECKs.
- uint8_t thumb_opcode;;
+ uint8_t thumb_opcode;
if (so.IsImmediate()) {
use_immediate = true;
@@ -1460,7 +1498,7 @@
case ADD:
if (so.IsRegister()) {
Register rm = so.GetRegister();
- if (rn == rd && !set_cc) {
+ if (rn == rd && set_cc != kCcSet) {
// Can use T2 encoding (allows 4 bit registers)
dp_opcode = 1U /* 0b01 */;
opcode_shift = 10;
@@ -1471,6 +1509,12 @@
rd = static_cast<Register>(static_cast<uint32_t>(rd) & 7U /* 0b111 */);
} else {
// T1.
+ DCHECK(!IsHighRegister(rd));
+ DCHECK(!IsHighRegister(rn));
+ DCHECK(!IsHighRegister(rm));
+ // Sets condition codes if and only if outside IT block,
+ // check that it complies with set_cc.
+ DCHECK((cond == AL) ? set_cc != kCcKeep : set_cc != kCcSet);
opcode_shift = 9;
thumb_opcode = 12U /* 0b01100 */;
immediate = static_cast<uint32_t>(so.GetRegister());
@@ -1523,40 +1567,47 @@
case SUB:
if (so.IsRegister()) {
- // T1.
- opcode_shift = 9;
- thumb_opcode = 13U /* 0b01101 */;
- immediate = static_cast<uint32_t>(so.GetRegister());
- use_immediate = true;
- immediate_shift = 6;
- } else {
- if (rd == SP && rn == SP) {
- // SUB sp, sp, #imm
- dp_opcode = 2U /* 0b10 */;
- thumb_opcode = 0x61 /* 0b1100001 */;
- opcode_shift = 7;
- CHECK_LT(immediate, (1u << 9));
- CHECK_ALIGNED(immediate, 4);
+ // T1.
+ Register rm = so.GetRegister();
+ DCHECK(!IsHighRegister(rd));
+ DCHECK(!IsHighRegister(rn));
+ DCHECK(!IsHighRegister(rm));
+ // Sets condition codes if and only if outside IT block,
+ // check that it complies with set_cc.
+ DCHECK((cond == AL) ? set_cc != kCcKeep : set_cc != kCcSet);
+ opcode_shift = 9;
+ thumb_opcode = 13U /* 0b01101 */;
+ immediate = static_cast<uint32_t>(rm);
+ use_immediate = true;
+ immediate_shift = 6;
+ } else {
+ if (rd == SP && rn == SP) {
+ // SUB sp, sp, #imm
+ dp_opcode = 2U /* 0b10 */;
+ thumb_opcode = 0x61 /* 0b1100001 */;
+ opcode_shift = 7;
+ CHECK_LT(immediate, (1u << 9));
+ CHECK_ALIGNED(immediate, 4);
- // Remove rd and rn from instruction by orring it with immed and clearing bits.
- rn = R0;
- rd = R0;
- rd_shift = 0;
- rn_shift = 0;
- immediate >>= 2;
- } else if (rn != rd) {
- // Must use T1.
- opcode_shift = 9;
- thumb_opcode = 15U /* 0b01111 */;
- immediate_shift = 6;
- } else {
- // T2 encoding.
- opcode_shift = 11;
- thumb_opcode = 7U /* 0b111 */;
- rd_shift = 8;
- rn_shift = 8;
- }
- }
+ // Remove rd and rn from instruction by orring it with immed and clearing bits.
+ rn = R0;
+ rd = R0;
+ rd_shift = 0;
+ rn_shift = 0;
+ immediate >>= 2;
+ } else if (rn != rd) {
+ // Must use T1.
+ opcode_shift = 9;
+ thumb_opcode = 15U /* 0b01111 */;
+ immediate_shift = 6;
+ } else {
+ // T2 encoding.
+ opcode_shift = 11;
+ thumb_opcode = 7U /* 0b111 */;
+ rd_shift = 8;
+ rn_shift = 8;
+ }
+ }
break;
default:
LOG(FATAL) << "This opcode is not an ADD or SUB: " << opcode;
@@ -1575,7 +1626,7 @@
void Thumb2Assembler::EmitDataProcessing(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so) {
@@ -1589,9 +1640,15 @@
}
}
-void Thumb2Assembler::EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc) {
+void Thumb2Assembler::EmitShift(Register rd,
+ Register rm,
+ Shift shift,
+ uint8_t amount,
+ Condition cond,
+ SetCc set_cc) {
CHECK_LT(amount, (1 << 5));
- if (IsHighRegister(rd) || IsHighRegister(rm) || shift == ROR || shift == RRX) {
+ if ((IsHighRegister(rd) || IsHighRegister(rm) || shift == ROR || shift == RRX) ||
+ ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet)) {
uint16_t opcode = 0;
switch (shift) {
case LSL: opcode = 0U /* 0b00 */; break;
@@ -1605,7 +1662,7 @@
}
// 32 bit.
int32_t encoding = B31 | B30 | B29 | B27 | B25 | B22 |
- 0xf << 16 | (setcc ? B20 : 0);
+ 0xf << 16 | (set_cc == kCcSet ? B20 : 0);
uint32_t imm3 = amount >> 2;
uint32_t imm2 = amount & 3U /* 0b11 */;
encoding |= imm3 << 12 | imm2 << 6 | static_cast<int16_t>(rm) |
@@ -1628,10 +1685,16 @@
}
}
-void Thumb2Assembler::EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc) {
+void Thumb2Assembler::EmitShift(Register rd,
+ Register rn,
+ Shift shift,
+ Register rm,
+ Condition cond,
+ SetCc set_cc) {
CHECK_NE(shift, RRX);
bool must_be_32bit = false;
- if (IsHighRegister(rd) || IsHighRegister(rm) || IsHighRegister(rn) || rd != rn) {
+ if (IsHighRegister(rd) || IsHighRegister(rm) || IsHighRegister(rn) || rd != rn ||
+ ((cond == AL) ? set_cc == kCcKeep : set_cc == kCcSet)) {
must_be_32bit = true;
}
@@ -1648,7 +1711,7 @@
}
// 32 bit.
int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 |
- 0xf << 12 | (setcc ? B20 : 0);
+ 0xf << 12 | (set_cc == kCcSet ? B20 : 0);
encoding |= static_cast<int16_t>(rn) << 16 | static_cast<int16_t>(rm) |
static_cast<int16_t>(rd) << 8 | opcode << 21;
Emit32(encoding);
@@ -1658,6 +1721,7 @@
case LSL: opcode = 2U /* 0b0010 */; break;
case LSR: opcode = 3U /* 0b0011 */; break;
case ASR: opcode = 4U /* 0b0100 */; break;
+ case ROR: opcode = 7U /* 0b0111 */; break;
default:
LOG(FATAL) << "Unsupported thumb2 shift opcode";
UNREACHABLE();
@@ -2915,70 +2979,70 @@
void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CHECK_LE(shift_imm, 31u);
CheckCondition(cond);
- EmitShift(rd, rm, LSL, shift_imm, setcc);
+ EmitShift(rd, rm, LSL, shift_imm, cond, set_cc);
}
void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CHECK(1u <= shift_imm && shift_imm <= 32u);
if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
CheckCondition(cond);
- EmitShift(rd, rm, LSR, shift_imm, setcc);
+ EmitShift(rd, rm, LSR, shift_imm, cond, set_cc);
}
void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CHECK(1u <= shift_imm && shift_imm <= 32u);
if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
CheckCondition(cond);
- EmitShift(rd, rm, ASR, shift_imm, setcc);
+ EmitShift(rd, rm, ASR, shift_imm, cond, set_cc);
}
void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CHECK(1u <= shift_imm && shift_imm <= 31u);
CheckCondition(cond);
- EmitShift(rd, rm, ROR, shift_imm, setcc);
+ EmitShift(rd, rm, ROR, shift_imm, cond, set_cc);
}
-void Thumb2Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) {
+void Thumb2Assembler::Rrx(Register rd, Register rm, Condition cond, SetCc set_cc) {
CheckCondition(cond);
- EmitShift(rd, rm, RRX, rm, setcc);
+ EmitShift(rd, rm, RRX, rm, cond, set_cc);
}
void Thumb2Assembler::Lsl(Register rd, Register rm, Register rn,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CheckCondition(cond);
- EmitShift(rd, rm, LSL, rn, setcc);
+ EmitShift(rd, rm, LSL, rn, cond, set_cc);
}
void Thumb2Assembler::Lsr(Register rd, Register rm, Register rn,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CheckCondition(cond);
- EmitShift(rd, rm, LSR, rn, setcc);
+ EmitShift(rd, rm, LSR, rn, cond, set_cc);
}
void Thumb2Assembler::Asr(Register rd, Register rm, Register rn,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CheckCondition(cond);
- EmitShift(rd, rm, ASR, rn, setcc);
+ EmitShift(rd, rm, ASR, rn, cond, set_cc);
}
void Thumb2Assembler::Ror(Register rd, Register rm, Register rn,
- bool setcc, Condition cond) {
+ Condition cond, SetCc set_cc) {
CheckCondition(cond);
- EmitShift(rd, rm, ROR, rn, setcc);
+ EmitShift(rd, rm, ROR, rn, cond, set_cc);
}
@@ -3173,24 +3237,24 @@
Condition cond) {
ShifterOperand shifter_op;
if (ShifterOperandCanHold(rd, rn, ADD, value, &shifter_op)) {
- adds(rd, rn, shifter_op, cond);
+ add(rd, rn, shifter_op, cond, kCcSet);
} else if (ShifterOperandCanHold(rd, rn, ADD, -value, &shifter_op)) {
- subs(rd, rn, shifter_op, cond);
+ sub(rd, rn, shifter_op, cond, kCcSet);
} else {
CHECK(rn != IP);
if (ShifterOperandCanHold(rd, rn, MVN, ~value, &shifter_op)) {
mvn(IP, shifter_op, cond);
- adds(rd, rn, ShifterOperand(IP), cond);
+ add(rd, rn, ShifterOperand(IP), cond, kCcSet);
} else if (ShifterOperandCanHold(rd, rn, MVN, ~(-value), &shifter_op)) {
mvn(IP, shifter_op, cond);
- subs(rd, rn, ShifterOperand(IP), cond);
+ sub(rd, rn, ShifterOperand(IP), cond, kCcSet);
} else {
movw(IP, Low16Bits(value), cond);
uint16_t value_high = High16Bits(value);
if (value_high != 0) {
movt(IP, value_high, cond);
}
- adds(rd, rn, ShifterOperand(IP), cond);
+ add(rd, rn, ShifterOperand(IP), cond, kCcSet);
}
}
}
@@ -3316,7 +3380,7 @@
}
}
LoadImmediate(tmp_reg, offset, cond);
- add(tmp_reg, tmp_reg, ShifterOperand(base), cond);
+ add(tmp_reg, tmp_reg, ShifterOperand(base), AL);
base = tmp_reg;
offset = 0;
}
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index 41eb5d3..c802c27 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -63,25 +63,29 @@
void FinalizeCode() OVERRIDE;
// Data-processing instructions.
- void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void and_(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void eor(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void sub(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void add(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void adc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
-
- void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
@@ -91,16 +95,17 @@
void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void orr(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void mov(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void movs(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void mov(Register rd, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void bic(Register rd, Register rn, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
- void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
+ virtual void mvn(Register rd, const ShifterOperand& so,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
// Miscellaneous data-processing instructions.
void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
@@ -245,25 +250,25 @@
void blx(Register rm, Condition cond = AL) OVERRIDE;
void bx(Register rm, Condition cond = AL) OVERRIDE;
- void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Rrx(Register rd, Register rm, bool setcc = false,
- Condition cond = AL) OVERRIDE;
+ virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Rrx(Register rd, Register rm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
- void Lsl(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Lsr(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Asr(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) OVERRIDE;
- void Ror(Register rd, Register rm, Register rn, bool setcc = false,
- Condition cond = AL) OVERRIDE;
+ virtual void Lsl(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Lsr(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Asr(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
+ virtual void Ror(Register rd, Register rm, Register rn,
+ Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
void Push(Register rd, Condition cond = AL) OVERRIDE;
void Pop(Register rd, Condition cond = AL) OVERRIDE;
@@ -600,7 +605,7 @@
// Emit a single 32 or 16 bit data processing instruction.
void EmitDataProcessing(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so);
@@ -609,7 +614,7 @@
// in 16 bits?
bool Is32BitDataProcessing(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so);
@@ -617,7 +622,7 @@
// Emit a 32 bit data processing instruction.
void Emit32BitDataProcessing(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so);
@@ -625,14 +630,14 @@
// Emit a 16 bit data processing instruction.
void Emit16BitDataProcessing(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so);
void Emit16BitAddSub(Condition cond,
Opcode opcode,
- bool set_cc,
+ SetCc set_cc,
Register rn,
Register rd,
const ShifterOperand& so);
@@ -694,8 +699,10 @@
static int DecodeBranchOffset(int32_t inst);
int32_t EncodeTstOffset(int offset, int32_t inst);
int DecodeTstOffset(int32_t inst);
- void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc = false);
- void EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc = false);
+ void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount,
+ Condition cond = AL, SetCc set_cc = kCcDontCare);
+ void EmitShift(Register rd, Register rn, Shift shift, Register rm,
+ Condition cond = AL, SetCc set_cc = kCcDontCare);
// Whether the assembler can relocate branches. If false, unresolved branches will be
// emitted on 32bits.
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index cb01cea..b2a354b 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -199,6 +199,7 @@
TEST(Thumb2AssemblerTest, SimpleMov) {
arm::Thumb2Assembler assembler;
+ __ movs(R0, ShifterOperand(R1));
__ mov(R0, ShifterOperand(R1));
__ mov(R8, ShifterOperand(R9));
@@ -222,8 +223,8 @@
arm::Thumb2Assembler assembler;
__ mov(R0, ShifterOperand(R1));
- __ add(R0, R1, ShifterOperand(R2));
- __ add(R0, R1, ShifterOperand());
+ __ adds(R0, R1, ShifterOperand(R2));
+ __ add(R0, R1, ShifterOperand(0));
EmitAndCheck(&assembler, "SimpleMovAdd");
}
@@ -231,41 +232,132 @@
TEST(Thumb2AssemblerTest, DataProcessingRegister) {
arm::Thumb2Assembler assembler;
+ // 32 bit variants using low registers.
+ __ mvn(R0, ShifterOperand(R1), AL, kCcKeep);
+ __ add(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ sub(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ and_(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ orr(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ eor(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ bic(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ adc(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ sbc(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ rsb(R0, R1, ShifterOperand(R2), AL, kCcKeep);
+ __ teq(R0, ShifterOperand(R1));
+
+ // 16 bit variants using low registers.
+ __ movs(R0, ShifterOperand(R1));
+ __ mov(R0, ShifterOperand(R1), AL, kCcKeep);
+ __ mvns(R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R1), AL, kCcKeep);
+ __ adds(R0, R1, ShifterOperand(R2));
+ __ subs(R0, R1, ShifterOperand(R2));
+ __ adcs(R0, R0, ShifterOperand(R1));
+ __ sbcs(R0, R0, ShifterOperand(R1));
+ __ ands(R0, R0, ShifterOperand(R1));
+ __ orrs(R0, R0, ShifterOperand(R1));
+ __ eors(R0, R0, ShifterOperand(R1));
+ __ bics(R0, R0, ShifterOperand(R1));
+ __ tst(R0, ShifterOperand(R1));
+ __ cmp(R0, ShifterOperand(R1));
+ __ cmn(R0, ShifterOperand(R1));
+
+ // 16-bit variants using high registers.
+ __ mov(R1, ShifterOperand(R8), AL, kCcKeep);
+ __ mov(R9, ShifterOperand(R0), AL, kCcKeep);
+ __ mov(R8, ShifterOperand(R9), AL, kCcKeep);
+ __ add(R1, R1, ShifterOperand(R8), AL, kCcKeep);
+ __ add(R9, R9, ShifterOperand(R0), AL, kCcKeep);
+ __ add(R8, R8, ShifterOperand(R9), AL, kCcKeep);
+ __ cmp(R0, ShifterOperand(R9));
+ __ cmp(R8, ShifterOperand(R1));
+ __ cmp(R9, ShifterOperand(R8));
+
+ // The 16-bit RSBS Rd, Rn, #0, also known as NEGS Rd, Rn is specified using
+ // an immediate (0) but emitted without any, so we test it here.
+ __ rsbs(R0, R1, ShifterOperand(0));
+ __ rsbs(R0, R0, ShifterOperand(0)); // Check Rd == Rn code path.
+
+ // 32 bit variants using high registers that would be 16-bit if using low registers.
+ __ movs(R0, ShifterOperand(R8));
+ __ mvns(R0, ShifterOperand(R8));
+ __ add(R0, R1, ShifterOperand(R8), AL, kCcKeep);
+ __ adds(R0, R1, ShifterOperand(R8));
+ __ subs(R0, R1, ShifterOperand(R8));
+ __ adcs(R0, R0, ShifterOperand(R8));
+ __ sbcs(R0, R0, ShifterOperand(R8));
+ __ ands(R0, R0, ShifterOperand(R8));
+ __ orrs(R0, R0, ShifterOperand(R8));
+ __ eors(R0, R0, ShifterOperand(R8));
+ __ bics(R0, R0, ShifterOperand(R8));
+ __ tst(R0, ShifterOperand(R8));
+ __ cmn(R0, ShifterOperand(R8));
+ __ rsbs(R0, R8, ShifterOperand(0)); // Check that this is not emitted as 16-bit.
+ __ rsbs(R8, R8, ShifterOperand(0)); // Check that this is not emitted as 16-bit (Rd == Rn).
+
+ // 32-bit variants of instructions that would be 16-bit outside IT block.
+ __ it(arm::EQ);
+ __ mvns(R0, ShifterOperand(R1), arm::EQ);
+ __ it(arm::EQ);
+ __ adds(R0, R1, ShifterOperand(R2), arm::EQ);
+ __ it(arm::EQ);
+ __ subs(R0, R1, ShifterOperand(R2), arm::EQ);
+ __ it(arm::EQ);
+ __ adcs(R0, R0, ShifterOperand(R1), arm::EQ);
+ __ it(arm::EQ);
+ __ sbcs(R0, R0, ShifterOperand(R1), arm::EQ);
+ __ it(arm::EQ);
+ __ ands(R0, R0, ShifterOperand(R1), arm::EQ);
+ __ it(arm::EQ);
+ __ orrs(R0, R0, ShifterOperand(R1), arm::EQ);
+ __ it(arm::EQ);
+ __ eors(R0, R0, ShifterOperand(R1), arm::EQ);
+ __ it(arm::EQ);
+ __ bics(R0, R0, ShifterOperand(R1), arm::EQ);
+
+ // 16-bit variants of instructions that would be 32-bit outside IT block.
+ __ it(arm::EQ);
+ __ mvn(R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+ __ it(arm::EQ);
+ __ add(R0, R1, ShifterOperand(R2), arm::EQ, kCcKeep);
+ __ it(arm::EQ);
+ __ sub(R0, R1, ShifterOperand(R2), arm::EQ, kCcKeep);
+ __ it(arm::EQ);
+ __ adc(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+ __ it(arm::EQ);
+ __ sbc(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+ __ it(arm::EQ);
+ __ and_(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+ __ it(arm::EQ);
+ __ orr(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+ __ it(arm::EQ);
+ __ eor(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+ __ it(arm::EQ);
+ __ bic(R0, R0, ShifterOperand(R1), arm::EQ, kCcKeep);
+
+ // 16 bit variants selected for the default kCcDontCare.
__ mov(R0, ShifterOperand(R1));
__ mvn(R0, ShifterOperand(R1));
-
- // 32 bit variants.
+ __ add(R0, R0, ShifterOperand(R1));
__ add(R0, R1, ShifterOperand(R2));
__ sub(R0, R1, ShifterOperand(R2));
- __ and_(R0, R1, ShifterOperand(R2));
- __ orr(R0, R1, ShifterOperand(R2));
- __ eor(R0, R1, ShifterOperand(R2));
- __ bic(R0, R1, ShifterOperand(R2));
- __ adc(R0, R1, ShifterOperand(R2));
- __ sbc(R0, R1, ShifterOperand(R2));
- __ rsb(R0, R1, ShifterOperand(R2));
-
- // 16 bit variants.
- __ add(R0, R1, ShifterOperand());
- __ sub(R0, R1, ShifterOperand());
+ __ adc(R0, R0, ShifterOperand(R1));
+ __ sbc(R0, R0, ShifterOperand(R1));
__ and_(R0, R0, ShifterOperand(R1));
__ orr(R0, R0, ShifterOperand(R1));
__ eor(R0, R0, ShifterOperand(R1));
__ bic(R0, R0, ShifterOperand(R1));
- __ adc(R0, R0, ShifterOperand(R1));
- __ sbc(R0, R0, ShifterOperand(R1));
- __ rsb(R0, R0, ShifterOperand(R1));
+ __ mov(R1, ShifterOperand(R8));
+ __ mov(R9, ShifterOperand(R0));
+ __ mov(R8, ShifterOperand(R9));
+ __ add(R1, R1, ShifterOperand(R8));
+ __ add(R9, R9, ShifterOperand(R0));
+ __ add(R8, R8, ShifterOperand(R9));
+ __ rsb(R0, R1, ShifterOperand(0));
+ __ rsb(R0, R0, ShifterOperand(0));
- __ tst(R0, ShifterOperand(R1));
- __ teq(R0, ShifterOperand(R1));
- __ cmp(R0, ShifterOperand(R1));
- __ cmn(R0, ShifterOperand(R1));
-
- __ movs(R0, ShifterOperand(R1));
- __ mvns(R0, ShifterOperand(R1));
-
- // 32 bit variants.
- __ add(R12, R1, ShifterOperand(R0));
+ // And an arbitrary 32-bit instruction using IP.
+ __ add(R12, R1, ShifterOperand(R0), AL, kCcKeep);
EmitAndCheck(&assembler, "DataProcessingRegister");
}
@@ -296,6 +388,9 @@
__ movs(R0, ShifterOperand(0x55));
__ mvns(R0, ShifterOperand(0x55));
+ __ adds(R0, R1, ShifterOperand(5));
+ __ subs(R0, R1, ShifterOperand(5));
+
EmitAndCheck(&assembler, "DataProcessingImmediate");
}
@@ -340,18 +435,30 @@
TEST(Thumb2AssemblerTest, DataProcessingShiftedRegister) {
arm::Thumb2Assembler assembler;
- __ mov(R3, ShifterOperand(R4, LSL, 4));
- __ mov(R3, ShifterOperand(R4, LSR, 5));
- __ mov(R3, ShifterOperand(R4, ASR, 6));
- __ mov(R3, ShifterOperand(R4, ROR, 7));
- __ mov(R3, ShifterOperand(R4, ROR));
+ // 16-bit variants.
+ __ movs(R3, ShifterOperand(R4, LSL, 4));
+ __ movs(R3, ShifterOperand(R4, LSR, 5));
+ __ movs(R3, ShifterOperand(R4, ASR, 6));
- // 32 bit variants.
- __ mov(R8, ShifterOperand(R4, LSL, 4));
- __ mov(R8, ShifterOperand(R4, LSR, 5));
- __ mov(R8, ShifterOperand(R4, ASR, 6));
- __ mov(R8, ShifterOperand(R4, ROR, 7));
- __ mov(R8, ShifterOperand(R4, RRX));
+ // 32-bit ROR because ROR immediate doesn't have the same 16-bit version as other shifts.
+ __ movs(R3, ShifterOperand(R4, ROR, 7));
+
+ // 32-bit RRX because RRX has no 16-bit version.
+ __ movs(R3, ShifterOperand(R4, RRX));
+
+ // 32 bit variants (not setting condition codes).
+ __ mov(R3, ShifterOperand(R4, LSL, 4), AL, kCcKeep);
+ __ mov(R3, ShifterOperand(R4, LSR, 5), AL, kCcKeep);
+ __ mov(R3, ShifterOperand(R4, ASR, 6), AL, kCcKeep);
+ __ mov(R3, ShifterOperand(R4, ROR, 7), AL, kCcKeep);
+ __ mov(R3, ShifterOperand(R4, RRX), AL, kCcKeep);
+
+ // 32 bit variants (high registers).
+ __ movs(R8, ShifterOperand(R4, LSL, 4));
+ __ movs(R8, ShifterOperand(R4, LSR, 5));
+ __ movs(R8, ShifterOperand(R4, ASR, 6));
+ __ movs(R8, ShifterOperand(R4, ROR, 7));
+ __ movs(R8, ShifterOperand(R4, RRX));
EmitAndCheck(&assembler, "DataProcessingShiftedRegister");
}
@@ -1023,7 +1130,7 @@
TEST(Thumb2AssemblerTest, Shifts) {
arm::Thumb2Assembler assembler;
- // 16 bit
+ // 16 bit selected for CcDontCare.
__ Lsl(R0, R1, 5);
__ Lsr(R0, R1, 5);
__ Asr(R0, R1, 5);
@@ -1031,6 +1138,32 @@
__ Lsl(R0, R0, R1);
__ Lsr(R0, R0, R1);
__ Asr(R0, R0, R1);
+ __ Ror(R0, R0, R1);
+
+ // 16 bit with kCcSet.
+ __ Lsls(R0, R1, 5);
+ __ Lsrs(R0, R1, 5);
+ __ Asrs(R0, R1, 5);
+
+ __ Lsls(R0, R0, R1);
+ __ Lsrs(R0, R0, R1);
+ __ Asrs(R0, R0, R1);
+ __ Rors(R0, R0, R1);
+
+ // 32-bit with kCcKeep.
+ __ Lsl(R0, R1, 5, AL, kCcKeep);
+ __ Lsr(R0, R1, 5, AL, kCcKeep);
+ __ Asr(R0, R1, 5, AL, kCcKeep);
+
+ __ Lsl(R0, R0, R1, AL, kCcKeep);
+ __ Lsr(R0, R0, R1, AL, kCcKeep);
+ __ Asr(R0, R0, R1, AL, kCcKeep);
+ __ Ror(R0, R0, R1, AL, kCcKeep);
+
+ // 32-bit because ROR immediate doesn't have a 16-bit version like the other shifts.
+ __ Ror(R0, R1, 5);
+ __ Rors(R0, R1, 5);
+ __ Ror(R0, R1, 5, AL, kCcKeep);
// 32 bit due to high registers.
__ Lsl(R8, R1, 5);
@@ -1052,21 +1185,21 @@
// S bit (all 32 bit)
// 32 bit due to high registers.
- __ Lsl(R8, R1, 5, true);
- __ Lsr(R0, R8, 5, true);
- __ Asr(R8, R1, 5, true);
- __ Ror(R0, R8, 5, true);
+ __ Lsls(R8, R1, 5);
+ __ Lsrs(R0, R8, 5);
+ __ Asrs(R8, R1, 5);
+ __ Rors(R0, R8, 5);
// 32 bit due to different Rd and Rn.
- __ Lsl(R0, R1, R2, true);
- __ Lsr(R0, R1, R2, true);
- __ Asr(R0, R1, R2, true);
- __ Ror(R0, R1, R2, true);
+ __ Lsls(R0, R1, R2);
+ __ Lsrs(R0, R1, R2);
+ __ Asrs(R0, R1, R2);
+ __ Rors(R0, R1, R2);
// 32 bit due to use of high registers.
- __ Lsl(R8, R1, R2, true);
- __ Lsr(R0, R8, R2, true);
- __ Asr(R0, R1, R8, true);
+ __ Lsls(R8, R1, R2);
+ __ Lsrs(R0, R8, R2);
+ __ Asrs(R0, R1, R8);
EmitAndCheck(&assembler, "Shifts");
}
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index 280ed77..82ad642 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -1,8 +1,9 @@
const char* SimpleMovResults[] = {
" 0: 0008 movs r0, r1\n",
- " 2: 46c8 mov r8, r9\n",
- " 4: 2001 movs r0, #1\n",
- " 6: f04f 0809 mov.w r8, #9\n",
+ " 2: 4608 mov r0, r1\n",
+ " 4: 46c8 mov r8, r9\n",
+ " 6: 2001 movs r0, #1\n",
+ " 8: f04f 0809 mov.w r8, #9\n",
nullptr
};
const char* SimpleMov32Results[] = {
@@ -11,39 +12,120 @@
nullptr
};
const char* SimpleMovAddResults[] = {
- " 0: 0008 movs r0, r1\n",
+ " 0: 4608 mov r0, r1\n",
" 2: 1888 adds r0, r1, r2\n",
" 4: 1c08 adds r0, r1, #0\n",
nullptr
};
const char* DataProcessingRegisterResults[] = {
- " 0: 0008 movs r0, r1\n",
- " 2: 43c8 mvns r0, r1\n",
- " 4: 1888 adds r0, r1, r2\n",
- " 6: 1a88 subs r0, r1, r2\n",
- " 8: ea01 0002 and.w r0, r1, r2\n",
- " c: ea41 0002 orr.w r0, r1, r2\n",
- " 10: ea81 0002 eor.w r0, r1, r2\n",
- " 14: ea21 0002 bic.w r0, r1, r2\n",
- " 18: eb41 0002 adc.w r0, r1, r2\n",
- " 1c: eb61 0002 sbc.w r0, r1, r2\n",
- " 20: ebc1 0002 rsb r0, r1, r2\n",
- " 24: 1c08 adds r0, r1, #0\n",
- " 26: 1e08 subs r0, r1, #0\n",
- " 28: 4008 ands r0, r1\n",
- " 2a: 4308 orrs r0, r1\n",
- " 2c: 4048 eors r0, r1\n",
- " 2e: 4388 bics r0, r1\n",
- " 30: 4148 adcs r0, r1\n",
- " 32: 4188 sbcs r0, r1\n",
- " 34: 4248 negs r0, r1\n",
- " 36: 4208 tst r0, r1\n",
- " 38: ea90 0f01 teq r0, r1\n",
- " 3c: 4288 cmp r0, r1\n",
- " 3e: 42c8 cmn r0, r1\n",
- " 40: 0008 movs r0, r1\n",
- " 42: 43c8 mvns r0, r1\n",
- " 44: eb01 0c00 add.w ip, r1, r0\n",
+ " 0: ea6f 0001 mvn.w r0, r1\n",
+ " 4: eb01 0002 add.w r0, r1, r2\n",
+ " 8: eba1 0002 sub.w r0, r1, r2\n",
+ " c: ea01 0002 and.w r0, r1, r2\n",
+ " 10: ea41 0002 orr.w r0, r1, r2\n",
+ " 14: ea81 0002 eor.w r0, r1, r2\n",
+ " 18: ea21 0002 bic.w r0, r1, r2\n",
+ " 1c: eb41 0002 adc.w r0, r1, r2\n",
+ " 20: eb61 0002 sbc.w r0, r1, r2\n",
+ " 24: ebc1 0002 rsb r0, r1, r2\n",
+ " 28: ea90 0f01 teq r0, r1\n",
+ " 2c: 0008 movs r0, r1\n",
+ " 2e: 4608 mov r0, r1\n",
+ " 30: 43c8 mvns r0, r1\n",
+ " 32: 4408 add r0, r1\n",
+ " 34: 1888 adds r0, r1, r2\n",
+ " 36: 1a88 subs r0, r1, r2\n",
+ " 38: 4148 adcs r0, r1\n",
+ " 3a: 4188 sbcs r0, r1\n",
+ " 3c: 4008 ands r0, r1\n",
+ " 3e: 4308 orrs r0, r1\n",
+ " 40: 4048 eors r0, r1\n",
+ " 42: 4388 bics r0, r1\n",
+ " 44: 4208 tst r0, r1\n",
+ " 46: 4288 cmp r0, r1\n",
+ " 48: 42c8 cmn r0, r1\n",
+ " 4a: 4641 mov r1, r8\n",
+ " 4c: 4681 mov r9, r0\n",
+ " 4e: 46c8 mov r8, r9\n",
+ " 50: 4441 add r1, r8\n",
+ " 52: 4481 add r9, r0\n",
+ " 54: 44c8 add r8, r9\n",
+ " 56: 4548 cmp r0, r9\n",
+ " 58: 4588 cmp r8, r1\n",
+ " 5a: 45c1 cmp r9, r8\n",
+ " 5c: 4248 negs r0, r1\n",
+ " 5e: 4240 negs r0, r0\n",
+ " 60: ea5f 0008 movs.w r0, r8\n",
+ " 64: ea7f 0008 mvns.w r0, r8\n",
+ " 68: eb01 0008 add.w r0, r1, r8\n",
+ " 6c: eb11 0008 adds.w r0, r1, r8\n",
+ " 70: ebb1 0008 subs.w r0, r1, r8\n",
+ " 74: eb50 0008 adcs.w r0, r0, r8\n",
+ " 78: eb70 0008 sbcs.w r0, r0, r8\n",
+ " 7c: ea10 0008 ands.w r0, r0, r8\n",
+ " 80: ea50 0008 orrs.w r0, r0, r8\n",
+ " 84: ea90 0008 eors.w r0, r0, r8\n",
+ " 88: ea30 0008 bics.w r0, r0, r8\n",
+ " 8c: ea10 0f08 tst.w r0, r8\n",
+ " 90: eb10 0f08 cmn.w r0, r8\n",
+ " 94: f1d8 0000 rsbs r0, r8, #0\n",
+ " 98: f1d8 0800 rsbs r8, r8, #0\n",
+ " 9c: bf08 it eq\n",
+ " 9e: ea7f 0001 mvnseq.w r0, r1\n",
+ " a2: bf08 it eq\n",
+ " a4: eb11 0002 addseq.w r0, r1, r2\n",
+ " a8: bf08 it eq\n",
+ " aa: ebb1 0002 subseq.w r0, r1, r2\n",
+ " ae: bf08 it eq\n",
+ " b0: eb50 0001 adcseq.w r0, r0, r1\n",
+ " b4: bf08 it eq\n",
+ " b6: eb70 0001 sbcseq.w r0, r0, r1\n",
+ " ba: bf08 it eq\n",
+ " bc: ea10 0001 andseq.w r0, r0, r1\n",
+ " c0: bf08 it eq\n",
+ " c2: ea50 0001 orrseq.w r0, r0, r1\n",
+ " c6: bf08 it eq\n",
+ " c8: ea90 0001 eorseq.w r0, r0, r1\n",
+ " cc: bf08 it eq\n",
+ " ce: ea30 0001 bicseq.w r0, r0, r1\n",
+ " d2: bf08 it eq\n",
+ " d4: 43c8 mvneq r0, r1\n",
+ " d6: bf08 it eq\n",
+ " d8: 1888 addeq r0, r1, r2\n",
+ " da: bf08 it eq\n",
+ " dc: 1a88 subeq r0, r1, r2\n",
+ " de: bf08 it eq\n",
+ " e0: 4148 adceq r0, r1\n",
+ " e2: bf08 it eq\n",
+ " e4: 4188 sbceq r0, r1\n",
+ " e6: bf08 it eq\n",
+ " e8: 4008 andeq r0, r1\n",
+ " ea: bf08 it eq\n",
+ " ec: 4308 orreq r0, r1\n",
+ " ee: bf08 it eq\n",
+ " f0: 4048 eoreq r0, r1\n",
+ " f2: bf08 it eq\n",
+ " f4: 4388 biceq r0, r1\n",
+ " f6: 4608 mov r0, r1\n",
+ " f8: 43c8 mvns r0, r1\n",
+ " fa: 4408 add r0, r1\n",
+ " fc: 1888 adds r0, r1, r2\n",
+ " fe: 1a88 subs r0, r1, r2\n",
+ " 100: 4148 adcs r0, r1\n",
+ " 102: 4188 sbcs r0, r1\n",
+ " 104: 4008 ands r0, r1\n",
+ " 106: 4308 orrs r0, r1\n",
+ " 108: 4048 eors r0, r1\n",
+ " 10a: 4388 bics r0, r1\n",
+ " 10c: 4641 mov r1, r8\n",
+ " 10e: 4681 mov r9, r0\n",
+ " 110: 46c8 mov r8, r9\n",
+ " 112: 4441 add r1, r8\n",
+ " 114: 4481 add r9, r0\n",
+ " 116: 44c8 add r8, r9\n",
+ " 118: 4248 negs r0, r1\n",
+ " 11a: 4240 negs r0, r0\n",
+ " 11c: eb01 0c00 add.w ip, r1, r0\n",
nullptr
};
const char* DataProcessingImmediateResults[] = {
@@ -66,6 +148,8 @@
" 3a: 1f48 subs r0, r1, #5\n",
" 3c: 2055 movs r0, #85 ; 0x55\n",
" 3e: f07f 0055 mvns.w r0, #85 ; 0x55\n",
+ " 42: 1d48 adds r0, r1, #5\n",
+ " 44: 1f48 subs r0, r1, #5\n",
nullptr
};
const char* DataProcessingModifiedImmediateResults[] = {
@@ -100,13 +184,18 @@
" 0: 0123 lsls r3, r4, #4\n",
" 2: 0963 lsrs r3, r4, #5\n",
" 4: 11a3 asrs r3, r4, #6\n",
- " 6: ea4f 13f4 mov.w r3, r4, ror #7\n",
- " a: 41e3 rors r3, r4\n",
- " c: ea4f 1804 mov.w r8, r4, lsl #4\n",
- " 10: ea4f 1854 mov.w r8, r4, lsr #5\n",
- " 14: ea4f 18a4 mov.w r8, r4, asr #6\n",
- " 18: ea4f 18f4 mov.w r8, r4, ror #7\n",
- " 1c: ea4f 0834 mov.w r8, r4, rrx\n",
+ " 6: ea5f 13f4 movs.w r3, r4, ror #7\n",
+ " a: ea5f 0334 movs.w r3, r4, rrx\n",
+ " e: ea4f 1304 mov.w r3, r4, lsl #4\n",
+ " 12: ea4f 1354 mov.w r3, r4, lsr #5\n",
+ " 16: ea4f 13a4 mov.w r3, r4, asr #6\n",
+ " 1a: ea4f 13f4 mov.w r3, r4, ror #7\n",
+ " 1e: ea4f 0334 mov.w r3, r4, rrx\n",
+ " 22: ea5f 1804 movs.w r8, r4, lsl #4\n",
+ " 26: ea5f 1854 movs.w r8, r4, lsr #5\n",
+ " 2a: ea5f 18a4 movs.w r8, r4, asr #6\n",
+ " 2e: ea5f 18f4 movs.w r8, r4, ror #7\n",
+ " 32: ea5f 0834 movs.w r8, r4, rrx\n",
nullptr
};
const char* BasicLoadResults[] = {
@@ -1511,7 +1600,7 @@
" 7fc: 23fa movs r3, #250 ; 0xfa\n",
" 7fe: 23fc movs r3, #252 ; 0xfc\n",
" 800: 23fe movs r3, #254 ; 0xfe\n",
- " 802: 0011 movs r1, r2\n",
+ " 802: 4611 mov r1, r2\n",
nullptr
};
const char* Branch32Results[] = {
@@ -2541,7 +2630,7 @@
" 800: 23fc movs r3, #252 ; 0xfc\n",
" 802: 23fe movs r3, #254 ; 0xfe\n",
" 804: 2300 movs r3, #0\n",
- " 806: 0011 movs r1, r2\n",
+ " 806: 4611 mov r1, r2\n",
nullptr
};
const char* CompareAndBranchMaxResults[] = {
@@ -2610,7 +2699,7 @@
" 7c: 237a movs r3, #122 ; 0x7a\n",
" 7e: 237c movs r3, #124 ; 0x7c\n",
" 80: 237e movs r3, #126 ; 0x7e\n",
- " 82: 0011 movs r1, r2\n",
+ " 82: 4611 mov r1, r2\n",
nullptr
};
const char* CompareAndBranchRelocation16Results[] = {
@@ -2681,7 +2770,7 @@
" 80: 237c movs r3, #124 ; 0x7c\n",
" 82: 237e movs r3, #126 ; 0x7e\n",
" 84: 2380 movs r3, #128 ; 0x80\n",
- " 86: 0011 movs r1, r2\n",
+ " 86: 4611 mov r1, r2\n",
nullptr
};
const char* CompareAndBranchRelocation32Results[] = {
@@ -3712,7 +3801,7 @@
" 802: 23fc movs r3, #252 ; 0xfc\n",
" 804: 23fe movs r3, #254 ; 0xfe\n",
" 806: 2300 movs r3, #0\n",
- " 808: 0011 movs r1, r2\n",
+ " 808: 4611 mov r1, r2\n",
nullptr
};
const char* MixedBranch32Results[] = {
@@ -4743,7 +4832,7 @@
" 802: 23fe movs r3, #254 ; 0xfe\n",
" 804: 2300 movs r3, #0\n",
" 806: f7ff bbfd b.w 4 <MixedBranch32+0x4>\n",
- " 80a: 0011 movs r1, r2\n",
+ " 80a: 4611 mov r1, r2\n",
nullptr
};
const char* ShiftsResults[] = {
@@ -4753,28 +4842,46 @@
" 6: 4088 lsls r0, r1\n",
" 8: 40c8 lsrs r0, r1\n",
" a: 4108 asrs r0, r1\n",
- " c: ea4f 1841 mov.w r8, r1, lsl #5\n",
- " 10: ea4f 1058 mov.w r0, r8, lsr #5\n",
- " 14: ea4f 1861 mov.w r8, r1, asr #5\n",
- " 18: ea4f 1078 mov.w r0, r8, ror #5\n",
- " 1c: fa01 f002 lsl.w r0, r1, r2\n",
- " 20: fa21 f002 lsr.w r0, r1, r2\n",
- " 24: fa41 f002 asr.w r0, r1, r2\n",
- " 28: fa61 f002 ror.w r0, r1, r2\n",
- " 2c: fa01 f802 lsl.w r8, r1, r2\n",
- " 30: fa28 f002 lsr.w r0, r8, r2\n",
- " 34: fa41 f008 asr.w r0, r1, r8\n",
- " 38: ea5f 1841 movs.w r8, r1, lsl #5\n",
- " 3c: ea5f 1058 movs.w r0, r8, lsr #5\n",
- " 40: ea5f 1861 movs.w r8, r1, asr #5\n",
- " 44: ea5f 1078 movs.w r0, r8, ror #5\n",
- " 48: fa11 f002 lsls.w r0, r1, r2\n",
- " 4c: fa31 f002 lsrs.w r0, r1, r2\n",
- " 50: fa51 f002 asrs.w r0, r1, r2\n",
- " 54: fa71 f002 rors.w r0, r1, r2\n",
- " 58: fa11 f802 lsls.w r8, r1, r2\n",
- " 5c: fa38 f002 lsrs.w r0, r8, r2\n",
- " 60: fa51 f008 asrs.w r0, r1, r8\n",
+ " c: 41c8 rors r0, r1\n",
+ " e: 0148 lsls r0, r1, #5\n",
+ " 10: 0948 lsrs r0, r1, #5\n",
+ " 12: 1148 asrs r0, r1, #5\n",
+ " 14: 4088 lsls r0, r1\n",
+ " 16: 40c8 lsrs r0, r1\n",
+ " 18: 4108 asrs r0, r1\n",
+ " 1a: 41c8 rors r0, r1\n",
+ " 1c: ea4f 1041 mov.w r0, r1, lsl #5\n",
+ " 20: ea4f 1051 mov.w r0, r1, lsr #5\n",
+ " 24: ea4f 1061 mov.w r0, r1, asr #5\n",
+ " 28: fa00 f001 lsl.w r0, r0, r1\n",
+ " 2c: fa20 f001 lsr.w r0, r0, r1\n",
+ " 30: fa40 f001 asr.w r0, r0, r1\n",
+ " 34: fa60 f001 ror.w r0, r0, r1\n",
+ " 38: ea4f 1071 mov.w r0, r1, ror #5\n",
+ " 3c: ea5f 1071 movs.w r0, r1, ror #5\n",
+ " 40: ea4f 1071 mov.w r0, r1, ror #5\n",
+ " 44: ea4f 1841 mov.w r8, r1, lsl #5\n",
+ " 48: ea4f 1058 mov.w r0, r8, lsr #5\n",
+ " 4c: ea4f 1861 mov.w r8, r1, asr #5\n",
+ " 50: ea4f 1078 mov.w r0, r8, ror #5\n",
+ " 54: fa01 f002 lsl.w r0, r1, r2\n",
+ " 58: fa21 f002 lsr.w r0, r1, r2\n",
+ " 5c: fa41 f002 asr.w r0, r1, r2\n",
+ " 60: fa61 f002 ror.w r0, r1, r2\n",
+ " 64: fa01 f802 lsl.w r8, r1, r2\n",
+ " 68: fa28 f002 lsr.w r0, r8, r2\n",
+ " 6c: fa41 f008 asr.w r0, r1, r8\n",
+ " 70: ea5f 1841 movs.w r8, r1, lsl #5\n",
+ " 74: ea5f 1058 movs.w r0, r8, lsr #5\n",
+ " 78: ea5f 1861 movs.w r8, r1, asr #5\n",
+ " 7c: ea5f 1078 movs.w r0, r8, ror #5\n",
+ " 80: fa11 f002 lsls.w r0, r1, r2\n",
+ " 84: fa31 f002 lsrs.w r0, r1, r2\n",
+ " 88: fa51 f002 asrs.w r0, r1, r2\n",
+ " 8c: fa71 f002 rors.w r0, r1, r2\n",
+ " 90: fa11 f802 lsls.w r8, r1, r2\n",
+ " 94: fa38 f002 lsrs.w r0, r8, r2\n",
+ " 98: fa51 f008 asrs.w r0, r1, r8\n",
nullptr
};
const char* LoadStoreRegOffsetResults[] = {