Index: include/llvm/ADT/Triple.h =================================================================== --- include/llvm/ADT/Triple.h +++ include/llvm/ADT/Triple.h @@ -46,7 +46,8 @@ enum ArchType { UnknownArch, - arm, // ARM: arm, armv.*, xscale + arm, // ARM (little endian): arm, armv.*, xscale + armeb, // ARM (big endian): armeb aarch64, // AArch64 (little endian): aarch64 aarch64_be, // AArch64 (big endian): aarch64_be hexagon, // Hexagon: hexagon @@ -63,7 +64,8 @@ sparcv9, // Sparcv9: Sparcv9 systemz, // SystemZ: s390x tce, // TCE (http://tce.cs.tut.fi/): tce - thumb, // Thumb: thumb, thumbv.* + thumb, // Thumb (little endian): thumb, thumbv.* + thumbeb, // Thumb (big endian): thumbeb x86, // X86: i[3-9]86 x86_64, // X86-64: amd64, x86_64 xcore, // XCore: xcore Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -897,7 +897,9 @@ resolveAArch64Relocation(Section, Offset, Value, Type, Addend); break; case Triple::arm: // Fall through. + case Triple::armeb: case Triple::thumb: + case Triple::thumbeb: resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); Index: lib/Support/Triple.cpp =================================================================== --- lib/Support/Triple.cpp +++ lib/Support/Triple.cpp @@ -22,6 +22,7 @@ case aarch64: return "aarch64"; case aarch64_be: return "aarch64_be"; case arm: return "arm"; + case armeb: return "armeb"; case hexagon: return "hexagon"; case mips: return "mips"; case mipsel: return "mipsel"; @@ -37,6 +38,7 @@ case systemz: return "s390x"; case tce: return "tce"; case thumb: return "thumb"; + case thumbeb: return "thumbeb"; case x86: return "i386"; case x86_64: return "x86_64"; case xcore: return "xcore"; @@ -60,7 +62,9 @@ case aarch64_be: return "aarch64"; case arm: - case thumb: return "arm"; + case armeb: + case thumb: + case thumbeb: return "arm"; case ppc64: case ppc64le: @@ -165,6 +169,7 @@ .Case("aarch64", aarch64) .Case("aarch64_be", aarch64_be) .Case("arm", arm) + .Case("armeb", armeb) .Case("mips", mips) .Case("mipsel", mipsel) .Case("mips64", mips64) @@ -181,6 +186,7 @@ .Case("systemz", systemz) .Case("tce", tce) .Case("thumb", thumb) + .Case("thumbeb", thumbeb) .Case("x86", x86) .Case("x86-64", x86_64) .Case("xcore", xcore) @@ -209,6 +215,7 @@ .Cases("armv5", "armv5e", "thumbv5", "thumbv5e", "armv5") .Cases("armv6", "thumbv6", "armv6") .Cases("armv7", "thumbv7", "armv7") + .Case("armeb", "armeb") .Case("r600", "r600") .Case("nvptx", "nvptx") .Case("nvptx64", "nvptx64") @@ -234,8 +241,12 @@ // FIXME: It would be good to replace these with explicit names for all the // various suffixes supported. .StartsWith("armv", Triple::arm) + .Case("armeb", Triple::armeb) + .StartsWith("armebv", Triple::armeb) .Case("thumb", Triple::thumb) .StartsWith("thumbv", Triple::thumb) + .Case("thumbeb", Triple::thumbeb) + .StartsWith("thumbebv", Triple::thumbeb) .Case("msp430", Triple::msp430) .Cases("mips", "mipseb", "mipsallegrex", Triple::mips) .Cases("mipsel", "mipsallegrexel", Triple::mipsel) @@ -721,6 +732,7 @@ case llvm::Triple::amdil: case llvm::Triple::arm: + case llvm::Triple::armeb: case llvm::Triple::hexagon: case llvm::Triple::le32: case llvm::Triple::mips: @@ -731,6 +743,7 @@ case llvm::Triple::sparc: case llvm::Triple::tce: case llvm::Triple::thumb: + case llvm::Triple::thumbeb: case llvm::Triple::x86: case llvm::Triple::xcore: case llvm::Triple::spir: @@ -779,6 +792,7 @@ case Triple::amdil: case Triple::spir: case Triple::arm: + case Triple::armeb: case Triple::hexagon: case Triple::le32: case Triple::mips: @@ -789,6 +803,7 @@ case Triple::sparc: case Triple::tce: case Triple::thumb: + case Triple::thumbeb: case Triple::x86: case Triple::xcore: // Already 32-bit. @@ -811,12 +826,14 @@ case Triple::UnknownArch: case Triple::amdil: case Triple::arm: + case Triple::armeb: case Triple::hexagon: case Triple::le32: case Triple::msp430: case Triple::r600: case Triple::tce: case Triple::thumb: + case Triple::thumbeb: case Triple::xcore: T.setArch(UnknownArch); break; Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -1719,6 +1719,8 @@ // Force static initialization. extern "C" void LLVMInitializeARMAsmPrinter() { - RegisterAsmPrinter X(TheARMTarget); - RegisterAsmPrinter Y(TheThumbTarget); + RegisterAsmPrinter X(TheARMleTarget); + RegisterAsmPrinter Y(TheARMbeTarget); + RegisterAsmPrinter A(TheThumbleTarget); + RegisterAsmPrinter B(TheThumbbeTarget); } Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -6522,6 +6522,7 @@ static_cast(MI->getOperand(IsCmpxchg ? 7 : 5).getImm()); DebugLoc dl = MI->getDebugLoc(); bool isThumb2 = Subtarget->isThumb2(); + bool isLittleEndian = Subtarget->isLittle(); MachineRegisterInfo &MRI = BB->getParent()->getRegInfo(); if (isThumb2) { @@ -6576,8 +6577,8 @@ // Load if (isThumb2) { AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc)) - .addReg(destlo, RegState::Define) - .addReg(desthi, RegState::Define) + .addReg(isLittleEndian ? destlo : desthi, RegState::Define) + .addReg(isLittleEndian ? desthi : destlo, RegState::Define) .addReg(ptr)); } else { unsigned GPRPair0 = MRI.createVirtualRegister(&ARM::GPRPairRegClass); @@ -6586,9 +6587,9 @@ .addReg(ptr)); // Copy r2/r3 into dest. (This copy will normally be coalesced.) BuildMI(BB, dl, TII->get(TargetOpcode::COPY), destlo) - .addReg(GPRPair0, 0, ARM::gsub_0); + .addReg(GPRPair0, 0, isLittleEndian ? ARM::gsub_0 : ARM::gsub_1); BuildMI(BB, dl, TII->get(TargetOpcode::COPY), desthi) - .addReg(GPRPair0, 0, ARM::gsub_1); + .addReg(GPRPair0, 0, isLittleEndian ? ARM::gsub_1 : ARM::gsub_0); } unsigned StoreLo, StoreHi; @@ -6642,8 +6643,12 @@ if (isThumb2) { MRI.constrainRegClass(StoreLo, &ARM::rGPRRegClass); MRI.constrainRegClass(StoreHi, &ARM::rGPRRegClass); - AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), storesuccess) - .addReg(StoreLo).addReg(StoreHi).addReg(ptr)); + if( isLittleEndian ) + AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), storesuccess) + .addReg(StoreLo).addReg(StoreHi).addReg(ptr)); + else + AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), storesuccess) + .addReg(StoreHi).addReg(StoreLo).addReg(ptr)); } else { // Marshal a pair... unsigned StorePair = MRI.createVirtualRegister(&ARM::GPRPairRegClass); @@ -6653,11 +6658,11 @@ BuildMI(BB, dl, TII->get(TargetOpcode::INSERT_SUBREG), r1) .addReg(UndefPair) .addReg(StoreLo) - .addImm(ARM::gsub_0); + .addImm(isLittleEndian ? ARM::gsub_0 : ARM::gsub_1); BuildMI(BB, dl, TII->get(TargetOpcode::INSERT_SUBREG), StorePair) .addReg(r1) .addReg(StoreHi) - .addImm(ARM::gsub_1); + .addImm(isLittleEndian ? ARM::gsub_1 : ARM::gsub_0); // ...and store it AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), storesuccess) @@ -6692,6 +6697,8 @@ AtomicOrdering Ord = static_cast(MI->getOperand(3).getImm()); DebugLoc dl = MI->getDebugLoc(); bool isThumb2 = Subtarget->isThumb2(); + if(!Subtarget->isLittle()) + std::swap(destlo, desthi); MachineRegisterInfo &MRI = BB->getParent()->getRegInfo(); if (isThumb2) { Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h +++ lib/Target/ARM/ARMSubtarget.h @@ -203,6 +203,9 @@ /// CPUString - String name of used CPU. std::string CPUString; + /// IsLittle - The target is Little Endian + bool IsLittle; + /// TargetTriple - What processor and OS we're targeting. Triple TargetTriple; @@ -226,7 +229,8 @@ /// of the specified triple. /// ARMSubtarget(const std::string &TT, const std::string &CPU, - const std::string &FS, const TargetOptions &Options); + const std::string &FS, bool IsLittle, + const TargetOptions &Options); /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size /// that still makes it profitable to inline the call. @@ -375,6 +379,8 @@ const std::string & getCPUString() const { return CPUString; } + bool isLittle() const { return IsLittle; } + unsigned getMispredictionPenalty() const; /// This function returns true if the target has sincos() routine in its Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -75,12 +75,14 @@ clEnumValEnd)); ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, - const std::string &FS, const TargetOptions &Options) + const std::string &FS, bool IsLittle, + const TargetOptions &Options) : ARMGenSubtargetInfo(TT, CPU, FS) , ARMProcFamily(Others) , ARMProcClass(None) , stackAlignment(4) , CPUString(CPU) + , IsLittle(IsLittle) , TargetTriple(TT) , Options(Options) , TargetABI(ARM_ABI_UNKNOWN) { Index: lib/Target/ARM/ARMTargetMachine.h =================================================================== --- lib/Target/ARM/ARMTargetMachine.h +++ lib/Target/ARM/ARMTargetMachine.h @@ -42,7 +42,8 @@ StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL); + CodeGenOpt::Level OL, + bool isLittle); ARMJITInfo *getJITInfo() override { return &JITInfo; } const ARMSubtarget *getSubtargetImpl() const override { return &Subtarget; } @@ -77,7 +78,8 @@ StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL); + CodeGenOpt::Level OL, + bool isLittle); const ARMRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); @@ -97,6 +99,28 @@ const DataLayout *getDataLayout() const override { return &DL; } }; +/// ARMleTargetMachine - ARM little endian target machine. +/// +class ARMleTargetMachine : public ARMTargetMachine { + virtual void anchor(); +public: + ARMleTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); +}; + +/// ARMbeTargetMachine - ARM big endian target machine. +/// +class ARMbeTargetMachine : public ARMTargetMachine { + virtual void anchor(); +public: + ARMbeTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); +}; + /// ThumbTargetMachine - Thumb target machine. /// Due to the way architectures are handled, this represents both /// Thumb-1 and Thumb-2. @@ -115,7 +139,8 @@ StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL); + CodeGenOpt::Level OL, + bool isLittle); /// returns either Thumb1RegisterInfo or Thumb2RegisterInfo const ARMBaseRegisterInfo *getRegisterInfo() const override { @@ -141,6 +166,28 @@ const DataLayout *getDataLayout() const override { return &DL; } }; +/// ThumbleTargetMachine - Thumb little endian target machine. +/// +class ThumbleTargetMachine : public ThumbTargetMachine { + virtual void anchor(); +public: + ThumbleTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); +}; + +/// ThumbbeTargetMachine - Thumb big endian target machine. +/// +class ThumbbeTargetMachine : public ThumbTargetMachine { + virtual void anchor(); +public: + ThumbbeTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); +}; + } // end namespace llvm #endif Index: lib/Target/ARM/ARMTargetMachine.cpp =================================================================== --- lib/Target/ARM/ARMTargetMachine.cpp +++ lib/Target/ARM/ARMTargetMachine.cpp @@ -30,8 +30,10 @@ extern "C" void LLVMInitializeARMTarget() { // Register the target. - RegisterTargetMachine X(TheARMTarget); - RegisterTargetMachine Y(TheThumbTarget); + RegisterTargetMachine X(TheARMleTarget); + RegisterTargetMachine Y(TheARMbeTarget); + RegisterTargetMachine A(TheThumbleTarget); + RegisterTargetMachine B(TheThumbbeTarget); } @@ -41,9 +43,10 @@ StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL) + CodeGenOpt::Level OL, + bool isLittle) : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), - Subtarget(TT, CPU, FS, Options), + Subtarget(TT, CPU, FS, isLittle, Options), JITInfo(), InstrItins(Subtarget.getInstrItineraryData()) { @@ -65,9 +68,15 @@ void ARMTargetMachine::anchor() { } static std::string computeDataLayout(ARMSubtarget &ST) { - // Little endian. - std::string Ret = "e"; + std::string Ret = ""; + if (ST.isLittle()) + // Little endian. + Ret += "e"; + else + // Big endian. + Ret += "E"; + Ret += DataLayout::getManglingComponent(ST.getTargetTriple()); // Pointers are 32 bits and aligned to 32 bits. @@ -118,8 +127,9 @@ StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL) - : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), + CodeGenOpt::Level OL, + bool isLittle) + : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle), InstrInfo(Subtarget), DL(computeDataLayout(Subtarget)), TLInfo(*this), @@ -131,14 +141,33 @@ "support ARM mode execution!"); } +void ARMleTargetMachine::anchor() { } + +ARMleTargetMachine:: +ARMleTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} + +void ARMbeTargetMachine::anchor() { } + +ARMbeTargetMachine:: +ARMbeTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} + void ThumbTargetMachine::anchor() { } ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL) - : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), + CodeGenOpt::Level OL, + bool isLittle) + : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle), InstrInfo(Subtarget.hasThumb2() ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget)) : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))), @@ -151,6 +180,24 @@ initAsmInfo(); } +void ThumbleTargetMachine::anchor() { } + +ThumbleTargetMachine:: +ThumbleTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} + +void ThumbbeTargetMachine::anchor() { } + +ThumbbeTargetMachine:: +ThumbbeTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} + namespace { /// ARM Code Generator Pass Configuration Options. class ARMPassConfig : public TargetPassConfig { Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -9088,8 +9088,10 @@ /// Force static initialization. extern "C" void LLVMInitializeARMAsmParser() { - RegisterMCAsmParser X(TheARMTarget); - RegisterMCAsmParser Y(TheThumbTarget); + RegisterMCAsmParser X(TheARMleTarget); + RegisterMCAsmParser Y(TheARMbeTarget); + RegisterMCAsmParser A(TheThumbleTarget); + RegisterMCAsmParser B(TheThumbbeTarget); } #define GET_REGISTER_MATCHER Index: lib/Target/ARM/Disassembler/ARMDisassembler.cpp =================================================================== --- lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -856,10 +856,14 @@ extern "C" void LLVMInitializeARMDisassembler() { - TargetRegistry::RegisterMCDisassembler(TheARMTarget, + TargetRegistry::RegisterMCDisassembler(TheARMleTarget, createARMDisassembler); - TargetRegistry::RegisterMCDisassembler(TheThumbTarget, + TargetRegistry::RegisterMCDisassembler(TheARMbeTarget, + createARMDisassembler); + TargetRegistry::RegisterMCDisassembler(TheThumbleTarget, createThumbDisassembler); + TargetRegistry::RegisterMCDisassembler(TheThumbbeTarget, + createThumbDisassembler); } static const uint16_t GPRDecoderTable[] = { Index: lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -41,11 +41,12 @@ class ARMAsmBackend : public MCAsmBackend { const MCSubtargetInfo* STI; - bool isThumbMode; // Currently emitting Thumb code. + bool isThumbMode; // Currently emitting Thumb code. + bool IsLittleEndian; // Big or little endian. public: - ARMAsmBackend(const Target &T, const StringRef TT) + ARMAsmBackend(const Target &T, const StringRef TT, bool IsLittle) : MCAsmBackend(), STI(ARM_MC::createARMMCSubtargetInfo(TT, "", "")), - isThumbMode(TT.startswith("thumb")) {} + isThumbMode(TT.startswith("thumb")), IsLittleEndian(IsLittle) {} ~ARMAsmBackend() { delete STI; @@ -146,6 +147,7 @@ unsigned getPointerSize() const { return 4; } bool isThumb() const { return isThumbMode; } void setIsThumb(bool it) { isThumbMode = it; } + bool isLittle() const { return IsLittleEndian; } }; } // end anonymous namespace @@ -637,6 +639,54 @@ } } +/// getFixupKindFullSizeBytes - The number of bytes the fixup may change. +static unsigned getFixupKindFullSizeBytes(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + + case FK_Data_1: + case ARM::fixup_arm_thumb_bcc: + case ARM::fixup_arm_thumb_cp: + case ARM::fixup_thumb_adr_pcrel_10: + return 2; + + case FK_Data_2: + case ARM::fixup_arm_thumb_br: + case ARM::fixup_arm_thumb_cb: + return 2; + + case ARM::fixup_arm_pcrel_10_unscaled: + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_uncondbl: + case ARM::fixup_arm_condbl: + case ARM::fixup_arm_blx: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: + return 4; + + case FK_Data_4: + case ARM::fixup_t2_ldst_pcrel_12: + case ARM::fixup_t2_condbranch: + case ARM::fixup_t2_uncondbranch: + case ARM::fixup_t2_pcrel_10: + case ARM::fixup_t2_adr_pcrel_12: + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movt_hi16_pcrel: + case ARM::fixup_arm_movw_lo16_pcrel: + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movt_hi16_pcrel: + case ARM::fixup_t2_movw_lo16_pcrel: + return 4; + } +} + void ARMAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); @@ -646,11 +696,16 @@ unsigned Offset = Fixup.getOffset(); assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); + // Used to point to big endian bytes + unsigned FullSize = getFixupKindFullSizeBytes(Fixup.getKind()); + // For each byte of the fragment that the fixup touches, mask in the bits from // the fixup value. The Value has been "split up" into the appropriate // bitfields above. - for (unsigned i = 0; i != NumBytes; ++i) - Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); + for (unsigned i = 0; i != NumBytes; ++i) { + unsigned Idx = IsLittleEndian ? i : (FullSize - 1 - i); + Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); + } } namespace { @@ -661,11 +716,11 @@ public: uint8_t OSABI; ELFARMAsmBackend(const Target &T, const StringRef TT, - uint8_t _OSABI) - : ARMAsmBackend(T, TT), OSABI(_OSABI) { } + uint8_t _OSABI, bool _IsLittle) + : ARMAsmBackend(T, TT, _IsLittle), OSABI(_OSABI) { } MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { - return createARMELFObjectWriter(OS, OSABI); + return createARMELFObjectWriter(OS, OSABI, isLittle()); } }; @@ -675,7 +730,7 @@ const MachO::CPUSubTypeARM Subtype; DarwinARMAsmBackend(const Target &T, const StringRef TT, MachO::CPUSubTypeARM st) - : ARMAsmBackend(T, TT), Subtype(st) { + : ARMAsmBackend(T, TT, /* IsLittleEndian */ true), Subtype(st) { HasDataInCodeSupport = true; } @@ -690,7 +745,8 @@ MCAsmBackend *llvm::createARMAsmBackend(const Target &T, const MCRegisterInfo &MRI, - StringRef TT, StringRef CPU) { + StringRef TT, StringRef CPU, + bool isLittle) { Triple TheTriple(TT); if (TheTriple.isOSBinFormatMachO()) { @@ -716,5 +772,30 @@ #endif uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); - return new ELFARMAsmBackend(T, TT, OSABI); + return new ELFARMAsmBackend(T, TT, OSABI, isLittle); } + +MCAsmBackend *llvm::createARMleAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { + return createARMAsmBackend(T, MRI, TT, CPU, true); +} + +MCAsmBackend *llvm::createARMbeAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { + return createARMAsmBackend(T, MRI, TT, CPU, false); +} + +MCAsmBackend *llvm::createThumbleAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { + return createARMAsmBackend(T, MRI, TT, CPU, true); +} + +MCAsmBackend *llvm::createThumbbeAsmBackend(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU) { + return createARMAsmBackend(T, MRI, TT, CPU, false); +} + Index: lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -304,7 +304,8 @@ } MCObjectWriter *llvm::createARMELFObjectWriter(raw_ostream &OS, - uint8_t OSABI) { + uint8_t OSABI, + bool IsLittleEndian) { MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI); - return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true); + return createELFObjectWriter(MOTW, OS, IsLittleEndian); } Index: lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h +++ lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h @@ -22,13 +22,13 @@ class ARMMCAsmInfoDarwin : public MCAsmInfoDarwin { void anchor() override; public: - explicit ARMMCAsmInfoDarwin(); + explicit ARMMCAsmInfoDarwin(StringRef TT); }; class ARMELFMCAsmInfo : public MCAsmInfoELF { void anchor() override; public: - explicit ARMELFMCAsmInfo(); + explicit ARMELFMCAsmInfo(StringRef TT); void setUseIntegratedAssembler(bool Value) override; }; Index: lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp +++ lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp @@ -13,12 +13,18 @@ #include "ARMMCAsmInfo.h" #include "llvm/Support/CommandLine.h" +#include "llvm/ADT/Triple.h" using namespace llvm; void ARMMCAsmInfoDarwin::anchor() { } -ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin() { +ARMMCAsmInfoDarwin::ARMMCAsmInfoDarwin(StringRef TT) { + Triple TheTriple(TT); + if ((TheTriple.getArch() == Triple::armeb) || + (TheTriple.getArch() == Triple::thumbeb)) + IsLittleEndian = false; + Data64bitsDirective = 0; CommentString = "@"; Code16Directive = ".code\t16"; @@ -35,7 +41,12 @@ void ARMELFMCAsmInfo::anchor() { } -ARMELFMCAsmInfo::ARMELFMCAsmInfo() { +ARMELFMCAsmInfo::ARMELFMCAsmInfo(StringRef TT) { + Triple TheTriple(TT); + if ((TheTriple.getArch() == Triple::armeb) || + (TheTriple.getArch() == Triple::thumbeb)) + IsLittleEndian = false; + // ".comm align is in bytes but .align is pow-2." AlignmentIsInBytes = false; Index: lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -40,10 +40,11 @@ void operator=(const ARMMCCodeEmitter &) LLVM_DELETED_FUNCTION; const MCInstrInfo &MCII; const MCContext &CTX; + bool IsLittleEndian; public: - ARMMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) - : MCII(mcii), CTX(ctx) { + ARMMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool IsLittle) + : MCII(mcii), CTX(ctx), IsLittleEndian(IsLittle) { } ~ARMMCCodeEmitter() {} @@ -397,8 +398,8 @@ void EmitConstant(uint64_t Val, unsigned Size, raw_ostream &OS) const { // Output the constant in little endian byte order. for (unsigned i = 0; i != Size; ++i) { - EmitByte(Val & 255, OS); - Val >>= 8; + unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; + EmitByte((Val >> Shift) & 0xff, OS); } } @@ -409,13 +410,20 @@ } // end anonymous namespace -MCCodeEmitter *llvm::createARMMCCodeEmitter(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new ARMMCCodeEmitter(MCII, Ctx); +MCCodeEmitter *llvm::createARMleMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new ARMMCCodeEmitter(MCII, Ctx, true); } +MCCodeEmitter *llvm::createARMbeMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new ARMMCCodeEmitter(MCII, Ctx, false); +} + /// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing /// instructions, and rewrite them to their Thumb2 form if we are currently in /// Thumb2 mode. Index: lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h +++ lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h @@ -33,7 +33,8 @@ class Target; class raw_ostream; -extern Target TheARMTarget, TheThumbTarget; +extern Target TheARMleTarget, TheThumbleTarget; +extern Target TheARMbeTarget, TheThumbbeTarget; namespace ARM_MC { std::string ParseARMTriple(StringRef TT, StringRef CPU); @@ -51,17 +52,36 @@ MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); -MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, - MCContext &Ctx); +MCCodeEmitter *createARMleMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx); +MCCodeEmitter *createARMbeMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI, + MCContext &Ctx); + MCAsmBackend *createARMAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU, + bool IsLittleEndian); + +MCAsmBackend *createARMleAsmBackend(const Target &T, const MCRegisterInfo &MRI, StringRef TT, StringRef CPU); +MCAsmBackend *createARMbeAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); + +MCAsmBackend *createThumbleAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); + +MCAsmBackend *createThumbbeAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); + /// createARMELFObjectWriter - Construct an ELF Mach-O object writer. MCObjectWriter *createARMELFObjectWriter(raw_ostream &OS, - uint8_t OSABI); + uint8_t OSABI, + bool IsLittleEndian); /// createARMMachObjectWriter - Construct an ARM Mach-O object writer. MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS, Index: lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp +++ lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp @@ -89,11 +89,16 @@ unsigned Idx = 0; // FIXME: Enhance Triple helper class to extract ARM version. - bool isThumb = triple.getArch() == Triple::thumb; + bool isThumb = triple.getArch() == Triple::thumb || + triple.getArch() == Triple::thumbeb; if (Len >= 5 && TT.substr(0, 4) == "armv") Idx = 4; + else if (Len >= 5 && TT.substr(0, 4) == "armebv") + Idx = 6; else if (Len >= 7 && TT.substr(0, 6) == "thumbv") Idx = 6; + else if (Len >= 7 && TT.substr(0, 6) == "thumbebv") + Idx = 8; bool NoCPU = CPU == "generic" || CPU.empty(); std::string ARMArchFeature; @@ -214,9 +219,9 @@ MCAsmInfo *MAI; if (TheTriple.isOSBinFormatMachO()) - MAI = new ARMMCAsmInfoDarwin(); + MAI = new ARMMCAsmInfoDarwin(TT); else - MAI = new ARMELFMCAsmInfo(); + MAI = new ARMELFMCAsmInfo(TT); unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true); MAI->addInitialFrameState(MCCFIInstruction::createDefCfa(0, Reg, 0)); @@ -323,56 +328,94 @@ // Force static initialization. extern "C" void LLVMInitializeARMTargetMC() { // Register the MC asm info. - RegisterMCAsmInfoFn A(TheARMTarget, createARMMCAsmInfo); - RegisterMCAsmInfoFn B(TheThumbTarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn X(TheARMleTarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn Y(TheARMbeTarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn A(TheThumbleTarget, createARMMCAsmInfo); + RegisterMCAsmInfoFn B(TheThumbbeTarget, createARMMCAsmInfo); // Register the MC codegen info. - TargetRegistry::RegisterMCCodeGenInfo(TheARMTarget, createARMMCCodeGenInfo); - TargetRegistry::RegisterMCCodeGenInfo(TheThumbTarget, createARMMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheARMleTarget, createARMMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheARMbeTarget, createARMMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheThumbleTarget, createARMMCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheThumbbeTarget, createARMMCCodeGenInfo); // Register the MC instruction info. - TargetRegistry::RegisterMCInstrInfo(TheARMTarget, createARMMCInstrInfo); - TargetRegistry::RegisterMCInstrInfo(TheThumbTarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheARMleTarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheARMbeTarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheThumbleTarget, createARMMCInstrInfo); + TargetRegistry::RegisterMCInstrInfo(TheThumbbeTarget, createARMMCInstrInfo); // Register the MC register info. - TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo); - TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheARMleTarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheARMbeTarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheThumbleTarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCRegInfo(TheThumbbeTarget, createARMMCRegisterInfo); // Register the MC subtarget info. - TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget, + TargetRegistry::RegisterMCSubtargetInfo(TheARMleTarget, ARM_MC::createARMMCSubtargetInfo); - TargetRegistry::RegisterMCSubtargetInfo(TheThumbTarget, + TargetRegistry::RegisterMCSubtargetInfo(TheARMbeTarget, ARM_MC::createARMMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(TheThumbleTarget, + ARM_MC::createARMMCSubtargetInfo); + TargetRegistry::RegisterMCSubtargetInfo(TheThumbbeTarget, + ARM_MC::createARMMCSubtargetInfo); // Register the MC instruction analyzer. - TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget, + TargetRegistry::RegisterMCInstrAnalysis(TheARMleTarget, createARMMCInstrAnalysis); - TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget, + TargetRegistry::RegisterMCInstrAnalysis(TheARMbeTarget, createARMMCInstrAnalysis); + TargetRegistry::RegisterMCInstrAnalysis(TheThumbleTarget, + createARMMCInstrAnalysis); + TargetRegistry::RegisterMCInstrAnalysis(TheThumbbeTarget, + createARMMCInstrAnalysis); // Register the MC Code Emitter - TargetRegistry::RegisterMCCodeEmitter(TheARMTarget, createARMMCCodeEmitter); - TargetRegistry::RegisterMCCodeEmitter(TheThumbTarget, createARMMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheARMleTarget, + createARMleMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheARMbeTarget, + createARMbeMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheThumbleTarget, + createARMleMCCodeEmitter); + TargetRegistry::RegisterMCCodeEmitter(TheThumbbeTarget, + createARMbeMCCodeEmitter); // Register the asm backend. - TargetRegistry::RegisterMCAsmBackend(TheARMTarget, createARMAsmBackend); - TargetRegistry::RegisterMCAsmBackend(TheThumbTarget, createARMAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheARMleTarget, createARMleAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheARMbeTarget, createARMbeAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheThumbleTarget, + createThumbleAsmBackend); + TargetRegistry::RegisterMCAsmBackend(TheThumbbeTarget, + createThumbbeAsmBackend); // Register the object streamer. - TargetRegistry::RegisterMCObjectStreamer(TheARMTarget, createMCStreamer); - TargetRegistry::RegisterMCObjectStreamer(TheThumbTarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheARMleTarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheARMbeTarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheThumbleTarget, createMCStreamer); + TargetRegistry::RegisterMCObjectStreamer(TheThumbbeTarget, createMCStreamer); // Register the asm streamer. - TargetRegistry::RegisterAsmStreamer(TheARMTarget, createMCAsmStreamer); - TargetRegistry::RegisterAsmStreamer(TheThumbTarget, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheARMleTarget, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheARMbeTarget, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheThumbleTarget, createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheThumbbeTarget, createMCAsmStreamer); // Register the MCInstPrinter. - TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheARMleTarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheARMbeTarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheThumbleTarget, + createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheThumbbeTarget, + createARMMCInstPrinter); // Register the MC relocation info. - TargetRegistry::RegisterMCRelocationInfo(TheARMTarget, + TargetRegistry::RegisterMCRelocationInfo(TheARMleTarget, createARMMCRelocationInfo); - TargetRegistry::RegisterMCRelocationInfo(TheThumbTarget, + TargetRegistry::RegisterMCRelocationInfo(TheARMbeTarget, createARMMCRelocationInfo); + TargetRegistry::RegisterMCRelocationInfo(TheThumbleTarget, + createARMMCRelocationInfo); + TargetRegistry::RegisterMCRelocationInfo(TheThumbbeTarget, + createARMMCRelocationInfo); } Index: lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp =================================================================== --- lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp +++ lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp @@ -12,12 +12,17 @@ #include "llvm/Support/TargetRegistry.h" using namespace llvm; -Target llvm::TheARMTarget, llvm::TheThumbTarget; +Target llvm::TheARMleTarget, llvm::TheARMbeTarget; +Target llvm::TheThumbleTarget, llvm::TheThumbbeTarget; extern "C" void LLVMInitializeARMTargetInfo() { RegisterTarget - X(TheARMTarget, "arm", "ARM"); + X(TheARMleTarget, "arm", "ARM"); + RegisterTarget + Y(TheARMbeTarget, "armeb", "ARM (big endian)"); RegisterTarget - Y(TheThumbTarget, "thumb", "Thumb"); + A(TheThumbleTarget, "thumb", "Thumb"); + RegisterTarget + B(TheThumbbeTarget, "thumbeb", "Thumb (big endian)"); }