From 5d02c84191f0aea5b35b810a30edce97dd24bffc Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Sun, 5 Jan 2014 02:13:48 +0000 Subject: [PATCH] [Sparc] Add initial implementation of MC Code emitter for sparc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198533 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/CMakeLists.txt | 1 + lib/Target/Sparc/MCTargetDesc/CMakeLists.txt | 4 +- .../Sparc/MCTargetDesc/SparcAsmBackend.cpp | 101 ++++++++++++++ .../Sparc/MCTargetDesc/SparcFixupKinds.h | 36 +++++ .../Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp | 131 ++++++++++++++++++ .../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 12 ++ .../Sparc/MCTargetDesc/SparcMCTargetDesc.h | 16 +++ lib/Target/Sparc/Makefile | 2 +- lib/Target/Sparc/SparcCodeEmitter.cpp | 17 +++ lib/Target/Sparc/SparcInstrInfo.td | 9 +- test/MC/Sparc/sparc-alu-instructions.s | 72 ++++++++++ 11 files changed, 397 insertions(+), 4 deletions(-) create mode 100644 lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp create mode 100644 lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h create mode 100644 lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp create mode 100644 test/MC/Sparc/sparc-alu-instructions.s diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index 1795beee3b2..9fad0e85619 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -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) diff --git a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt index 3a40fcaba47..2619f9db26d 100644 --- a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt @@ -1,6 +1,8 @@ add_llvm_library(LLVMSparcDesc - SparcMCTargetDesc.cpp + SparcAsmBackend.cpp SparcMCAsmInfo.cpp + SparcMCCodeEmitter.cpp + SparcMCTargetDesc.cpp SparcMCExpr.cpp SparcTargetStreamer.cpp ) diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp new file mode 100644 index 00000000000..e86b3c89d23 --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -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()); +} diff --git a/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h new file mode 100644 index 00000000000..1b56f1266b8 --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -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 diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp new file mode 100644 index 00000000000..641aed429bb --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -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 &Fixups) const; + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &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 &Fixups) const; + + unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const; + unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &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 &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 &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 &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 &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" diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp index a98e240fe06..0322ddcf4d0 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -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, diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h index cba775adb1a..5b3f7448ec9 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h @@ -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 diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index 6b563e907e7..94a8dd01d47 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -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 diff --git a/lib/Target/Sparc/SparcCodeEmitter.cpp b/lib/Target/Sparc/SparcCodeEmitter.cpp index 9bfe31fe496..f4a2c739494 100644 --- a/lib/Target/Sparc/SparcCodeEmitter.cpp +++ b/lib/Target/Sparc/SparcCodeEmitter.cpp @@ -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 { diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index d3c8e4ad788..43d9bc95314 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -100,8 +100,13 @@ def MEMri : Operand { def TLSSym : Operand; // Branch targets have OtherVT type. -def brtarget : Operand; -def calltarget : Operand; +def brtarget : Operand { + let EncoderMethod = "getBranchTargetOpValue"; +} + +def calltarget : Operand { + let EncoderMethod = "getCallTargetOpValue"; +} // Operand for printing out a condition code. let PrintMethod = "printCCOperand" in diff --git a/test/MC/Sparc/sparc-alu-instructions.s b/test/MC/Sparc/sparc-alu-instructions.s new file mode 100644 index 00000000000..393b5df5f9d --- /dev/null +++ b/test/MC/Sparc/sparc-alu-instructions.s @@ -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 + -- 2.34.1