X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FMCTargetDesc%2FARMAsmBackend.cpp;h=20dce218ea3c60d2b0faa2ca5ab866bdea3aa17d;hb=d9615670b7d2b6b43d19d6e8706e9d504f91030e;hp=415dee3121536246f71cdd08c728de3b8d8ac9f4;hpb=398db9368d72d1d60d40b2e18c16ca2c14aa7f39;p=oota-llvm.git diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 415dee31215..20dce218ea3 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -11,6 +11,7 @@ #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" @@ -24,9 +25,9 @@ #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; @@ -151,9 +152,11 @@ static unsigned getRelaxedOpcode(unsigned Op) { 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; } } @@ -195,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()!"); } @@ -211,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); @@ -418,7 +438,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, 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) | @@ -433,8 +453,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // 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 @@ -449,10 +469,10 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, 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; @@ -639,16 +659,16 @@ public: // 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); } @@ -659,42 +679,33 @@ public: } // 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(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);