1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

[Sparc] Add initial implementation of MC Code emitter for sparc.

llvm-svn: 198533
This commit is contained in:
Venkatraman Govindaraju 2014-01-05 02:13:48 +00:00
parent bbc434b85c
commit 7b675d45b0
11 changed files with 397 additions and 4 deletions

View File

@ -3,6 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td)
tablegen(LLVM SparcGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter)
tablegen(LLVM SparcGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM SparcGenDAGISel.inc -gen-dag-isel)

View File

@ -1,6 +1,8 @@
add_llvm_library(LLVMSparcDesc
SparcMCTargetDesc.cpp
SparcAsmBackend.cpp
SparcMCAsmInfo.cpp
SparcMCCodeEmitter.cpp
SparcMCTargetDesc.cpp
SparcMCExpr.cpp
SparcTargetStreamer.cpp
)

View File

@ -0,0 +1,101 @@
//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCAsmBackend.h"
#include "MCTargetDesc/SparcMCTargetDesc.h"
#include "MCTargetDesc/SparcFixupKinds.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
namespace {
class SparcAsmBackend : public MCAsmBackend {
public:
SparcAsmBackend(const Target &T) : MCAsmBackend() {}
unsigned getNumFixupKinds() const {
return Sparc::NumTargetFixupKinds;
}
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = {
// name offset bits flags
{ "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }
};
if (Kind < FirstTargetFixupKind)
return MCAsmBackend::getFixupKindInfo(Kind);
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
"Invalid kind!");
return Infos[Kind - FirstTargetFixupKind];
}
bool mayNeedRelaxation(const MCInst &Inst) const {
// FIXME.
return false;
}
/// fixupNeedsRelaxation - Target specific predicate for whether a given
/// fixup requires the associated instruction to be relaxed.
bool fixupNeedsRelaxation(const MCFixup &Fixup,
uint64_t Value,
const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const {
// FIXME.
assert(0 && "fixupNeedsRelaxation() unimplemented");
return false;
}
void relaxInstruction(const MCInst &Inst, MCInst &Res) const {
// FIXME.
assert(0 && "relaxInstruction() unimplemented");
}
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const {
// FIXME: Zero fill for now.
for (uint64_t i = 0; i != Count; ++i)
OW->Write8(0);
return true;
}
};
class ELFSparcAsmBackend : public SparcAsmBackend {
public:
ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
SparcAsmBackend(T) { }
void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
uint64_t Value) const {
assert(0 && "applyFixup not implemented yet");
}
MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
assert(0 && "Object Writer not implemented yet");
return 0;
}
virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
return false;
}
};
} // end anonymous namespace
MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
const MCRegisterInfo &MRI,
StringRef TT,
StringRef CPU) {
return new ELFSparcAsmBackend(T, Triple(TT).getOS());
}

View File

@ -0,0 +1,36 @@
//===-- SparcFixupKinds.h - Sparc Specific Fixup Entries --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SPARC_FIXUPKINDS_H
#define LLVM_SPARC_FIXUPKINDS_H
#include "llvm/MC/MCFixup.h"
namespace llvm {
namespace Sparc {
enum Fixups {
// fixup_sparc_call30 - 30-bit PC relative relocation for call
fixup_sparc_call30 = FirstTargetFixupKind,
/// fixup_sparc_br22 - 22-bit PC relative relocation for
/// branches
fixup_sparc_br22,
/// fixup_sparc_br22 - 22-bit PC relative relocation for
/// branches on icc/xcc
fixup_sparc_br19,
// Marker
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
};
}
}
#endif

View File

