summaryrefslogtreecommitdiff
path: root/compiler/utils/arm/assembler_arm32.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils/arm/assembler_arm32.cc')
-rw-r--r--compiler/utils/arm/assembler_arm32.cc119
1 files changed, 99 insertions, 20 deletions
diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc
index b2bb20fa2d..267bba8521 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -541,20 +541,40 @@ void Arm32Assembler::EmitType5(Condition cond, int offset, bool link) {
void Arm32Assembler::EmitMemOp(Condition cond,
- bool load,
- bool byte,
- Register rd,
- const Address& ad) {
+ bool load,
+ bool byte,
+ Register rd,
+ const Address& ad) {
CHECK_NE(rd, kNoRegister);
CHECK_NE(cond, kNoCondition);
const Address& addr = static_cast<const Address&>(ad);
- int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
- B26 |
- (load ? L : 0) |
- (byte ? B : 0) |
- (static_cast<int32_t>(rd) << kRdShift) |
- addr.encodingArm();
+ int32_t encoding = 0;
+ if (!ad.IsImmediate() && ad.GetRegisterOffset() == PC) {
+ // PC relative LDR(literal)
+ int32_t offset = ad.GetOffset();
+ int32_t u = B23;
+ if (offset < 0) {
+ offset = -offset;
+ u = 0;
+ }
+ CHECK_LT(offset, (1 << 12));
+ encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+ B26 | B24 | u | B20 |
+ (load ? L : 0) |
+ (byte ? B : 0) |
+ (static_cast<int32_t>(rd) << kRdShift) |
+ 0xf << 16 |
+ (offset & 0xfff);
+
+ } else {
+ encoding = (static_cast<int32_t>(cond) << kConditionShift) |
+ B26 |
+ (load ? L : 0) |
+ (byte ? B : 0) |
+ (static_cast<int32_t>(rd) << kRdShift) |
+ addr.encodingArm();
+ }
Emit(encoding);
}
@@ -1020,39 +1040,98 @@ void Arm32Assembler::EmitVFPds(Condition cond, int32_t opcode,
void Arm32Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm,
- Condition cond) {
+ bool setcc, Condition cond) {
CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted.
- mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
+ if (setcc) {
+ movs(rd, ShifterOperand(rm, LSL, shift_imm), cond);
+ } else {
+ mov(rd, ShifterOperand(rm, LSL, shift_imm), cond);
+ }
}
void Arm32Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm,
- Condition cond) {
+ bool setcc, Condition cond) {
CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted.
if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
- mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
+ if (setcc) {
+ movs(rd, ShifterOperand(rm, LSR, shift_imm), cond);
+ } else {
+ mov(rd, ShifterOperand(rm, LSR, shift_imm), cond);
+ }
}
void Arm32Assembler::Asr(Register rd, Register rm, uint32_t shift_imm,
- Condition cond) {
+ bool setcc, Condition cond) {
CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted.
if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax.
- mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
+ if (setcc) {
+ movs(rd, ShifterOperand(rm, ASR, shift_imm), cond);
+ } else {
+ mov(rd, ShifterOperand(rm, ASR, shift_imm), cond);
+ }
}
void Arm32Assembler::Ror(Register rd, Register rm, uint32_t shift_imm,
- Condition cond) {
+ bool setcc, Condition cond) {
CHECK_NE(shift_imm, 0u); // Use Rrx instruction.
- mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
+ if (setcc) {
+ movs(rd, ShifterOperand(rm, ROR, shift_imm), cond);
+ } else {
+ mov(rd, ShifterOperand(rm, ROR, shift_imm), cond);
+ }
+}
+
+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::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);
+ }
+}
+
+
+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);
+ }
}
-void Arm32Assembler::Rrx(Register rd, Register rm, Condition cond) {
- mov(rd, ShifterOperand(rm, ROR, 0), cond);
+
+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);
+ }
}
+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);
+ }
+}
+
void Arm32Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
CHECK_NE(cond, kNoCondition);
int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |