summaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorKevin Enderby <enderby@apple.com>2014-01-10 00:43:32 +0000
committerKevin Enderby <enderby@apple.com>2014-01-10 00:43:32 +0000
commitd9615670b7d2b6b43d19d6e8706e9d504f91030e (patch)
tree44a4738660a192b844c043592a329829e99e4328 /lib/Target
parent36c48cad0d14cb1679f494c811554198308c4bc1 (diff)
downloadllvm-d9615670b7d2b6b43d19d6e8706e9d504f91030e.tar.gz
llvm-d9615670b7d2b6b43d19d6e8706e9d504f91030e.tar.bz2
llvm-d9615670b7d2b6b43d19d6e8706e9d504f91030e.tar.xz
Fix a bug with the ARM thumb2 CBNZ and CBNZ instructions that
branch to the next instruction. This can not be encoded but can be turned into a NOP. rdar://15062072 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198904 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp21
1 files changed, 20 insertions, 1 deletions
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index fecab9f5d4..20dce218ea 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -155,6 +155,8 @@ static unsigned getRelaxedOpcode(unsigned Op) {
case ARM::tLDRpci: return ARM::t2LDRpci;
case ARM::tADR: return ARM::t2ADR;
case ARM::tB: return ARM::t2B;
+ case ARM::tCBZ: return ARM::tHINT;
+ case ARM::tCBNZ: return ARM::tHINT;
}
}
@@ -196,6 +198,12 @@ bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
int64_t Offset = int64_t(Value) - 4;
return Offset > 1020 || Offset < 0 || Offset & 3;
}
+ case ARM::fixup_arm_thumb_cb:
+ // If we have a Thumb CBZ or CBNZ instruction and its target is the next
+ // instruction it is is actually out of range for the instruction.
+ // It will be changed to a NOP.
+ int64_t Offset = (Value & ~1);
+ return Offset == 2;
}
llvm_unreachable("Unexpected fixup kind in fixupNeedsRelaxation()!");
}
@@ -212,7 +220,18 @@ void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
report_fatal_error("unexpected instruction to relax: " + OS.str());
}
- // The instructions we're relaxing have (so far) the same operands.
+ // If we are changing Thumb CBZ or CBNZ instruction to a NOP, aka tHINT, we
+ // have to change the operands too.
+ if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) &&
+ RelaxedOp == ARM::tHINT) {
+ Res.setOpcode(RelaxedOp);
+ Res.addOperand(MCOperand::CreateImm(0));
+ Res.addOperand(MCOperand::CreateImm(14));
+ Res.addOperand(MCOperand::CreateReg(0));
+ return;
+ }
+
+ // The rest of instructions we're relaxing have the same operands.
// We just need to update to the proper opcode.
Res = Inst;
Res.setOpcode(RelaxedOp);