#include "MCTargetDesc/ARMAddressingModes.h"
#include "MCTargetDesc/ARMBaseInfo.h"
#include "MCTargetDesc/ARMFixupKinds.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCValue.h"
-#include "llvm/Object/MachOFormat.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MachO.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
switch (Op) {
default: return Op;
case ARM::tBcc: return ARM::t2Bcc;
- case ARM::tLDRpciASM: return ARM::t2LDRpci;
+ 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;
}
}
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()!");
}
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);
uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
uint32_t imm10Bits = (offset & 0x1FF800) >> 11;
uint32_t imm11Bits = (offset & 0x000007FF);
-
+
uint32_t Binary = 0;
uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits);
uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
// four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as
// imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00)
// where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
- // The value is encoded into disjoint bit positions in the destination
- // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
+ // The value is encoded into disjoint bit positions in the destination
+ // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
// J = either J1 or J2 bit, 0 = zero.
//
// BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0
uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
uint32_t imm10LBits = (offset & 0x3FF);
-
+
uint32_t Binary = 0;
uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits);
- uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
+ uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
((uint16_t)imm10LBits) << 1);
Binary |= secondHalf << 16;
Binary |= firstHalf;
// FIXME: This should be in a separate file.
class DarwinARMAsmBackend : public ARMAsmBackend {
public:
- const object::mach::CPUSubtypeARM Subtype;
+ const MachO::CPUSubTypeARM Subtype;
DarwinARMAsmBackend(const Target &T, const StringRef TT,
- object::mach::CPUSubtypeARM st)
+ MachO::CPUSubTypeARM st)
: ARMAsmBackend(T, TT), Subtype(st) {
HasDataInCodeSupport = true;
}
MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
return createARMMachObjectWriter(OS, /*Is64Bit=*/false,
- object::mach::CTM_ARM,
+ MachO::CPU_TYPE_ARM,
Subtype);
}
} // end anonymous namespace
-MCAsmBackend *llvm::createARMAsmBackend(const Target &T, StringRef TT, StringRef CPU) {
+MCAsmBackend *llvm::createARMAsmBackend(const Target &T,
+ const MCRegisterInfo &MRI,
+ StringRef TT, StringRef CPU) {
Triple TheTriple(TT);
- if (TheTriple.isOSDarwin()) {
- if (TheTriple.getArchName() == "armv4t" ||
- TheTriple.getArchName() == "thumbv4t")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V4T);
- else if (TheTriple.getArchName() == "armv5e" ||
- TheTriple.getArchName() == "thumbv5e")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V5TEJ);
- else if (TheTriple.getArchName() == "armv6" ||
- TheTriple.getArchName() == "thumbv6")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6);
- else if (TheTriple.getArchName() == "armv6m" ||
- TheTriple.getArchName() == "thumbv6m")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V6M);
- else if (TheTriple.getArchName() == "armv7em" ||
- TheTriple.getArchName() == "thumbv7em")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7EM);
- else if (TheTriple.getArchName() == "armv7f" ||
- TheTriple.getArchName() == "thumbv7f")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7F);
- else if (TheTriple.getArchName() == "armv7k" ||
- TheTriple.getArchName() == "thumbv7k")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7K);
- else if (TheTriple.getArchName() == "armv7m" ||
- TheTriple.getArchName() == "thumbv7m")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7M);
- else if (TheTriple.getArchName() == "armv7s" ||
- TheTriple.getArchName() == "thumbv7s")
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7S);
- return new DarwinARMAsmBackend(T, TT, object::mach::CSARM_V7);
+ if (TheTriple.isOSBinFormatMachO()) {
+ MachO::CPUSubTypeARM CS =
+ StringSwitch<MachO::CPUSubTypeARM>(TheTriple.getArchName())
+ .Cases("armv4t", "thumbv4t", MachO::CPU_SUBTYPE_ARM_V4T)
+ .Cases("armv5e", "thumbv5e", MachO::CPU_SUBTYPE_ARM_V5TEJ)
+ .Cases("armv6", "thumbv6", MachO::CPU_SUBTYPE_ARM_V6)
+ .Cases("armv6m", "thumbv6m", MachO::CPU_SUBTYPE_ARM_V6M)
+ .Cases("armv7em", "thumbv7em", MachO::CPU_SUBTYPE_ARM_V7EM)
+ .Cases("armv7f", "thumbv7f", MachO::CPU_SUBTYPE_ARM_V7F)
+ .Cases("armv7k", "thumbv7k", MachO::CPU_SUBTYPE_ARM_V7K)
+ .Cases("armv7m", "thumbv7m", MachO::CPU_SUBTYPE_ARM_V7M)
+ .Cases("armv7s", "thumbv7s", MachO::CPU_SUBTYPE_ARM_V7S)
+ .Default(MachO::CPU_SUBTYPE_ARM_V7);
+
+ return new DarwinARMAsmBackend(T, TT, CS);
}
- if (TheTriple.isOSWindows())
+#if 0
+ // FIXME: Introduce yet another checker but assert(0).
+ if (TheTriple.isOSBinFormatCOFF())
assert(0 && "Windows not supported on ARM");
+#endif
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS());
return new ELFARMAsmBackend(T, TT, OSABI);