@ -0,0 +1,131 @@
//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SparcMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "mccodeemitter"
#include "SparcMCTargetDesc.h"
#include "MCTargetDesc/SparcFixupKinds.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
namespace {
class SparcMCCodeEmitter : public MCCodeEmitter {
SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
MCContext &Ctx;
public:
SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
~SparcMCCodeEmitter() {}
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const;
// getBinaryCodeForInstr - TableGen'erated function for getting the
// binary encoding for an instruction.
uint64_t getBinaryCodeForInstr(const MCInst &MI,
SmallVectorImpl<MCFixup> &Fixups) const;
/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const;
unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const;
unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const;
};
} // end anonymous namespace
MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
const MCSubtargetInfo &STI,
MCContext &Ctx) {
return new SparcMCCodeEmitter(Ctx);
}
void SparcMCCodeEmitter::
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const {
unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
// Output the constant in big endian byte order.
for (unsigned i = 0; i != 4; ++i) {
OS << (char)(Bits >> 24);
Bits <<= 8;
}
++MCNumEmitted; // Keep track of the # of mi's emitted.
}
unsigned SparcMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups) const {
if (MO.isReg())
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
if (MO.isImm())
return MO.getImm();
assert(MO.isExpr());
const MCExpr *Expr = MO.getExpr();
int64_t Res;
if (Expr->EvaluateAsAbsolute(Res))
return Res;
assert(0 && "Unhandled expression!");
return 0;
}
unsigned SparcMCCodeEmitter::
getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isReg() || MO.isImm())
return getMachineOpValue(MI, MO, Fixups);
Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
(MCFixupKind)Sparc::fixup_sparc_call30));
return 0;
}
unsigned SparcMCCodeEmitter::
getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpNo);
if (MO.isReg() || MO.isImm())
return getMachineOpValue(MI, MO, Fixups);
Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
if (MI.getOpcode() == SP::BPXCC)
fixup = Sparc::fixup_sparc_br19;
Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
(MCFixupKind)fixup));
return 0;
}
#include "SparcGenMCCodeEmitter.inc"

View File

@ -136,6 +136,18 @@ extern "C" void LLVMInitializeSparcTargetMC() {
TargetRegistry::RegisterMCSubtargetInfo(TheSparcV9Target,
createSparcMCSubtargetInfo);
// Register the MC Code Emitter.
TargetRegistry::RegisterMCCodeEmitter(TheSparcTarget,
createSparcMCCodeEmitter);
TargetRegistry::RegisterMCCodeEmitter(TheSparcV9Target,
createSparcMCCodeEmitter);
//Register the asm backend.
TargetRegistry::RegisterMCAsmBackend(TheSparcTarget,
createSparcAsmBackend);
TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target,
createSparcAsmBackend);
TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
createMCAsmStreamer);
TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,

View File

@ -15,11 +15,27 @@
#define SPARCMCTARGETDESC_H
namespace llvm {
class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
class MCInstrInfo;
class MCRegisterInfo;
class MCSubtargetInfo;
class Target;
class StringRef;
extern Target TheSparcTarget;
extern Target TheSparcV9Target;
MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII,
const MCRegisterInfo &MRI,
const MCSubtargetInfo &STI,
MCContext &Ctx);
MCAsmBackend *createSparcAsmBackend(const Target &T,
const MCRegisterInfo &MRI,
StringRef TT,
StringRef CPU);
} // End llvm namespace
// Defines symbolic names for Sparc registers. This defines a mapping from

View File

@ -16,7 +16,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \
SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \
SparcGenDAGISel.inc \
SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
SparcGenCodeEmitter.inc
SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc
DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc

View File

