From 1b88927253cef3d8d715f0e881880472504b9824 Mon Sep 17 00:00:00 2001 From: Douglas Katzman Date: Wed, 29 Apr 2015 20:30:57 +0000 Subject: [PATCH] [Sparc] Really add sparcel architecture support. Mostly copy-and-paste from Sparc v8 architecture. Differential Revision: http://reviews.llvm.org/D8741 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236146 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELFObjectFile.h | 2 +- lib/MC/MCObjectFileInfo.cpp | 1 + lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 2 +- .../Sparc/Disassembler/SparcDisassembler.cpp | 33 ++++++++++--------- .../Sparc/MCTargetDesc/SparcAsmBackend.cpp | 8 ++--- .../MCTargetDesc/SparcELFObjectWriter.cpp | 6 ++-- .../Sparc/MCTargetDesc/SparcMCAsmInfo.cpp | 4 +-- .../Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp | 24 +++++++++----- .../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 10 +++--- .../Sparc/MCTargetDesc/SparcMCTargetDesc.h | 9 +++-- lib/Target/Sparc/SparcAsmPrinter.cpp | 1 + lib/Target/Sparc/SparcTargetMachine.cpp | 32 +++++++++++------- lib/Target/Sparc/SparcTargetMachine.h | 15 +++++++-- .../Sparc/TargetInfo/SparcTargetInfo.cpp | 11 ++++--- 14 files changed, 97 insertions(+), 61 deletions(-) diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index e7eba976fd4..464efe87fe4 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -928,7 +928,7 @@ unsigned ELFObjectFile::getArch() const { case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: - return Triple::sparc; + return IsLittleEndian ? Triple::sparcel : Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index cd7036249ad..02fc55e0749 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -337,6 +337,7 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8; break; + case Triple::sparcel: case Triple::sparc: if (RelocM == Reloc::PIC_) { LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index a094011366d..7e979e50e97 100644 --- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -907,10 +907,10 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, return true; } - extern "C" void LLVMInitializeSparcAsmParser() { RegisterMCAsmParser A(TheSparcTarget); RegisterMCAsmParser B(TheSparcV9Target); + RegisterMCAsmParser C(TheSparcelTarget); } #define GET_REGISTER_MATCHER diff --git a/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp index 8bc4ca98161..8a6f3a65001 100644 --- a/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ b/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; @@ -38,17 +40,15 @@ public: raw_ostream &VStream, raw_ostream &CStream) const override; }; - } namespace llvm { - extern Target TheSparcTarget, TheSparcV9Target; +extern Target TheSparcTarget, TheSparcV9Target, TheSparcelTarget; } -static MCDisassembler *createSparcDisassembler( - const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx) { +static MCDisassembler *createSparcDisassembler(const Target &T, + const MCSubtargetInfo &STI, + MCContext &Ctx) { return new SparcDisassembler(STI, Ctx); } @@ -59,10 +59,10 @@ extern "C" void LLVMInitializeSparcDisassembler() { createSparcDisassembler); TargetRegistry::RegisterMCDisassembler(TheSparcV9Target, createSparcDisassembler); + TargetRegistry::RegisterMCDisassembler(TheSparcelTarget, + createSparcDisassembler); } - - static const unsigned IntRegDecoderTable[] = { SP::G0, SP::G1, SP::G2, SP::G3, SP::G4, SP::G5, SP::G6, SP::G7, @@ -208,16 +208,19 @@ static DecodeStatus DecodeSWAP(MCInst &Inst, unsigned insn, uint64_t Address, /// 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,12 +231,12 @@ DecodeStatus SparcDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, 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; - // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTableSparc32, Instr, Insn, Address, this, STI); diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index 4abb6b8d25d..c9c3f537996 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -216,9 +216,9 @@ namespace { return true; } - bool is64Bit() const { - StringRef name = TheTarget.getName(); - return name == "sparcv9"; + bool is64Bit() const { return StringRef(TheTarget.getName()) == "sparcv9"; } + bool isLittleEndian() const { + return StringRef(TheTarget.getName()) == "sparcel"; } }; @@ -246,7 +246,7 @@ namespace { MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); - return createSparcELFObjectWriter(OS, is64Bit(), OSABI); + return createSparcELFObjectWriter(OS, is64Bit(), isLittleEndian(), OSABI); } }; diff --git a/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp index 98ba7e6a631..4f07ae21920 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -106,7 +106,9 @@ unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target, } MCObjectWriter *llvm::createSparcELFObjectWriter(raw_pwrite_stream &OS, - bool Is64Bit, uint8_t OSABI) { + bool Is64Bit, + bool IsLittleEndian, + uint8_t OSABI) { MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI); - return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); + return createELFObjectWriter(MOTW, OS, IsLittleEndian); } diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp index 6767e4b224f..124cb3b4b98 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp @@ -18,12 +18,12 @@ using namespace llvm; -void SparcELFMCAsmInfo::anchor() { } +void SparcELFMCAsmInfo::anchor() {} SparcELFMCAsmInfo::SparcELFMCAsmInfo(StringRef TT) { - IsLittleEndian = false; Triple TheTriple(TT); bool isV9 = (TheTriple.getArch() == Triple::sparcv9); + IsLittleEndian = (TheTriple.getArch() == Triple::sparcel); if (isV9) { PointerSize = CalleeSaveStackSlotSize = 8; diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp index b447ab3a75f..ff5a3cb32b3 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ b/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; @@ -78,16 +79,23 @@ MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII, return new SparcMCCodeEmitter(Ctx); } -void SparcMCCodeEmitter:: -EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { +void SparcMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + 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()) { diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp index 78954047fc9..5ab45bf82db 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -146,8 +146,9 @@ extern "C" void LLVMInitializeSparcTargetMC() { // Register the MC asm info. RegisterMCAsmInfoFn X(TheSparcTarget, createSparcMCAsmInfo); RegisterMCAsmInfoFn Y(TheSparcV9Target, createSparcV9MCAsmInfo); + RegisterMCAsmInfoFn Z(TheSparcelTarget, createSparcMCAsmInfo); - for (Target *T : {&TheSparcTarget, &TheSparcV9Target}) { + for (Target *T : {&TheSparcTarget, &TheSparcV9Target, &TheSparcelTarget}) { // Register the MC instruction info. TargetRegistry::RegisterMCInstrInfo(*T, createSparcMCInstrInfo); @@ -176,8 +177,9 @@ extern "C" void LLVMInitializeSparcTargetMC() { // Register the MC codegen info. TargetRegistry::RegisterMCCodeGenInfo(TheSparcTarget, - createSparcMCCodeGenInfo); + createSparcMCCodeGenInfo); TargetRegistry::RegisterMCCodeGenInfo(TheSparcV9Target, - createSparcV9MCCodeGenInfo); - + createSparcV9MCCodeGenInfo); + TargetRegistry::RegisterMCCodeGenInfo(TheSparcelTarget, + createSparcMCCodeGenInfo); } diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h index 5f38b12403e..28e211948c3 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h @@ -31,16 +31,15 @@ class raw_ostream; extern Target TheSparcTarget; extern Target TheSparcV9Target; +extern Target TheSparcelTarget; MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx); -MCAsmBackend *createSparcAsmBackend(const Target &T, - const MCRegisterInfo &MRI, - StringRef TT, - StringRef CPU); +MCAsmBackend *createSparcAsmBackend(const Target &T, const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); MCObjectWriter *createSparcELFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit, - uint8_t OSABI); + bool IsLIttleEndian, uint8_t OSABI); } // End llvm namespace // Defines symbolic names for Sparc registers. This defines a mapping from diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp index a976e101f77..5bfa2878896 100644 --- a/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -445,4 +445,5 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, extern "C" void LLVMInitializeSparcAsmPrinter() { RegisterAsmPrinter X(TheSparcTarget); RegisterAsmPrinter Y(TheSparcV9Target); + RegisterAsmPrinter Z(TheSparcelTarget); } diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp index 6979a176232..d43cd9e3127 100644 --- a/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/lib/Target/Sparc/SparcTargetMachine.cpp @@ -22,11 +22,13 @@ extern "C" void LLVMInitializeSparcTarget() { // Register the target. RegisterTargetMachine X(TheSparcTarget); RegisterTargetMachine Y(TheSparcV9Target); + RegisterTargetMachine Z(TheSparcelTarget); } -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) { + // Sparc is typically big endian, but some are little. + std::string Ret = T.getArch() == Triple::sparcel ? "e" : "E"; + Ret += "-m:e"; // Some ABIs have 32bit pointers. if (!is64Bit) @@ -57,8 +59,8 @@ SparcTargetMachine::SparcTargetMachine(const Target &T, StringRef TT, 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), + : LLVMTargetMachine(T, computeDataLayout(Triple(TT), is64bit), TT, CPU, FS, + Options, RM, CM, OL), TLOF(make_unique()), Subtarget(TT, CPU, FS, *this, is64bit) { initAsmInfo(); @@ -116,12 +118,18 @@ SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, void SparcV9TargetMachine::anchor() { } -SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, - StringRef TT, StringRef CPU, - StringRef FS, +SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, const TargetOptions &Options, - Reloc::Model RM, - CodeModel::Model CM, + 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) {} + +void SparcelTargetMachine::anchor() {} + +SparcelTargetMachine::SparcelTargetMachine(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) {} diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h index 30a8ebf75d9..fd05b8c711b 100644 --- a/lib/Target/Sparc/SparcTargetMachine.h +++ b/lib/Target/Sparc/SparcTargetMachine.h @@ -58,9 +58,18 @@ public: class SparcV9TargetMachine : public SparcTargetMachine { virtual void anchor(); public: - SparcV9TargetMachine(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, + SparcV9TargetMachine(const Target &T, StringRef TT, StringRef CPU, + StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); +}; + +class SparcelTargetMachine : public SparcTargetMachine { + virtual void anchor(); + +public: + SparcelTargetMachine(const Target &T, StringRef TT, StringRef CPU, + StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); }; diff --git a/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp b/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp index 4eea16370ea..ab1c6beee4e 100644 --- a/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp +++ b/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp @@ -14,10 +14,13 @@ using namespace llvm; Target llvm::TheSparcTarget; Target llvm::TheSparcV9Target; +Target llvm::TheSparcelTarget; extern "C" void LLVMInitializeSparcTargetInfo() { - RegisterTarget - X(TheSparcTarget, "sparc", "Sparc"); - RegisterTarget - Y(TheSparcV9Target, "sparcv9", "Sparc V9"); + RegisterTarget X(TheSparcTarget, "sparc", + "Sparc"); + RegisterTarget Y(TheSparcV9Target, + "sparcv9", "Sparc V9"); + RegisterTarget Z(TheSparcelTarget, + "sparcel", "Sparc LE"); }