Index: include/llvm/ADT/Triple.h =================================================================== --- include/llvm/ADT/Triple.h +++ include/llvm/ADT/Triple.h @@ -64,6 +64,7 @@ amdgcn, // AMDGCN: AMD GCN GPUs sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 + sparc_le, // Sparc: (little endian sparc) systemz, // SystemZ: s390x tce, // TCE (http://tce.cs.tut.fi/): tce thumb, // Thumb (little endian): thumb, thumbv.* Index: include/llvm/Object/ELFObjectFile.h =================================================================== --- include/llvm/Object/ELFObjectFile.h +++ include/llvm/Object/ELFObjectFile.h @@ -928,7 +928,7 @@ case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: - return Triple::sparc; + return IsLittleEndian ? Triple::sparc_le : Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; Index: lib/MC/MCObjectFileInfo.cpp =================================================================== --- lib/MC/MCObjectFileInfo.cpp +++ lib/MC/MCObjectFileInfo.cpp @@ -337,6 +337,7 @@ TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; break; + case Triple::sparc_le: case Triple::sparc: if (RelocM == Reloc::PIC_) { LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; Index: lib/Support/Triple.cpp =================================================================== --- lib/Support/Triple.cpp +++ lib/Support/Triple.cpp @@ -37,6 +37,7 @@ case amdgcn: return "amdgcn"; case sparc: return "sparc"; case sparcv9: return "sparcv9"; + case sparc_le: return "sparc_le"; case systemz: return "s390x"; case tce: return "tce"; case thumb: return "thumb"; @@ -90,6 +91,7 @@ case bpf: return "bpf"; case sparcv9: + case sparc_le: case sparc: return "sparc"; case systemz: return "systemz"; @@ -311,6 +313,7 @@ .Case("hexagon", Triple::hexagon) .Case("s390x", Triple::systemz) .Case("sparc", Triple::sparc) + .Case("sparc_le", Triple::sparc_le) .Cases("sparcv9", "sparc64", Triple::sparcv9) .Case("tce", Triple::tce) .Case("xcore", Triple::xcore) @@ -916,6 +919,7 @@ case llvm::Triple::ppc: case llvm::Triple::r600: case llvm::Triple::sparc: + case llvm::Triple::sparc_le: case llvm::Triple::tce: case llvm::Triple::thumb: case llvm::Triple::thumbeb: @@ -988,6 +992,7 @@ case Triple::ppc: case Triple::r600: case Triple::sparc: + case Triple::sparc_le: case Triple::tce: case Triple::thumb: case Triple::thumbeb: @@ -1024,6 +1029,7 @@ case Triple::thumb: case Triple::thumbeb: case Triple::xcore: + case Triple::sparc_le: T.setArch(UnknownArch); break; Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -910,6 +910,7 @@ extern "C" void LLVMInitializeSparcAsmParser() { RegisterMCAsmParser A(TheSparcTarget); RegisterMCAsmParser B(TheSparcV9Target); + RegisterMCAsmParser C(TheSparc_leTarget); } #define GET_REGISTER_MATCHER Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp =================================================================== --- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -16,6 +16,8 @@ #include "SparcSubtarget.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -42,7 +44,7 @@ } namespace llvm { - extern Target TheSparcTarget, TheSparcV9Target; + extern Target TheSparcTarget, TheSparcV9Target, TheSparc_leTarget; } static MCDisassembler *createSparcDisassembler( @@ -59,6 +61,8 @@ createSparcDisassembler); TargetRegistry::RegisterMCDisassembler(TheSparcV9Target, createSparcDisassembler); + TargetRegistry::RegisterMCDisassembler(TheSparc_leTarget, + createSparcDisassembler); } @@ -208,16 +212,17 @@ /// Read four bytes from the ArrayRef and return 32 bit word. static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address, - uint64_t &Size, uint32_t &Insn) { + uint64_t &Size, uint32_t &Insn, + bool IsLittleEndian) { // We want to read exactly 4 Bytes of data. if (Bytes.size() < 4) { Size = 0; return MCDisassembler::Fail; } - // Encoded as a big-endian 32-bit word in the stream. - Insn = - (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24); + Insn = IsLittleEndian + ? (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | (Bytes[3] << 24) + : (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24); return MCDisassembler::Success; } @@ -228,8 +233,9 @@ raw_ostream &VStream, raw_ostream &CStream) const { uint32_t Insn; - - DecodeStatus Result = readInstruction32(Bytes, Address, Size, Insn); + bool isLittleEndian = getContext().getAsmInfo()->isLittleEndian(); + DecodeStatus Result = readInstruction32(Bytes, Address, Size, Insn, + isLittleEndian); if (Result == MCDisassembler::Fail) return MCDisassembler::Fail; Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -220,6 +220,10 @@ StringRef name = TheTarget.getName(); return name == "sparcv9"; } + bool isLittleEndian() const { + StringRef name = TheTarget.getName(); + return name == "sparc_le"; + } }; class ELFSparcAsmBackend : public SparcAsmBackend { @@ -246,7 +250,7 @@ MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); - return createSparcELFObjectWriter(OS, is64Bit(), OSABI); + return createSparcELFObjectWriter(OS, is64Bit(), isLittleEndian(), OSABI); } }; Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -106,7 +106,8 @@ MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS, bool Is64Bit, + bool IsLittleEndian, uint8_t OSABI) { MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI); - return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); + return createELFObjectWriter(MOTW, OS, IsLittleEndian); } Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp @@ -21,9 +21,9 @@ void SparcELFMCAsmInfo::anchor() { } SparcELFMCAsmInfo::SparcELFMCAsmInfo(StringRef TT) { - IsLittleEndian = false; Triple TheTriple(TT); bool isV9 = (TheTriple.getArch() == Triple::sparcv9); + IsLittleEndian = (TheTriple.getArch() == Triple::sparc_le); if (isV9) { PointerSize = CalleeSaveStackSlotSize = 8; Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -21,6 +21,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -84,10 +85,18 @@ const MCSubtargetInfo &STI) const { unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI); - // Output the constant in big endian byte order. - for (unsigned i = 0; i != 4; ++i) { - OS << (char)(Bits >> 24); - Bits <<= 8; + if (Ctx.getAsmInfo()->isLittleEndian()) { + // Output the bits in little-endian byte order. + for (unsigned i = 0; i != 4; ++i) { + OS << (char)Bits; + Bits >>= 8; + } + } else { + // Output the bits in big-endian byte order. + for (unsigned i = 0; i != 4; ++i) { + OS << (char)(Bits >> 24); + Bits <<= 8; + } } unsigned tlsOpNo = 0; switch (MI.getOpcode()) { Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h @@ -30,6 +30,7 @@ extern Target TheSparcTarget; extern Target TheSparcV9Target; +extern Target TheSparc_leTarget; MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, @@ -40,6 +41,7 @@ StringRef CPU); MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS, bool Is64Bit, + bool IsLIttleEndian, uint8_t OSABI); } // End llvm namespace Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -147,8 +147,9 @@ // Register the MC asm info. RegisterMCAsmInfoFn X(TheSparcTarget, createSparcMCAsmInfo); RegisterMCAsmInfoFn Y(TheSparcV9Target, createSparcV9MCAsmInfo); + RegisterMCAsmInfoFn Z(TheSparc_leTarget, createSparcMCAsmInfo); - for (Target *T : {&TheSparcTarget, &TheSparcV9Target}) { + for (Target *T : {&TheSparcTarget, &TheSparcV9Target, &TheSparc_leTarget}) { // Register the MC instruction info. TargetRegistry::RegisterMCInstrInfo(*T, createSparcMCInstrInfo); @@ -180,5 +181,7 @@ createSparcMCCodeGenInfo); TargetRegistry::RegisterMCCodeGenInfo(TheSparcV9Target, createSparcV9MCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheSparc_leTarget, + createSparcMCCodeGenInfo); } Index: lib/Target/Sparc/SparcAsmPrinter.cpp =================================================================== --- lib/Target/Sparc/SparcAsmPrinter.cpp +++ lib/Target/Sparc/SparcAsmPrinter.cpp @@ -463,4 +463,5 @@ extern "C" void LLVMInitializeSparcAsmPrinter() { RegisterAsmPrinter X(TheSparcTarget); RegisterAsmPrinter Y(TheSparcV9Target); + RegisterAsmPrinter Z(TheSparc_leTarget); } Index: lib/Target/Sparc/SparcSubtarget.h =================================================================== --- lib/Target/Sparc/SparcSubtarget.h +++ lib/Target/Sparc/SparcSubtarget.h @@ -31,6 +31,7 @@ class SparcSubtarget : public SparcGenSubtargetInfo { virtual void anchor(); + bool IsLittleEndian; bool IsV9; bool V8DeprecatedInsts; bool IsVIS, IsVIS2, IsVIS3; @@ -60,6 +61,7 @@ return &TSInfo; } + bool isLittleEndian() const { return IsLittleEndian; } bool isV9() const { return IsV9; } bool isVIS() const { return IsVIS; } bool isVIS2() const { return IsVIS2; } @@ -71,7 +73,7 @@ /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); - SparcSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); + SparcSubtarget &initializeSubtargetDependencies(Triple TT, StringRef CPU, StringRef FS); bool is64Bit() const { return Is64Bit; } Index: lib/Target/Sparc/SparcSubtarget.cpp =================================================================== --- lib/Target/Sparc/SparcSubtarget.cpp +++ lib/Target/Sparc/SparcSubtarget.cpp @@ -26,7 +26,8 @@ void SparcSubtarget::anchor() { } -SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU, +SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(Triple Triple, + StringRef CPU, StringRef FS) { IsV9 = false; V8DeprecatedInsts = false; @@ -46,6 +47,9 @@ if (!IsV9) UsePopc = false; + // cribbed from PPCSubtarget.cpp (despite the associated FIXME) + IsLittleEndian = (Triple.getArch() == Triple::sparc_le); + return *this; } @@ -53,7 +57,7 @@ const std::string &FS, TargetMachine &TM, bool is64Bit) : SparcGenSubtargetInfo(TT, CPU, FS), Is64Bit(is64Bit), - InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), + InstrInfo(initializeSubtargetDependencies(Triple(TT), CPU, FS)), TLInfo(TM, *this), TSInfo(*TM.getDataLayout()), FrameLowering(*this) {} int SparcSubtarget::getAdjustedFrameSize(int frameSize) const { Index: lib/Target/Sparc/SparcTargetMachine.h =================================================================== --- lib/Target/Sparc/SparcTargetMachine.h +++ lib/Target/Sparc/SparcTargetMachine.h @@ -27,7 +27,7 @@ SparcTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL, bool is64bit); + CodeGenOpt::Level OL, bool is64bit, bool isLitleEndian); ~SparcTargetMachine() override; const SparcSubtarget *getSubtargetImpl(const Function &) const override { @@ -65,6 +65,16 @@ CodeGenOpt::Level OL); }; +class Sparc_leTargetMachine : public SparcTargetMachine { + virtual void anchor(); +public: + Sparc_leTargetMachine(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/Sparc/SparcTargetMachine.cpp =================================================================== --- lib/Target/Sparc/SparcTargetMachine.cpp +++ lib/Target/Sparc/SparcTargetMachine.cpp @@ -22,11 +22,15 @@ // Register the target. RegisterTargetMachine X(TheSparcTarget); RegisterTargetMachine Y(TheSparcV9Target); + RegisterTargetMachine Z(TheSparc_leTarget); } -static std::string computeDataLayout(bool is64Bit) { - // Sparc is big endian. - std::string Ret = "E-m:e"; +static std::string computeDataLayout(const Triple &T, + bool is64Bit, + bool isLittleEndian) { + // Sparc is typically big endian, but some are little. + std::string Ret = isLittleEndian ? "e" : "E"; + Ret += "-m:e"; // Some ABIs have 32bit pointers. if (!is64Bit) @@ -56,9 +60,11 @@ StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL, bool is64bit) - : LLVMTargetMachine(T, computeDataLayout(is64bit), TT, CPU, FS, Options, RM, - CM, OL), + CodeGenOpt::Level OL, bool is64bit, + bool isLittleEndian) + : LLVMTargetMachine(T, + computeDataLayout(Triple(TT), is64bit, isLittleEndian), + TT, CPU, FS, Options, RM, CM, OL), TLOF(make_unique()), Subtarget(TT, CPU, FS, *this, is64bit) { initAsmInfo(); @@ -111,7 +117,7 @@ Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) - : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) { + : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false, false) { } void SparcV9TargetMachine::anchor() { } @@ -123,5 +129,17 @@ Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) - : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) { + : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true, false) { +} + +void Sparc_leTargetMachine::anchor() { } + +Sparc_leTargetMachine::Sparc_leTargetMachine(const Target &T, + StringRef TT, StringRef CPU, + StringRef FS, + const TargetOptions &Options, + Reloc::Model RM, + CodeModel::Model CM, + CodeGenOpt::Level OL) + : SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false, true) { } Index: lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp =================================================================== --- lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp +++ lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp @@ -14,10 +14,13 @@ Target llvm::TheSparcTarget; Target llvm::TheSparcV9Target; +Target llvm::TheSparc_leTarget; extern "C" void LLVMInitializeSparcTargetInfo() { RegisterTarget X(TheSparcTarget, "sparc", "Sparc"); RegisterTarget Y(TheSparcV9Target, "sparcv9", "Sparc V9"); + RegisterTarget + Z(TheSparc_leTarget, "sparc_le", "Sparc LE"); }