@ -72,6 +72,11 @@ private:
unsigned getMachineOpValue(const MachineInstr &MI,
const MachineOperand &MO) const;
unsigned getCallTargetOpValue(const MachineInstr &MI,
unsigned) const;
unsigned getBranchTargetOpValue(const MachineInstr &MI,
unsigned) const;
void emitWord(unsigned Word);
unsigned getRelocation(const MachineInstr &MI,
@ -181,6 +186,18 @@ unsigned SparcCodeEmitter::getMachineOpValue(const MachineInstr &MI,
llvm_unreachable("Unable to encode MachineOperand!");
return 0;
}
unsigned SparcCodeEmitter::getCallTargetOpValue(const MachineInstr &MI,
unsigned opIdx) const {
const MachineOperand MO = MI.getOperand(opIdx);
return getMachineOpValue(MI, MO);
}
unsigned SparcCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
unsigned opIdx) const {
const MachineOperand MO = MI.getOperand(opIdx);
return getMachineOpValue(MI, MO);
}
unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI,
const MachineOperand &MO) const {

View File

@ -100,8 +100,13 @@ def MEMri : Operand<iPTR> {
def TLSSym : Operand<iPTR>;
// Branch targets have OtherVT type.
def brtarget : Operand<OtherVT>;
def calltarget : Operand<i32>;
def brtarget : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValue";
}
def calltarget : Operand<i32> {
let EncoderMethod = "getCallTargetOpValue";
}
// Operand for printing out a condition code.
let PrintMethod = "printCCOperand" in

View File

@ -0,0 +1,72 @@
! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
! CHECK: add %g0, %g0, %g0 ! encoding: [0x80,0x00,0x00,0x00]
add %g0, %g0, %g0
! CHECK: add %g1, %g2, %g3 ! encoding: [0x86,0x00,0x40,0x02]
add %g1, %g2, %g3
! CHECK: add %o0, %o1, %l0 ! encoding: [0xa0,0x02,0x00,0x09]
add %r8, %r9, %l0
! CHECK: add %o0, 10, %l0 ! encoding: [0xa0,0x02,0x20,0x0a]
add %o0, 10, %l0
! CHECK: addcc %g1, %g2, %g3 ! encoding: [0x86,0x80,0x40,0x02]
addcc %g1, %g2, %g3
! CHECK: addxcc %g1, %g2, %g3 ! encoding: [0x86,0xc0,0x40,0x02]
addxcc %g1, %g2, %g3
! CHECK: udiv %g1, %g2, %g3 ! encoding: [0x86,0x70,0x40,0x02]
udiv %g1, %g2, %g3
! CHECK: sdiv %g1, %g2, %g3 ! encoding: [0x86,0x78,0x40,0x02]
sdiv %g1, %g2, %g3
! CHECK: and %g1, %g2, %g3 ! encoding: [0x86,0x08,0x40,0x02]
and %g1, %g2, %g3
! CHECK: andn %g1, %g2, %g3 ! encoding: [0x86,0x28,0x40,0x02]
andn %g1, %g2, %g3
! CHECK: or %g1, %g2, %g3 ! encoding: [0x86,0x10,0x40,0x02]
or %g1, %g2, %g3
! CHECK: orn %g1, %g2, %g3 ! encoding: [0x86,0x30,0x40,0x02]
orn %g1, %g2, %g3
! CHECK: xor %g1, %g2, %g3 ! encoding: [0x86,0x18,0x40,0x02]
xor %g1, %g2, %g3
! CHECK: xnor %g1, %g2, %g3 ! encoding: [0x86,0x38,0x40,0x02]
xnor %g1, %g2, %g3
! CHECK: umul %g1, %g2, %g3 ! encoding: [0x86,0x50,0x40,0x02]
umul %g1, %g2, %g3
! CHECK: smul %g1, %g2, %g3 ! encoding: [0x86,0x58,0x40,0x02]
smul %g1, %g2, %g3
! CHECK: nop ! encoding: [0x01,0x00,0x00,0x00]
nop
! CHECK: sethi 10, %l0 ! encoding: [0x21,0x00,0x00,0x0a]
sethi 10, %l0
! CHECK: sll %g1, %g2, %g3 ! encoding: [0x87,0x28,0x40,0x02]
sll %g1, %g2, %g3
! CHECK: sll %g1, 31, %g3 ! encoding: [0x87,0x28,0x60,0x1f]
sll %g1, 31, %g3
! CHECK: srl %g1, %g2, %g3 ! encoding: [0x87,0x30,0x40,0x02]
srl %g1, %g2, %g3
! CHECK: srl %g1, 31, %g3 ! encoding: [0x87,0x30,0x60,0x1f]
srl %g1, 31, %g3
! CHECK: sra %g1, %g2, %g3 ! encoding: [0x87,0x38,0x40,0x02]
sra %g1, %g2, %g3
! CHECK: sra %g1, 31, %g3 ! encoding: [0x87,0x38,0x60,0x1f]
sra %g1, 31, %g3
! CHECK: sub %g1, %g2, %g3 ! encoding: [0x86,0x20,0x40,0x02]
sub %g1, %g2, %g3
! CHECK: subcc %g1, %g2, %g3 ! encoding: [0x86,0xa0,0x40,0x02]
subcc %g1, %g2, %g3
! CHECK: subxcc %g1, %g2, %g3 ! encoding: [0x86,0xe0,0x40,0x02]
subxcc %g1, %g2, %g3