[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
This commit is contained in:
Douglas Katzman 2015-04-29 20:30:57 +00:00
parent 58a854d447
commit 1b88927253
14 changed files with 97 additions and 61 deletions

View File

@ -928,7 +928,7 @@ unsigned ELFObjectFile<ELFT>::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;

View File

@ -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;

View File

@ -907,10 +907,10 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
return true;
}
extern "C" void LLVMInitializeSparcAsmParser() {
RegisterMCAsmParser<SparcAsmParser> A(TheSparcTarget);
RegisterMCAsmParser<SparcAsmParser> B(TheSparcV9Target);
RegisterMCAsmParser<SparcAsmParser> C(TheSparcelTarget);
}
#define GET_REGISTER_MATCHER

View File

@ -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<uint8_t> 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);

View File

@ -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);
}
};

View File

@ -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);
}

View File

@ -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;

View File

@ -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<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
void SparcMCCodeEmitter::EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &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()) {

View File

@ -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);
}

View File

@ -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

View File

@ -445,4 +445,5 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
extern "C" void LLVMInitializeSparcAsmPrinter() {
RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
RegisterAsmPrinter<SparcAsmPrinter> Y(TheSparcV9Target);
RegisterAsmPrinter<SparcAsmPrinter> Z(TheSparcelTarget);
}

View File

@ -22,11 +22,13 @@ extern "C" void LLVMInitializeSparcTarget() {
// Register the target.
RegisterTargetMachine<SparcV8TargetMachine> X(TheSparcTarget);
RegisterTargetMachine<SparcV9TargetMachine> Y(TheSparcV9Target);
RegisterTargetMachine<SparcelTargetMachine> 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<SparcELFTargetObjectFile>()),
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) {}

View File

@ -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);
};

View File

@ -14,10 +14,13 @@ using namespace llvm;
Target llvm::TheSparcTarget;
Target llvm::TheSparcV9Target;
Target llvm::TheSparcelTarget;
extern "C" void LLVMInitializeSparcTargetInfo() {
RegisterTarget<Triple::sparc, /*HasJIT=*/ true>
X(TheSparcTarget, "sparc", "Sparc");
RegisterTarget<Triple::sparcv9, /*HasJIT=*/ true>
Y(TheSparcV9Target, "sparcv9", "Sparc V9");
RegisterTarget<Triple::sparc, /*HasJIT=*/true> X(TheSparcTarget, "sparc",
"Sparc");
RegisterTarget<Triple::sparcv9, /*HasJIT=*/true> Y(TheSparcV9Target,
"sparcv9", "Sparc V9");
RegisterTarget<Triple::sparcel, /*HasJIT=*/true> Z(TheSparcelTarget,
"sparcel", "Sparc LE");
}