diff options
Diffstat (limited to 'lib/Target')
28 files changed, 2119 insertions, 568 deletions
diff --git a/lib/Target/MBlaze/CMakeLists.txt b/lib/Target/MBlaze/CMakeLists.txt index 7b470ee..eb5906e 100644 --- a/lib/Target/MBlaze/CMakeLists.txt +++ b/lib/Target/MBlaze/CMakeLists.txt @@ -5,6 +5,7 @@ tablegen(MBlazeGenRegisterNames.inc -gen-register-enums) tablegen(MBlazeGenRegisterInfo.inc -gen-register-desc) tablegen(MBlazeGenInstrNames.inc -gen-instr-enums) tablegen(MBlazeGenInstrInfo.inc -gen-instr-desc) +tablegen(MBlazeGenCodeEmitter.inc -gen-emitter) tablegen(MBlazeGenAsmWriter.inc -gen-asm-writer) tablegen(MBlazeGenDAGISel.inc -gen-dag-isel) tablegen(MBlazeGenCallingConv.inc -gen-callingconv) @@ -23,4 +24,9 @@ add_llvm_target(MBlazeCodeGen MBlazeTargetObjectFile.cpp MBlazeIntrinsicInfo.cpp MBlazeSelectionDAGInfo.cpp + MBlazeAsmPrinter.cpp + MBlazeAsmBackend.cpp + MBlazeMCInstLower.cpp + MBlazeELFWriterInfo.cpp + MBlazeMCCodeEmitter.cpp ) diff --git a/lib/Target/MBlaze/InstPrinter/CMakeLists.txt b/lib/Target/MBlaze/InstPrinter/CMakeLists.txt new file mode 100644 index 0000000..242a573 --- /dev/null +++ b/lib/Target/MBlaze/InstPrinter/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMMBlazeAsmPrinter + MBlazeInstPrinter.cpp + ) + +add_dependencies(LLVMMBlazeAsmPrinter MBlazeCodeGenTable_gen) diff --git a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp new file mode 100644 index 0000000..4c59b54 --- /dev/null +++ b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp @@ -0,0 +1,140 @@ +//===-- MBlazeInstPrinter.cpp - Convert MBlaze MCInst to assembly syntax --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an MBlaze MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "MBlaze.h" +#include "MBlazeInstPrinter.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + + +// Include the auto-generated portion of the assembly writer. +#include "MBlazeGenAsmWriter.inc" + +void MBlazeInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { + printInstruction(MI, O); +} + +void MBlazeInstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isImm()) + O << Op.getImm(); + else { + assert(Op.isExpr() && "unknown pcrel immediate operand"); + O << *Op.getExpr(); + } +} + +void MBlazeInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, const char *Modifier) { + assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + O << getRegisterName(Op.getReg()); + } else if (Op.isImm()) { + O << (int32_t)Op.getImm(); + } else { + assert(Op.isExpr() && "unknown operand kind in printOperand"); + O << *Op.getExpr(); + } +} + +void MBlazeInstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, + const char *Modifier) { + const MCOperand &Base = MI->getOperand(OpNo); + const MCOperand &Disp = MI->getOperand(OpNo+1); + + // Print displacement first + + // If the global address expression is a part of displacement field with a + // register base, we should not emit any prefix symbol here, e.g. + // mov.w &foo, r1 + // vs + // mov.w glb(r1), r2 + // Otherwise (!) msp430-as will silently miscompile the output :( + if (!Base.getReg()) + O << '&'; + + if (Disp.isExpr()) + O << *Disp.getExpr(); + else { + assert(Disp.isImm() && "Expected immediate in displacement field"); + O << Disp.getImm(); + } + + // Print register base field + if (Base.getReg()) + O << getRegisterName(Base.getReg()); +} + +void MBlazeInstPrinter::printFSLImm(const MCInst *MI, int OpNo, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNo); + if (MO.isImm()) + O << "rfsl" << MO.getImm(); + else + printOperand(MI, OpNo, O, NULL); +} + +void MBlazeInstPrinter::printUnsignedImm(const MCInst *MI, int OpNo, + raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNo); + if (MO.isImm()) + O << MO.getImm(); + else + printOperand(MI, OpNo, O, NULL); +} + +void MBlazeInstPrinter::printMemOperand(const MCInst *MI, int OpNo, + raw_ostream &O, const char *Modifier ) { + printOperand(MI, OpNo+1, O, NULL); + O << ", "; + printOperand(MI, OpNo, O, NULL); +} + +/* +void MBlazeInstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + unsigned CC = MI->getOperand(OpNo).getImm(); + + switch (CC) { + default: + llvm_unreachable("Unsupported CC code"); + break; + case MBlazeCC::COND_E: + O << "eq"; + break; + case MBlazeCC::COND_NE: + O << "ne"; + break; + case MBlazeCC::COND_HS: + O << "hs"; + break; + case MBlazeCC::COND_LO: + O << "lo"; + break; + case MBlazeCC::COND_GE: + O << "ge"; + break; + case MBlazeCC::COND_L: + O << 'l'; + break; + } +} +*/ diff --git a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h new file mode 100644 index 0000000..2b80689 --- /dev/null +++ b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h @@ -0,0 +1,46 @@ +//===-- MBLazeInstPrinter.h - Convert MBlaze MCInst to assembly syntax ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints a MBlaze MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZEINSTPRINTER_H +#define MBLAZEINSTPRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { + class MCOperand; + + class MBlazeInstPrinter : public MCInstPrinter { + public: + MBlazeInstPrinter(const MCAsmInfo &MAI) : MCInstPrinter(MAI) { + } + + virtual void printInst(const MCInst *MI, raw_ostream &O); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + static const char *getInstructionName(unsigned Opcode); + + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = 0); + void printPCRelImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printSrcMemOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = 0); + void printFSLImm(const MCInst *MI, int OpNo, raw_ostream &O); + void printUnsignedImm(const MCInst *MI, int OpNo, raw_ostream &O); + void printMemOperand(const MCInst *MI, int OpNo,raw_ostream &O, + const char *Modifier = 0); + }; +} + +#endif diff --git a/lib/Target/MBlaze/InstPrinter/Makefile b/lib/Target/MBlaze/InstPrinter/Makefile new file mode 100644 index 0000000..9fb6e86 --- /dev/null +++ b/lib/Target/MBlaze/InstPrinter/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/MBlaze/AsmPrinter/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMMBlazeAsmPrinter + +# Hack: we need to include 'main' MBlaze target directory to grab +# private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/MBlaze/MBlaze.h b/lib/Target/MBlaze/MBlaze.h index f9d828b..00c73f0 100644 --- a/lib/Target/MBlaze/MBlaze.h +++ b/lib/Target/MBlaze/MBlaze.h @@ -21,8 +21,16 @@ namespace llvm { class MBlazeTargetMachine; class FunctionPass; class MachineCodeEmitter; + class MCCodeEmitter; + class TargetAsmBackend; class formatted_raw_ostream; + MCCodeEmitter *createMBlazeMCCodeEmitter(const Target &, + TargetMachine &TM, + MCContext &Ctx); + + TargetAsmBackend *createMBlazeAsmBackend(const Target &, const std::string &); + FunctionPass *createMBlazeISelDag(MBlazeTargetMachine &TM); FunctionPass *createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &TM); diff --git a/lib/Target/MBlaze/MBlaze.td b/lib/Target/MBlaze/MBlaze.td index 3815b6d..1fa1e4d 100644 --- a/lib/Target/MBlaze/MBlaze.td +++ b/lib/Target/MBlaze/MBlaze.td @@ -32,35 +32,35 @@ def MBlazeInstrInfo : InstrInfo; //===----------------------------------------------------------------------===// def FeaturePipe3 : SubtargetFeature<"pipe3", "HasPipe3", "true", - "Implements 3-stage pipeline.">; + "Implements 3-stage pipeline">; def FeatureBarrel : SubtargetFeature<"barrel", "HasBarrel", "true", - "Implements barrel shifter.">; + "Implements barrel shifter">; def FeatureDiv : SubtargetFeature<"div", "HasDiv", "true", - "Implements hardware divider.">; + "Implements hardware divider">; def FeatureMul : SubtargetFeature<"mul", "HasMul", "true", - "Implements hardware multiplier.">; + "Implements hardware multiplier">; def FeatureFSL : SubtargetFeature<"fsl", "HasFSL", "true", - "Implements FSL instructions.">; + "Implements FSL instructions">; def FeatureEFSL : SubtargetFeature<"efsl", "HasEFSL", "true", - "Implements extended FSL instructions.">; + "Implements extended FSL instructions">; def FeatureMSRSet : SubtargetFeature<"msrset", "HasMSRSet", "true", - "Implements MSR register set and clear.">; + "Implements MSR register set and clear">; def FeatureException : SubtargetFeature<"exception", "HasException", "true", - "Implements hardware exception support.">; + "Implements hardware exception support">; def FeaturePatCmp : SubtargetFeature<"patcmp", "HasPatCmp", "true", - "Implements pattern compare instruction.">; + "Implements pattern compare instruction">; def FeatureFPU : SubtargetFeature<"fpu", "HasFPU", "true", - "Implements floating point unit.">; + "Implements floating point unit">; def FeatureESR : SubtargetFeature<"esr", "HasESR", "true", "Implements ESR and EAR registers">; def FeaturePVR : SubtargetFeature<"pvr", "HasPVR", "true", - "Implements processor version register.">; + "Implements processor version register">; def FeatureMul64 : SubtargetFeature<"mul64", "HasMul64", "true", "Implements multiplier with 64-bit result">; def FeatureSqrt : SubtargetFeature<"sqrt", "HasSqrt", "true", - "Implements sqrt and floating point convert.">; + "Implements sqrt and floating point convert">; def FeatureMMU : SubtargetFeature<"mmu", "HasMMU", "true", - "Implements memory management unit.">; + "Implements memory management unit">; //===----------------------------------------------------------------------===// // MBlaze processors supported. @@ -69,13 +69,26 @@ def FeatureMMU : SubtargetFeature<"mmu", "HasMMU", "true", class Proc<string Name, list<SubtargetFeature> Features> : Processor<Name, MBlazeGenericItineraries, Features>; - def : Proc<"v400", []>; def : Proc<"v500", []>; def : Proc<"v600", []>; def : Proc<"v700", []>; def : Proc<"v710", []>; +//===----------------------------------------------------------------------===// +// Instruction Descriptions +//===----------------------------------------------------------------------===// + +def MBlazeAsmWriter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; + bit isMCAsmWriter = 1; +} + +//===----------------------------------------------------------------------===// +// Target Declaration +//===----------------------------------------------------------------------===// + def MBlaze : Target { let InstructionSet = MBlazeInstrInfo; + let AssemblyWriters = [MBlazeAsmWriter]; } diff --git a/lib/Target/MBlaze/MBlazeAsmBackend.cpp b/lib/Target/MBlaze/MBlazeAsmBackend.cpp new file mode 100644 index 0000000..7e11f73 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeAsmBackend.cpp @@ -0,0 +1,152 @@ +//===-- MBlazeAsmBackend.cpp - MBlaze 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/Target/TargetAsmBackend.h" +#include "MBlaze.h" +#include "MBlazeFixupKinds.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/ELFObjectWriter.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectFormat.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MachObjectWriter.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmBackend.h" +using namespace llvm; + +static unsigned getFixupKindSize(unsigned Kind) { + switch (Kind) { + default: assert(0 && "invalid fixup kind!"); + case FK_Data_1: return 1; + case MBlaze::reloc_pcrel_2byte: + case FK_Data_2: return 2; + case MBlaze::reloc_pcrel_4byte: + case FK_Data_4: return 4; + case FK_Data_8: return 8; + } +} + + +namespace { +class MBlazeAsmBackend : public TargetAsmBackend { +public: + MBlazeAsmBackend(const Target &T) + : TargetAsmBackend(T) { + } + + bool MayNeedRelaxation(const MCInst &Inst) const; + + void RelaxInstruction(const MCInst &Inst, MCInst &Res) const; + + bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const; + + unsigned getPointerSize() const { + return 4; + } +}; + +bool MBlazeAsmBackend::MayNeedRelaxation(const MCInst &Inst) const { + return false; +} + +void MBlazeAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { + assert(0 && "MBlazeAsmBackend::RelaxInstruction() unimplemented"); + return; +} + +bool MBlazeAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { + if ((Count % 4) != 0) + return false; + + for (uint64_t i = 0; i < Count; i += 4 ) + OW->Write32( 0x00000000 ); + + return true; +} +} // end anonymous namespace + +namespace { +// FIXME: This should be in a separate file. +// ELF is an ELF of course... +class ELFMBlazeAsmBackend : public MBlazeAsmBackend { + MCELFObjectFormat Format; + +public: + Triple::OSType OSType; + ELFMBlazeAsmBackend(const Target &T, Triple::OSType _OSType) + : MBlazeAsmBackend(T), OSType(_OSType) { + HasScatteredSymbols = true; + } + + virtual const MCObjectFormat &getObjectFormat() const { + return Format; + } + + + void ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF, + uint64_t Value) const; + + bool isVirtualSection(const MCSection &Section) const { + const MCSectionELF &SE = static_cast<const MCSectionELF&>(Section); + return SE.getType() == MCSectionELF::SHT_NOBITS; + } + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + return new ELFObjectWriter(OS, /*Is64Bit=*/false, + OSType, + /*IsLittleEndian=*/false, + /*HasRelocationAddend=*/true); + } +}; + +void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF, + uint64_t Value) const { + unsigned Size = getFixupKindSize(Fixup.getKind()); + + assert(Fixup.getOffset() + Size <= DF.getContents().size() && + "Invalid fixup offset!"); + + char *data = DF.getContents().data() + Fixup.getOffset(); + switch (Size) { + default: llvm_unreachable( "Cannot fixup unknown value." ); + case 1: llvm_unreachable( "Cannot fixup 1 byte value." ); + case 8: llvm_unreachable( "Cannot fixup 8 byte value." ); + + case 4: + *(data+7) = uint8_t(Value); + *(data+6) = uint8_t(Value >> 8); + *(data+3) = uint8_t(Value >> 16); + *(data+2) = uint8_t(Value >> 24); + break; + + case 2: + *(data+3) = uint8_t(Value >> 0); + *(data+2) = uint8_t(Value >> 8); + } +} +} // end anonymous namespace + +TargetAsmBackend *llvm::createMBlazeAsmBackend(const Target &T, + const std::string &TT) { + switch (Triple(TT).getOS()) { + case Triple::Darwin: + assert(0 && "Mac not supported on MBlaze"); + case Triple::MinGW32: + case Triple::Cygwin: + case Triple::Win32: + assert(0 && "Windows not supported on MBlaze"); + default: + return new ELFMBlazeAsmBackend(T, Triple(TT).getOS()); + } +} diff --git a/lib/Target/MBlaze/MBlazeAsmPrinter.cpp b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp new file mode 100644 index 0000000..c1ae450 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp @@ -0,0 +1,314 @@ +//===-- MBlazeAsmPrinter.cpp - MBlaze LLVM assembly writer ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to GAS-format MBlaze assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mblaze-asm-printer" + +#include "MBlaze.h" +#include "MBlazeSubtarget.h" +#include "MBlazeInstrInfo.h" +#include "MBlazeTargetMachine.h" +#include "MBlazeMachineFunction.h" +#include "MBlazeMCInstLower.h" +#include "InstPrinter/MBlazeInstPrinter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <cctype> + +using namespace llvm; + +namespace { + class MBlazeAsmPrinter : public AsmPrinter { + const MBlazeSubtarget *Subtarget; + public: + explicit MBlazeAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) { + Subtarget = &TM.getSubtarget<MBlazeSubtarget>(); + } + + virtual const char *getPassName() const { + return "MBlaze Assembly Printer"; + } + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); + void printFSLImm(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier = 0); + void printSavedRegsBitmask(raw_ostream &OS); + + void emitFrameDirective(); + + void EmitInstruction(const MachineInstr *MI); + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd(); + + virtual void EmitFunctionEntryLabel(); + }; +} // end of anonymous namespace + +// #include "MBlazeGenAsmWriter.inc" + +//===----------------------------------------------------------------------===// +// +// MBlaze Asm Directives +// +// -- Frame directive "frame Stackpointer, Stacksize, RARegister" +// Describe the stack frame. +// +// -- Mask directives "mask bitmask, offset" +// Tells the assembler which registers are saved and where. +// bitmask - contain a little endian bitset indicating which registers are +// saved on function prologue (e.g. with a 0x80000000 mask, the +// assembler knows the register 31 (RA) is saved at prologue. +// offset - the position before stack pointer subtraction indicating where +// the first saved register on prologue is located. (e.g. with a +// +// Consider the following function prologue: +// +// .frame R19,48,R15 +// .mask 0xc0000000,-8 +// addiu R1, R1, -48 +// sw R15, 40(R1) +// sw R19, 36(R1) +// +// With a 0xc0000000 mask, the assembler knows the register 15 (R15) and +// 19 (R19) are saved at prologue. As the save order on prologue is from +// left to right, R15 is saved first. A -8 offset means that after the +// stack pointer subtration, the first register in the mask (R15) will be +// saved at address 48-8=40. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) { + MBlazeMCInstLower MCInstLowering(OutContext, *Mang, *this); + + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); + OutStreamer.EmitInstruction(TmpInst); +} + +//===----------------------------------------------------------------------===// +// Mask directives +//===----------------------------------------------------------------------===// + +// Print a 32 bit hex number with all numbers. +static void printHex32(unsigned int Value, raw_ostream &O) { + O << "0x"; + for (int i = 7; i >= 0; i--) + O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); +} + + +// Create a bitmask with all callee saved registers for CPU or Floating Point +// registers. For CPU registers consider RA, GP and FP for saving if necessary. +void MBlazeAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + const MBlazeFunctionInfo *MBlazeFI = MF->getInfo<MBlazeFunctionInfo>(); + + // CPU Saved Registers Bitmasks + unsigned int CPUBitmask = 0; + + // Set the CPU Bitmasks + const MachineFrameInfo *MFI = MF->getFrameInfo(); + const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + unsigned RegNum = MBlazeRegisterInfo::getRegisterNumbering(Reg); + if (MBlaze::CPURegsRegisterClass->contains(Reg)) + CPUBitmask |= (1 << RegNum); + } + + // Return Address and Frame registers must also be set in CPUBitmask. + if (RI.hasFP(*MF)) + CPUBitmask |= (1 << MBlazeRegisterInfo:: + getRegisterNumbering(RI.getFrameRegister(*MF))); + + if (MFI->adjustsStack()) + CPUBitmask |= (1 << MBlazeRegisterInfo:: + getRegisterNumbering(RI.getRARegister())); + + // Print CPUBitmask + O << "\t.mask \t"; printHex32(CPUBitmask, O); + O << ',' << MBlazeFI->getCPUTopSavedRegOff() << '\n'; +} + +//===----------------------------------------------------------------------===// +// Frame and Set directives +//===----------------------------------------------------------------------===// + +/// Frame Directive +void MBlazeAsmPrinter::emitFrameDirective() { + // const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + + // unsigned stackReg = RI.getFrameRegister(*MF); + // unsigned returnReg = RI.getRARegister(); + // unsigned stackSize = MF->getFrameInfo()->getStackSize(); + + + /* + OutStreamer.EmitRawText("\t.frame\t" + + Twine(MBlazeInstPrinter::getRegisterName(stackReg)) + + "," + Twine(stackSize) + "," + + Twine(MBlazeInstPrinter::getRegisterName(returnReg))); + */ +} + +void MBlazeAsmPrinter::EmitFunctionEntryLabel() { + // OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); + OutStreamer.EmitLabel(CurrentFnSym); +} + +/// EmitFunctionBodyStart - Targets can override this to emit stuff before +/// the first basic block in the function. +void MBlazeAsmPrinter::EmitFunctionBodyStart() { + // emitFrameDirective(); + + // SmallString<128> Str; + // raw_svector_ostream OS(Str); + // printSavedRegsBitmask(OS); + // OutStreamer.EmitRawText(OS.str()); +} + +/// EmitFunctionBodyEnd - Targets can override this to emit stuff after +/// the last basic block in the function. +void MBlazeAsmPrinter::EmitFunctionBodyEnd() { + // OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); +} + +// Print out an operand for an inline asm expression. +bool MBlazeAsmPrinter:: +PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant,const char *ExtraCode, raw_ostream &O) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + + printOperand(MI, OpNo, O); + return false; +} + +void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << MBlazeInstPrinter::getRegisterName(MO.getReg()); + break; + + case MachineOperand::MO_Immediate: + O << (int)MO.getImm(); + break; + + case MachineOperand::MO_FPImmediate: { + const ConstantFP *fp = MO.getFPImm(); + printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue(), O); + O << ";\t# immediate = " << *fp; + break; + } + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + break; + + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + break; + + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" + << getFunctionNumber() << "_" << MO.getIndex(); + if (MO.getOffset()) + O << "+" << MO.getOffset(); + break; + + default: + llvm_unreachable("<unknown operand type>"); + } +} + +void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.isImm()) + O << (unsigned int)MO.getImm(); + else + printOperand(MI, opNum, O); +} + +void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.isImm()) + O << "rfsl" << (unsigned int)MO.getImm(); + else + printOperand(MI, opNum, O); +} + +void MBlazeAsmPrinter:: +printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier) { + printOperand(MI, opNum+1, O); + O << ", "; + printOperand(MI, opNum, O); +} + +static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI) { + if (SyntaxVariant == 0) + return new MBlazeInstPrinter(MAI); + return 0; +} + +// Force static initialization. +extern "C" void LLVMInitializeMBlazeAsmPrinter() { + RegisterAsmPrinter<MBlazeAsmPrinter> X(TheMBlazeTarget); + TargetRegistry::RegisterMCInstPrinter(TheMBlazeTarget, + createMBlazeMCInstPrinter); + +} diff --git a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp index b551b79..be9de6d 100644 --- a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp +++ b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp @@ -19,6 +19,10 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -51,6 +55,91 @@ namespace { char Filler::ID = 0; } // end of anonymous namespace +static bool hasImmInstruction( MachineBasicBlock::iterator &candidate ) { + // Any instruction with an immediate mode operand greater than + // 16-bits requires an implicit IMM instruction. + unsigned numOper = candidate->getNumOperands(); + for( unsigned op = 0; op < numOper; ++op ) { + if( candidate->getOperand(op).isImm() && + (candidate->getOperand(op).getImm() & 0xFFFFFFFFFFFF0000LL) != 0 ) + return true; + + // FIXME: we could probably check to see if the FP value happens + // to not need an IMM instruction. For now we just always + // assume that FP values always do. + if( candidate->getOperand(op).isFPImm() ) + return true; + } + + return false; +} + +static bool delayHasHazard( MachineBasicBlock::iterator &candidate, + MachineBasicBlock::iterator &slot ) { + + // Loop over all of the operands in the branch instruction + // and make sure that none of them are defined by the + // candidate instruction. + unsigned numOper = slot->getNumOperands(); + for( unsigned op = 0; op < numOper; ++op ) { + if( !slot->getOperand(op).isReg() || + !slot->getOperand(op).isUse() || + slot->getOperand(op).isImplicit() ) + continue; + + unsigned cnumOper = candidate->getNumOperands(); + for( unsigned cop = 0; cop < cnumOper; ++cop ) { + if( candidate->getOperand(cop).isReg() && + candidate->getOperand(cop).isDef() && + candidate->getOperand(cop).getReg() == + slot->getOperand(op).getReg() ) + return true; + } + } + + // There are no hazards between the two instructions + return false; +} + +static bool usedBeforeDelaySlot( MachineBasicBlock::iterator &candidate, + MachineBasicBlock::iterator &slot ) { + MachineBasicBlock::iterator I = candidate; + for (++I; I != slot; ++I) { + unsigned numOper = I->getNumOperands(); + for( unsigned op = 0; op < numOper; ++op ) { + if( I->getOperand(op).isReg() && + I->getOperand(op).isUse() ) { + unsigned reg = I->getOperand(op).getReg(); + unsigned cops = candidate->getNumOperands(); + for( unsigned cop = 0; cop < cops; ++cop ) { + if( candidate->getOperand(cop).isReg() && + candidate->getOperand(cop).isDef() && + candidate->getOperand(cop).getReg() == reg ) + return true; + } + } + } + } + + return false; +} + +static MachineBasicBlock::iterator +findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator &slot) { + MachineBasicBlock::iterator found = MBB.end(); + for (MachineBasicBlock::iterator I = MBB.begin(); I != slot; ++I) { + TargetInstrDesc desc = I->getDesc(); + if( desc.hasDelaySlot() || desc.isBranch() || + desc.mayLoad() || desc. mayStore() || + hasImmInstruction(I) || delayHasHazard(I,slot) || + usedBeforeDelaySlot(I,slot)) continue; + + found = I; + } + + return found; +} + /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. /// Currently, we fill delay slots with NOPs. We assume there is only one /// delay slot per delayed instruction. @@ -59,10 +148,16 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) if (I->getDesc().hasDelaySlot()) { MachineBasicBlock::iterator J = I; + MachineBasicBlock::iterator D = findDelayInstr(MBB,I); + ++J; - BuildMI(MBB, J, I->getDebugLoc(), TII->get(MBlaze::NOP)); ++FilledSlots; Changed = true; + + if( D == MBB.end() ) + BuildMI(MBB, J, I->getDebugLoc(), TII->get(MBlaze::NOP)); + else + MBB.splice( J, &MBB, D ); } return Changed; } diff --git a/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp b/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp new file mode 100644 index 0000000..378b5d4 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp @@ -0,0 +1,110 @@ +//===-- MBlazeELFWriterInfo.cpp - ELF Writer Info for the MBlaze backend --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF writer information for the MBlaze backend. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeELFWriterInfo.h" +#include "MBlazeRelocations.h" +#include "llvm/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Implementation of the MBlazeELFWriterInfo class +//===----------------------------------------------------------------------===// + +MBlazeELFWriterInfo::MBlazeELFWriterInfo(TargetMachine &TM) + : TargetELFWriterInfo(TM.getTargetData()->getPointerSizeInBits() == 64, + TM.getTargetData()->isLittleEndian()) { +} + +MBlazeELFWriterInfo::~MBlazeELFWriterInfo() {} + +unsigned MBlazeELFWriterInfo::getRelocationType(unsigned MachineRelTy) const { + switch(MachineRelTy) { + case MBlaze::reloc_pcrel_word: + return R_MICROBLAZE_64_PCREL; + case MBlaze::reloc_absolute_word: + return R_MICROBLAZE_NONE; + default: + llvm_unreachable("unknown mblaze machine relocation type"); + } + return 0; +} + +long int MBlazeELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier) const { + switch(RelTy) { + case R_MICROBLAZE_32_PCREL: + return Modifier - 4; + case R_MICROBLAZE_32: + return Modifier; + default: + llvm_unreachable("unknown mblaze relocation type"); + } + return 0; +} + +unsigned MBlazeELFWriterInfo::getRelocationTySize(unsigned RelTy) const { + // FIXME: Most of these sizes are guesses based on the name + switch(RelTy) { + case R_MICROBLAZE_32: + case R_MICROBLAZE_32_PCREL: + case R_MICROBLAZE_32_PCREL_LO: + case R_MICROBLAZE_32_LO: + case R_MICROBLAZE_SRO32: + case R_MICROBLAZE_SRW32: + case R_MICROBLAZE_32_SYM_OP_SYM: + case R_MICROBLAZE_GOTOFF_32: + return 32; + + case R_MICROBLAZE_64_PCREL: + case R_MICROBLAZE_64: + case R_MICROBLAZE_GOTPC_64: + case R_MICROBLAZE_GOT_64: + case R_MICROBLAZE_PLT_64: + case R_MICROBLAZE_GOTOFF_64: + return 64; + } + + return 0; +} + +bool MBlazeELFWriterInfo::isPCRelativeRel(unsigned RelTy) const { + // FIXME: Most of these are guesses based on the name + switch(RelTy) { + case R_MICROBLAZE_32_PCREL: + case R_MICROBLAZE_64_PCREL: + case R_MICROBLAZE_32_PCREL_LO: + case R_MICROBLAZE_GOTPC_64: + return true; + } + + return false; +} + +unsigned MBlazeELFWriterInfo::getAbsoluteLabelMachineRelTy() const { + return MBlaze::reloc_absolute_word; +} + +long int MBlazeELFWriterInfo::computeRelocation(unsigned SymOffset, + unsigned RelOffset, + unsigned RelTy) const { + if (RelTy == R_MICROBLAZE_32_PCREL || R_MICROBLAZE_64_PCREL) + return SymOffset - (RelOffset + 4); + else + assert("computeRelocation unknown for this relocation type"); + + return 0; +} diff --git a/lib/Target/MBlaze/MBlazeELFWriterInfo.h b/lib/Target/MBlaze/MBlazeELFWriterInfo.h new file mode 100644 index 0000000..2e6a9f3 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeELFWriterInfo.h @@ -0,0 +1,85 @@ +//===-- MBlazeELFWriterInfo.h - ELF Writer Info for MBlaze ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF writer information for the MBlaze backend. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZE_ELF_WRITER_INFO_H +#define MBLAZE_ELF_WRITER_INFO_H + +#include "llvm/Target/TargetELFWriterInfo.h" + +namespace llvm { + + class MBlazeELFWriterInfo : public TargetELFWriterInfo { + + // ELF Relocation types for MBlaze + enum MBlazeRelocationType { + R_MICROBLAZE_NONE = 0, + R_MICROBLAZE_32 = 1, + R_MICROBLAZE_32_PCREL = 2, + R_MICROBLAZE_64_PCREL = 3, + R_MICROBLAZE_32_PCREL_LO = 4, + R_MICROBLAZE_64 = 5, + R_MICROBLAZE_32_LO = 6, + R_MICROBLAZE_SRO32 = 7, + R_MICROBLAZE_SRW32 = 8, + R_MICROBLAZE_64_NONE = 9, + R_MICROBLAZE_32_SYM_OP_SYM = 10, + R_MICROBLAZE_GNU_VTINHERIT = 11, + R_MICROBLAZE_GNU_VTENTRY = 12, + R_MICROBLAZE_GOTPC_64 = 13, + R_MICROBLAZE_GOT_64 = 14, + R_MICROBLAZE_PLT_64 = 15, + R_MICROBLAZE_REL = 16, + R_MICROBLAZE_JUMP_SLOT = 17, + R_MICROBLAZE_GLOB_DAT = 18, + R_MICROBLAZE_GOTOFF_64 = 19, + R_MICROBLAZE_GOTOFF_32 = 20, + R_MICROBLAZE_COPY = 21 + }; + + public: + MBlazeELFWriterInfo(TargetMachine &TM); + virtual ~MBlazeELFWriterInfo(); + + /// getRelocationType - Returns the target specific ELF Relocation type. + /// 'MachineRelTy' contains the object code independent relocation type + virtual unsigned getRelocationType(unsigned MachineRelTy) const; + + /// hasRelocationAddend - True if the target uses an addend in the + /// ELF relocation entry. + virtual bool hasRelocationAddend() const { return false; } + + /// getDefaultAddendForRelTy - Gets the default addend value for a + /// relocation entry based on the target ELF relocation type. + virtual long int getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier = 0) const; + + /// getRelTySize - Returns the size of relocatable field in bits + virtual unsigned getRelocationTySize(unsigned RelTy) const; + + /// isPCRelativeRel - True if the relocation type is pc relative + virtual bool isPCRelativeRel(unsigned RelTy) const; + + /// getJumpTableRelocationTy - Returns the machine relocation type used + /// to reference a jumptable. + virtual unsigned getAbsoluteLabelMachineRelTy() const; + + /// computeRelocation - Some relocatable fields could be relocated + /// directly, avoiding the relocation symbol emission, compute the + /// final relocation value for this symbol. + virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset, + unsigned RelTy) const; + }; + +} // end llvm namespace + +#endif // MBLAZE_ELF_WRITER_INFO_H diff --git a/lib/Target/MBlaze/MBlazeFixupKinds.h b/lib/Target/MBlaze/MBlazeFixupKinds.h new file mode 100644 index 0000000..72466ca --- /dev/null +++ b/lib/Target/MBlaze/MBlazeFixupKinds.h @@ -0,0 +1,24 @@ +//===-- MBlaze/MBlazeFixupKinds.h - MBlaze 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_MBLAZE_MBLAZEFIXUPKINDS_H +#define LLVM_MBLAZE_MBLAZEFIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +namespace llvm { +namespace MBlaze { +enum Fixups { + reloc_pcrel_4byte = FirstTargetFixupKind, // 32-bit pcrel, e.g. a brlid + reloc_pcrel_2byte // 16-bit pcrel, e.g. beqid +}; +} +} + +#endif diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index aca5f5d..8229609 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -421,13 +421,11 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { SDValue HiPart; // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); - bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; - unsigned char OpFlag = IsPIC ? MBlazeII::MO_GOT : MBlazeII::MO_ABS_HILO; EVT PtrVT = Op.getValueType(); JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); - SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OpFlag); + SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, 0 ); return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, JTI); //return JTI; } @@ -440,7 +438,7 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), - N->getOffset(), MBlazeII::MO_ABS_HILO); + N->getOffset(), 0 ); return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, CP); } @@ -618,13 +616,12 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. - unsigned char OpFlag = MBlazeII::MO_NO_FLAG; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, - getPointerTy(), 0, OpFlag); + getPointerTy(), 0, 0 ); else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) Callee = DAG.getTargetExternalSymbol(S->getSymbol(), - getPointerTy(), OpFlag); + getPointerTy(), 0 ); // MBlazeJmpLink = #chain, #target_address, #opt_in_flags... // = Chain, Callee, Reg#1, Reg#2, ... diff --git a/lib/Target/MBlaze/MBlazeInstrFPU.td b/lib/Target/MBlaze/MBlazeInstrFPU.td index 657b1d4..d9845bb 100644 --- a/lib/Target/MBlaze/MBlazeInstrFPU.td +++ b/lib/Target/MBlaze/MBlazeInstrFPU.td @@ -24,9 +24,9 @@ class LoadFM<bits<6> op, string instr_asm, PatFrag OpNode> : [(set FGR32:$dst, (OpNode xaddr:$addr))], IILoad>; class LoadFMI<bits<6> op, string instr_asm, PatFrag OpNode> : - TAI<op, (outs FGR32:$dst), (ins memri:$addr), - !strconcat(instr_asm, " $dst, $addr"), - [(set FGR32:$dst, (OpNode iaddr:$addr))], IILoad>; + TB<op, (outs FGR32:$dst), (ins memri:$addr), + !strconcat(instr_asm, " $dst, $addr"), + [(set FGR32:$dst, (OpNode iaddr:$addr))], IILoad>; class StoreFM<bits<6> op, string instr_asm, PatFrag OpNode> : TA<op, 0x000, (outs), (ins FGR32:$dst, memrr:$addr), @@ -34,9 +34,9 @@ class StoreFM<bits<6> op, string instr_asm, PatFrag OpNode> : [(OpNode FGR32:$dst, xaddr:$addr)], IIStore>; class StoreFMI<bits<6> op, string instr_asm, PatFrag OpNode> : - TAI<op, (outs), (ins FGR32:$dst, memrr:$addr), - !strconcat(instr_asm, " $dst, $addr"), - [(OpNode FGR32:$dst, iaddr:$addr)], IIStore>; + TB<op, (outs), (ins FGR32:$dst, memrr:$addr), + !strconcat(instr_asm, " $dst, $addr"), + [(OpNode FGR32:$dst, iaddr:$addr)], IIStore>; class ArithF<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : @@ -56,35 +56,35 @@ class ArithFR<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode, !strconcat(instr_asm, " $dst, $c, $b"), [(set FGR32:$dst, (OpNode FGR32:$b, FGR32:$c))], itin>; -class ArithF2<bits<6> op, bits<11> flags, string instr_asm, - InstrItinClass itin> : - TF<op, flags, (outs FGR32:$dst), (ins FGR32:$b), - !strconcat(instr_asm, " $dst, $b"), - [], itin>; - -class ArithIF<bits<6> op, bits<11> flags, string instr_asm, - InstrItinClass itin> : - TF<op, flags, (outs FGR32:$dst), (ins CPURegs:$b), - !strconcat(instr_asm, " $dst, $b"), - [], itin>; - -class ArithFI<bits<6> op, bits<11> flags, string instr_asm, - InstrItinClass itin> : - TF<op, flags, (outs CPURegs:$dst), (ins FGR32:$b), - !strconcat(instr_asm, " $dst, $b"), - [], itin>; - class LogicF<bits<6> op, string instr_asm> : - TAI<op, (outs FGR32:$dst), (ins FGR32:$b, FGR32:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [], - IIAlu>; + TB<op, (outs FGR32:$dst), (ins FGR32:$b, FGR32:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; class LogicFI<bits<6> op, string instr_asm> : - TAI<op, (outs FGR32:$dst), (ins FGR32:$b, fimm:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [], - IIAlu>; + TB<op, (outs FGR32:$dst), (ins FGR32:$b, fimm:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; + +let rb=0 in { + class ArithF2<bits<6> op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA<op, flags, (outs FGR32:$dst), (ins FGR32:$b), + !strconcat(instr_asm, " $dst, $b"), + [], itin>; + + class ArithIF<bits<6> op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA<op, flags, (outs FGR32:$dst), (ins CPURegs:$b), + !strconcat(instr_asm, " $dst, $b"), + [], itin>; + + class ArithFI<bits<6> op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA<op, flags, (outs CPURegs:$dst), (ins FGR32:$b), + !strconcat(instr_asm, " $dst, $b"), + [], itin>; +} //===----------------------------------------------------------------------===// // Pseudo instructions diff --git a/lib/Target/MBlaze/MBlazeInstrFSL.td b/lib/Target/MBlaze/MBlazeInstrFSL.td index 5158411..f3c1cc3 100644 --- a/lib/Target/MBlaze/MBlazeInstrFSL.td +++ b/lib/Target/MBlaze/MBlazeInstrFSL.td @@ -10,144 +10,208 @@ //===----------------------------------------------------------------------===// // FSL Instruction Formats //===----------------------------------------------------------------------===// -class FSLGetD<bits<6> op, bits<11> flags, string instr_asm, Intrinsic OpNode> : - TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$b), - !strconcat(instr_asm, " $dst, $b"), - [(set CPURegs:$dst, (OpNode CPURegs:$b))], IIAlu>; - -class FSLGet<bits<6> op, string instr_asm, Intrinsic OpNode> : - TAI<op, (outs CPURegs:$dst), (ins fslimm:$b), - !strconcat(instr_asm, " $dst, $b"), - [(set CPURegs:$dst, (OpNode immZExt4:$b))], IIAlu>; - -class FSLPutD<bits<6> op, bits<11> flags, string instr_asm, Intrinsic OpNode> : - TA<op, flags, (outs), (ins CPURegs:$v, CPURegs:$b), - !strconcat(instr_asm, " $v, $b"), - [(OpNode CPURegs:$v, CPURegs:$b)], IIAlu>; - -class FSLPut<bits<6> op, string instr_asm, Intrinsic OpNode> : - TAI<op, (outs), (ins CPURegs:$v, fslimm:$b), - !strconcat(instr_asm, " $v, $b"), - [(OpNode CPURegs:$v, immZExt4:$b)], IIAlu>; - -class FSLPutTD<bits<6> op, bits<11> flags, string instr_asm, Intrinsic OpNode> : - TA<op, flags, (outs), (ins CPURegs:$b), - !strconcat(instr_asm, " $b"), - [(OpNode CPURegs:$b)], IIAlu>; - -class FSLPutT<bits<6> op, string instr_asm, Intrinsic OpNode> : - TAI<op, (outs), (ins fslimm:$b), - !strconcat(instr_asm, " $b"), - [(OpNode immZExt4:$b)], IIAlu>; +class FSLGet<bits<6> op, bits<5> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FFSL, (outs CPURegs:$dst), (ins fslimm:$b), + !strconcat(instr_asm, " $dst, $b"), + [(set CPURegs:$dst, (OpNode immZExt4:$b))],IIAlu> +{ + bits<5> rd; + bits<4> fslno; + + let Inst{6-10} = rd; + let Inst{11-15} = 0x0; + let Inst{16} = 0x0; + let Inst{17-21} = flags; // NCTAE + let Inst{22-27} = 0x0; + let Inst{28-31} = fslno; +} + +class FSLGetD<bits<6> op, bits<5> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FFSLD, (outs CPURegs:$dst), (ins CPURegs:$b), + !strconcat(instr_asm, " $dst, $b"), + [(set CPURegs:$dst, (OpNode CPURegs:$b))], IIAlu> +{ + bits<5> rd; + bits<5> rb; + + let Inst{6-10} = rd; + let Inst{11-15} = 0x0; + let Inst{16-20} = rb; + let Inst{21} = 0x0; + let Inst{22-26} = flags; // NCTAE + let Inst{27-31} = 0x0; +} + +class FSLPut<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FFSL, (outs), (ins CPURegs:$v, fslimm:$b), + !strconcat(instr_asm, " $v, $b"), + [(OpNode CPURegs:$v, immZExt4:$b)], IIAlu> +{ + bits<5> ra; + bits<4> fslno; + + let Inst{6-10} = 0x0; + let Inst{11-15} = ra; + let Inst{16} = 0x1; + let Inst{17-20} = flags; // NCTA + let Inst{21-27} = 0x0; + let Inst{28-31} = fslno; +} + +class FSLPutD<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FFSLD, (outs), (ins CPURegs:$v, CPURegs:$b), + !strconcat(instr_asm, " $v, $b"), + [(OpNode CPURegs:$v, CPURegs:$b)], IIAlu> +{ + bits<5> ra; + bits<5> rb; + + let Inst{6-10} = 0x0; + let Inst{11-15} = ra; + let Inst{16-20} = rb; + let Inst{21} = 0x1; + let Inst{22-25} = flags; // NCTA + let Inst{26-31} = 0x0; +} + +class FSLPutT<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FFSLT, (outs), (ins fslimm:$b), + !strconcat(instr_asm, " $b"), + [(OpNode immZExt4:$b)], IIAlu> +{ + bits<4> fslno; + + let Inst{6-10} = 0x0; + let Inst{11-15} = 0x0; + let Inst{16} = 0x1; + let Inst{17-20} = flags; // NCTA + let Inst{21-27} = 0x0; + let Inst{28-31} = fslno; +} + +class FSLPutTD<bits<6> op, bits<4> flags, string instr_asm, Intrinsic OpNode> : + MBlazeInst<op, FFSLTD, (outs), (ins CPURegs:$b), + !strconcat(instr_asm, " $b"), + [(OpNode CPURegs:$b)], IIAlu> +{ + bits<5> rb; + + let Inst{6-10} = 0x0; + let Inst{11-15} = 0x0; + let Inst{16-20} = rb; + let Inst{21} = 0x1; + let Inst{22-25} = flags; // NCTA + let Inst{26-31} = 0x0; +} //===----------------------------------------------------------------------===// // FSL Get Instructions //===----------------------------------------------------------------------===// -def GET : FSLGet<0x1B, "get ", int_mblaze_fsl_get>; -def AGET : FSLGet<0x1B, "aget ", int_mblaze_fsl_aget>; -def CGET : FSLGet<0x1B, "cget ", int_mblaze_fsl_cget>; -def CAGET : FSLGet<0x1B, "caget ", int_mblaze_fsl_caget>; -def EGET : FSLGet<0x1B, "eget ", int_mblaze_fsl_eget>; -def EAGET : FSLGet<0x1B, "eaget ", int_mblaze_fsl_eaget>; -def ECGET : FSLGet<0x1B, "ecget ", int_mblaze_fsl_ecget>; -def ECAGET : FSLGet<0x1B, "ecaget ", int_mblaze_fsl_ecaget>; -def NGET : FSLGet<0x1B, "nget ", int_mblaze_fsl_nget>; -def NAGET : FSLGet<0x1B, "naget ", int_mblaze_fsl_naget>; -def NCGET : FSLGet<0x1B, "ncget ", int_mblaze_fsl_ncget>; -def NCAGET : FSLGet<0x1B, "ncaget ", int_mblaze_fsl_ncaget>; -def NEGET : FSLGet<0x1B, "neget ", int_mblaze_fsl_neget>; -def NEAGET : FSLGet<0x1B, "neaget ", int_mblaze_fsl_neaget>; -def NECGET : FSLGet<0x1B, "necget ", int_mblaze_fsl_necget>; -def NECAGET : FSLGet<0x1B, "necaget ", int_mblaze_fsl_necaget>; -def TGET : FSLGet<0x1B, "tget ", int_mblaze_fsl_tget>; -def TAGET : FSLGet<0x1B, "taget ", int_mblaze_fsl_taget>; -def TCGET : FSLGet<0x1B, "tcget ", int_mblaze_fsl_tcget>; -def TCAGET : FSLGet<0x1B, "tcaget ", int_mblaze_fsl_tcaget>; -def TEGET : FSLGet<0x1B, "teget ", int_mblaze_fsl_teget>; -def TEAGET : FSLGet<0x1B, "teaget ", int_mblaze_fsl_teaget>; -def TECGET : FSLGet<0x1B, "tecget ", int_mblaze_fsl_tecget>; -def TECAGET : FSLGet<0x1B, "tecaget ", int_mblaze_fsl_tecaget>; -def TNGET : FSLGet<0x1B, "tnget ", int_mblaze_fsl_tnget>; -def TNAGET : FSLGet<0x1B, "tnaget ", int_mblaze_fsl_tnaget>; -def TNCGET : FSLGet<0x1B, "tncget ", int_mblaze_fsl_tncget>; -def TNCAGET : FSLGet<0x1B, "tncaget ", int_mblaze_fsl_tncaget>; -def TNEGET : FSLGet<0x1B, "tneget ", int_mblaze_fsl_tneget>; -def TNEAGET : FSLGet<0x1B, "tneaget ", int_mblaze_fsl_tneaget>; -def TNECGET : FSLGet<0x1B, "tnecget ", int_mblaze_fsl_tnecget>; -def TNECAGET : FSLGet<0x1B, "tnecaget ", int_mblaze_fsl_tnecaget>; +def GET : FSLGet<0x1B, 0x00, "get ", int_mblaze_fsl_get>; +def AGET : FSLGet<0x1B, 0x02, "aget ", int_mblaze_fsl_aget>; +def CGET : FSLGet<0x1B, 0x08, "cget ", int_mblaze_fsl_cget>; +def CAGET : FSLGet<0x1B, 0x0A, "caget ", int_mblaze_fsl_caget>; +def EGET : FSLGet<0x1B, 0x01, "eget ", int_mblaze_fsl_eget>; +def EAGET : FSLGet<0x1B, 0x03, "eaget ", int_mblaze_fsl_eaget>; +def ECGET : FSLGet<0x1B, 0x09, "ecget ", int_mblaze_fsl_ecget>; +def ECAGET : FSLGet<0x1B, 0x0B, "ecaget ", int_mblaze_fsl_ecaget>; +def NGET : FSLGet<0x1B, 0x10, "nget ", int_mblaze_fsl_nget>; +def NAGET : FSLGet<0x1B, 0x12, "naget ", int_mblaze_fsl_naget>; +def NCGET : FSLGet<0x1B, 0x18, "ncget ", int_mblaze_fsl_ncget>; +def NCAGET : FSLGet<0x1B, 0x1A, "ncaget ", int_mblaze_fsl_ncaget>; +def NEGET : FSLGet<0x1B, 0x11, "neget ", int_mblaze_fsl_neget>; +def NEAGET : FSLGet<0x1B, 0x13, "neaget ", int_mblaze_fsl_neaget>; +def NECGET : FSLGet<0x1B, 0x19, "necget ", int_mblaze_fsl_necget>; +def NECAGET : FSLGet<0x1B, 0x1B, "necaget ", int_mblaze_fsl_necaget>; +def TGET : FSLGet<0x1B, 0x04, "tget ", int_mblaze_fsl_tget>; +def TAGET : FSLGet<0x1B, 0x06, "taget ", int_mblaze_fsl_taget>; +def TCGET : FSLGet<0x1B, 0x0C, "tcget ", int_mblaze_fsl_tcget>; +def TCAGET : FSLGet<0x1B, 0x0E, "tcaget ", int_mblaze_fsl_tcaget>; +def TEGET : FSLGet<0x1B, 0x05, "teget ", int_mblaze_fsl_teget>; +def TEAGET : FSLGet<0x1B, 0x07, "teaget ", int_mblaze_fsl_teaget>; +def TECGET : FSLGet<0x1B, 0x0D, "tecget ", int_mblaze_fsl_tecget>; +def TECAGET : FSLGet<0x1B, 0x0F, "tecaget ", int_mblaze_fsl_tecaget>; +def TNGET : FSLGet<0x1B, 0x14, "tnget ", int_mblaze_fsl_tnget>; +def TNAGET : FSLGet<0x1B, 0x16, "tnaget ", int_mblaze_fsl_tnaget>; +def TNCGET : FSLGet<0x1B, 0x1C, "tncget ", int_mblaze_fsl_tncget>; +def TNCAGET : FSLGet<0x1B, 0x1E, "tncaget ", int_mblaze_fsl_tncaget>; +def TNEGET : FSLGet<0x1B, 0x15, "tneget ", int_mblaze_fsl_tneget>; +def TNEAGET : FSLGet<0x1B, 0x17, "tneaget ", int_mblaze_fsl_tneaget>; +def TNECGET : FSLGet<0x1B, 0x1D, "tnecget ", int_mblaze_fsl_tnecget>; +def TNECAGET : FSLGet<0x1B, 0x1F, "tnecaget ", int_mblaze_fsl_tnecaget>; //===----------------------------------------------------------------------===// // FSL Dynamic Get Instructions //===----------------------------------------------------------------------===// -def GETD : FSLGetD<0x1B, 0x00, "getd ", int_mblaze_fsl_get>; -def AGETD : FSLGetD<0x1B, 0x00, "agetd ", int_mblaze_fsl_aget>; -def CGETD : FSLGetD<0x1B, 0x00, "cgetd ", int_mblaze_fsl_cget>; -def CAGETD : FSLGetD<0x1B, 0x00, "cagetd ", int_mblaze_fsl_caget>; -def EGETD : FSLGetD<0x1B, 0x00, "egetd ", int_mblaze_fsl_eget>; -def EAGETD : FSLGetD<0x1B, 0x00, "eagetd ", int_mblaze_fsl_eaget>; -def ECGETD : FSLGetD<0x1B, 0x00, "ecgetd ", int_mblaze_fsl_ecget>; -def ECAGETD : FSLGetD<0x1B, 0x00, "ecagetd ", int_mblaze_fsl_ecaget>; -def NGETD : FSLGetD<0x1B, 0x00, "ngetd ", int_mblaze_fsl_nget>; -def NAGETD : FSLGetD<0x1B, 0x00, "nagetd ", int_mblaze_fsl_naget>; -def NCGETD : FSLGetD<0x1B, 0x00, "ncgetd ", int_mblaze_fsl_ncget>; -def NCAGETD : FSLGetD<0x1B, 0x00, "ncagetd ", int_mblaze_fsl_ncaget>; -def NEGETD : FSLGetD<0x1B, 0x00, "negetd ", int_mblaze_fsl_neget>; -def NEAGETD : FSLGetD<0x1B, 0x00, "neagetd ", int_mblaze_fsl_neaget>; -def NECGETD : FSLGetD<0x1B, 0x00, "necgetd ", int_mblaze_fsl_necget>; -def NECAGETD : FSLGetD<0x1B, 0x00, "necagetd ", int_mblaze_fsl_necaget>; -def TGETD : FSLGetD<0x1B, 0x00, "tgetd ", int_mblaze_fsl_tget>; -def TAGETD : FSLGetD<0x1B, 0x00, "tagetd ", int_mblaze_fsl_taget>; -def TCGETD : FSLGetD<0x1B, 0x00, "tcgetd ", int_mblaze_fsl_tcget>; -def TCAGETD : FSLGetD<0x1B, 0x00, "tcagetd ", int_mblaze_fsl_tcaget>; -def TEGETD : FSLGetD<0x1B, 0x00, "tegetd ", int_mblaze_fsl_teget>; -def TEAGETD : FSLGetD<0x1B, 0x00, "teagetd ", int_mblaze_fsl_teaget>; -def TECGETD : FSLGetD<0x1B, 0x00, "tecgetd ", int_mblaze_fsl_tecget>; -def TECAGETD : FSLGetD<0x1B, 0x00, "tecagetd ", int_mblaze_fsl_tecaget>; -def TNGETD : FSLGetD<0x1B, 0x00, "tngetd ", int_mblaze_fsl_tnget>; -def TNAGETD : FSLGetD<0x1B, 0x00, "tnagetd ", int_mblaze_fsl_tnaget>; -def TNCGETD : FSLGetD<0x1B, 0x00, "tncgetd ", int_mblaze_fsl_tncget>; -def TNCAGETD : FSLGetD<0x1B, 0x00, "tncagetd ", int_mblaze_fsl_tncaget>; -def TNEGETD : FSLGetD<0x1B, 0x00, "tnegetd ", int_mblaze_fsl_tneget>; -def TNEAGETD : FSLGetD<0x1B, 0x00, "tneagetd ", int_mblaze_fsl_tneaget>; -def TNECGETD : FSLGetD<0x1B, 0x00, "tnecgetd ", int_mblaze_fsl_tnecget>; -def TNECAGETD : FSLGetD<0x1B, 0x00, "tnecagetd", int_mblaze_fsl_tnecaget>; +def GETD : FSLGetD<0x13, 0x00, "getd ", int_mblaze_fsl_get>; +def AGETD : FSLGetD<0x13, 0x02, "agetd ", int_mblaze_fsl_aget>; +def CGETD : FSLGetD<0x13, 0x08, "cgetd ", int_mblaze_fsl_cget>; +def CAGETD : FSLGetD<0x13, 0x0A, "cagetd ", int_mblaze_fsl_caget>; +def EGETD : FSLGetD<0x13, 0x01, "egetd ", int_mblaze_fsl_eget>; +def EAGETD : FSLGetD<0x13, 0x03, "eagetd ", int_mblaze_fsl_eaget>; +def ECGETD : FSLGetD<0x13, 0x09, "ecgetd ", int_mblaze_fsl_ecget>; +def ECAGETD : FSLGetD<0x13, 0x0B, "ecagetd ", int_mblaze_fsl_ecaget>; +def NGETD : FSLGetD<0x13, 0x10, "ngetd ", int_mblaze_fsl_nget>; +def NAGETD : FSLGetD<0x13, 0x12, "nagetd ", int_mblaze_fsl_naget>; +def NCGETD : FSLGetD<0x13, 0x18, "ncgetd ", int_mblaze_fsl_ncget>; +def NCAGETD : FSLGetD<0x13, 0x1A, "ncagetd ", int_mblaze_fsl_ncaget>; +def NEGETD : FSLGetD<0x13, 0x11, "negetd ", int_mblaze_fsl_neget>; +def NEAGETD : FSLGetD<0x13, 0x13, "neagetd ", int_mblaze_fsl_neaget>; +def NECGETD : FSLGetD<0x13, 0x19, "necgetd ", int_mblaze_fsl_necget>; +def NECAGETD : FSLGetD<0x13, 0x1B, "necagetd ", int_mblaze_fsl_necaget>; +def TGETD : FSLGetD<0x13, 0x04, "tgetd ", int_mblaze_fsl_tget>; +def TAGETD : FSLGetD<0x13, 0x06, "tagetd ", int_mblaze_fsl_taget>; +def TCGETD : FSLGetD<0x13, 0x0C, "tcgetd ", int_mblaze_fsl_tcget>; +def TCAGETD : FSLGetD<0x13, 0x0E, "tcagetd ", int_mblaze_fsl_tcaget>; +def TEGETD : FSLGetD<0x13, 0x05, "tegetd ", int_mblaze_fsl_teget>; +def TEAGETD : FSLGetD<0x13, 0x07, "teagetd ", int_mblaze_fsl_teaget>; +def TECGETD : FSLGetD<0x13, 0x0D, "tecgetd ", int_mblaze_fsl_tecget>; +def TECAGETD : FSLGetD<0x13, 0x0F, "tecagetd ", int_mblaze_fsl_tecaget>; +def TNGETD : FSLGetD<0x13, 0x14, "tngetd ", int_mblaze_fsl_tnget>; +def TNAGETD : FSLGetD<0x13, 0x16, "tnagetd ", int_mblaze_fsl_tnaget>; +def TNCGETD : FSLGetD<0x13, 0x1C, "tncgetd ", int_mblaze_fsl_tncget>; +def TNCAGETD : FSLGetD<0x13, 0x1E, "tncagetd ", int_mblaze_fsl_tncaget>; +def TNEGETD : FSLGetD<0x13, 0x15, "tnegetd ", int_mblaze_fsl_tneget>; +def TNEAGETD : FSLGetD<0x13, 0x17, "tneagetd ", int_mblaze_fsl_tneaget>; +def TNECGETD : FSLGetD<0x13, 0x1D, "tnecgetd ", int_mblaze_fsl_tnecget>; +def TNECAGETD : FSLGetD<0x13, 0x1F, "tnecagetd", int_mblaze_fsl_tnecaget>; //===----------------------------------------------------------------------===// // FSL Put Instructions //===----------------------------------------------------------------------===// -def PUT : FSLPut<0x1B, "put ", int_mblaze_fsl_put>; -def APUT : FSLPut<0x1B, "aput ", int_mblaze_fsl_aput>; -def CPUT : FSLPut<0x1B, "cput ", int_mblaze_fsl_cput>; -def CAPUT : FSLPut<0x1B, "caput ", int_mblaze_fsl_caput>; -def NPUT : FSLPut<0x1B, "nput ", int_mblaze_fsl_nput>; -def NAPUT : FSLPut<0x1B, "naput ", int_mblaze_fsl_naput>; -def NCPUT : FSLPut<0x1B, "ncput ", int_mblaze_fsl_ncput>; -def NCAPUT : FSLPut<0x1B, "ncaput ", int_mblaze_fsl_ncaput>; -def TPUT : FSLPutT<0x1B, "tput ", int_mblaze_fsl_tput>; -def TAPUT : FSLPutT<0x1B, "taput ", int_mblaze_fsl_taput>; -def TCPUT : FSLPutT<0x1B, "tcput ", int_mblaze_fsl_tcput>; -def TCAPUT : FSLPutT<0x1B, "tcaput ", int_mblaze_fsl_tcaput>; -def TNPUT : FSLPutT<0x1B, "tnput ", int_mblaze_fsl_tnput>; -def TNAPUT : FSLPutT<0x1B, "tnaput ", int_mblaze_fsl_tnaput>; -def TNCPUT : FSLPutT<0x1B, "tncput ", int_mblaze_fsl_tncput>; -def TNCAPUT : FSLPutT<0x1B, "tncaput ", int_mblaze_fsl_tncaput>; +def PUT : FSLPut<0x1B, 0x0, "put ", int_mblaze_fsl_put>; +def APUT : FSLPut<0x1B, 0x1, "aput ", int_mblaze_fsl_aput>; +def CPUT : FSLPut<0x1B, 0x4, "cput ", int_mblaze_fsl_cput>; +def CAPUT : FSLPut<0x1B, 0x5, "caput ", int_mblaze_fsl_caput>; +def NPUT : FSLPut<0x1B, 0x8, "nput ", int_mblaze_fsl_nput>; +def NAPUT : FSLPut<0x1B, 0x9, "naput ", int_mblaze_fsl_naput>; +def NCPUT : FSLPut<0x1B, 0xC, "ncput ", int_mblaze_fsl_ncput>; +def NCAPUT : FSLPut<0x1B, 0xD, "ncaput ", int_mblaze_fsl_ncaput>; +def TPUT : FSLPutT<0x1B, 0x2, "tput ", int_mblaze_fsl_tput>; +def TAPUT : FSLPutT<0x1B, 0x3, "taput ", int_mblaze_fsl_taput>; +def TCPUT : FSLPutT<0x1B, 0x6, "tcput ", int_mblaze_fsl_tcput>; +def TCAPUT : FSLPutT<0x1B, 0x7, "tcaput ", int_mblaze_fsl_tcaput>; +def TNPUT : FSLPutT<0x1B, 0xA, "tnput ", int_mblaze_fsl_tnput>; +def TNAPUT : FSLPutT<0x1B, 0xB, "tnaput ", int_mblaze_fsl_tnaput>; +def TNCPUT : FSLPutT<0x1B, 0xE, "tncput ", int_mblaze_fsl_tncput>; +def TNCAPUT : FSLPutT<0x1B, 0xF, "tncaput ", int_mblaze_fsl_tncaput>; //===----------------------------------------------------------------------===// // FSL Dynamic Put Instructions //===----------------------------------------------------------------------===// -def PUTD : FSLPutD<0x1B, 0x00, "putd ", int_mblaze_fsl_put>; -def APUTD : FSLPutD<0x1B, 0x00, "aputd ", int_mblaze_fsl_aput>; -def CPUTD : FSLPutD<0x1B, 0x00, "cputd ", int_mblaze_fsl_cput>; -def CAPUTD : FSLPutD<0x1B, 0x00, "caputd ", int_mblaze_fsl_caput>; -def NPUTD : FSLPutD<0x1B, 0x00, "nputd ", int_mblaze_fsl_nput>; -def NAPUTD : FSLPutD<0x1B, 0x00, "naputd ", int_mblaze_fsl_naput>; -def NCPUTD : FSLPutD<0x1B, 0x00, "ncputd ", int_mblaze_fsl_ncput>; -def NCAPUTD : FSLPutD<0x1B, 0x00, "ncaputd ", int_mblaze_fsl_ncaput>; -def TPUTD : FSLPutTD<0x1B, 0x00, "tputd ", int_mblaze_fsl_tput>; -def TAPUTD : FSLPutTD<0x1B, 0x00, "taputd ", int_mblaze_fsl_taput>; -def TCPUTD : FSLPutTD<0x1B, 0x00, "tcputd ", int_mblaze_fsl_tcput>; -def TCAPUTD : FSLPutTD<0x1B, 0x00, "tcaputd ", int_mblaze_fsl_tcaput>; -def TNPUTD : FSLPutTD<0x1B, 0x00, "tnputd ", int_mblaze_fsl_tnput>; -def TNAPUTD : FSLPutTD<0x1B, 0x00, "tnaputd ", int_mblaze_fsl_tnaput>; -def TNCPUTD : FSLPutTD<0x1B, 0x00, "tncputd ", int_mblaze_fsl_tncput>; -def TNCAPUTD : FSLPutTD<0x1B, 0x00, "tncaputd ", int_mblaze_fsl_tncaput>; +def PUTD : FSLPutD<0x13, 0x0, "putd ", int_mblaze_fsl_put>; +def APUTD : FSLPutD<0x13, 0x1, "aputd ", int_mblaze_fsl_aput>; +def CPUTD : FSLPutD<0x13, 0x4, "cputd ", int_mblaze_fsl_cput>; +def CAPUTD : FSLPutD<0x13, 0x5, "caputd ", int_mblaze_fsl_caput>; +def NPUTD : FSLPutD<0x13, 0x8, "nputd ", int_mblaze_fsl_nput>; +def NAPUTD : FSLPutD<0x13, 0x9, "naputd ", int_mblaze_fsl_naput>; +def NCPUTD : FSLPutD<0x13, 0xC, "ncputd ", int_mblaze_fsl_ncput>; +def NCAPUTD : FSLPutD<0x13, 0xD, "ncaputd ", int_mblaze_fsl_ncaput>; +def TPUTD : FSLPutTD<0x13, 0x2, "tputd ", int_mblaze_fsl_tput>; +def TAPUTD : FSLPutTD<0x13, 0x3, "taputd ", int_mblaze_fsl_taput>; +def TCPUTD : FSLPutTD<0x13, 0x6, "tcputd ", int_mblaze_fsl_tcput>; +def TCAPUTD : FSLPutTD<0x13, 0x7, "tcaputd ", int_mblaze_fsl_tcaput>; +def TNPUTD : FSLPutTD<0x13, 0xA, "tnputd ", int_mblaze_fsl_tnput>; +def TNAPUTD : FSLPutTD<0x13, 0xB, "tnaputd ", int_mblaze_fsl_tnaput>; +def TNCPUTD : FSLPutTD<0x13, 0xE, "tncputd ", int_mblaze_fsl_tncput>; +def TNCAPUTD : FSLPutTD<0x13, 0xF, "tncaputd ", int_mblaze_fsl_tncaput>; diff --git a/lib/Target/MBlaze/MBlazeInstrFormats.td b/lib/Target/MBlaze/MBlazeInstrFormats.td index 28e8e44..595ef1d 100644 --- a/lib/Target/MBlaze/MBlazeInstrFormats.td +++ b/lib/Target/MBlaze/MBlazeInstrFormats.td @@ -7,6 +7,26 @@ // //===----------------------------------------------------------------------===// +// Format specifies the encoding used by the instruction. This is part of the +// ad-hoc solution used to emit machine instruction encodings by our machine +// code emitter. +class Format<bits<6> val> { + bits<6> Value = val; +} + +def FPseudo : Format<0>; +def FRRR : Format<1>; +def FRRI : Format<2>; +def FRIR : Format<3>; +def FFSL : Format<4>; +def FFSLD : Format<5>; +def FFSLT : Format<6>; +def FFSLTD : Format<7>; +def FR : Format<8>; +def FI : Format<9>; +def FRR : Format<10>; +def FRI : Format<11>; + //===----------------------------------------------------------------------===// // Describe MBlaze instructions format // @@ -21,14 +41,15 @@ //===----------------------------------------------------------------------===// // Generic MBlaze Format -class MBlazeInst<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin> : Instruction +class MBlazeInst<bits<6> op, Format form, dag outs, dag ins, string asmstr, + list<dag> pattern, InstrItinClass itin> : Instruction { - field bits<32> Inst; - let Namespace = "MBlaze"; + field bits<32> Inst; - bits<6> opcode; + bits<6> opcode = op; + Format Form = form; + bits<6> FormBits = Form.Value; // Top 6 bits are the 'opcode' field let Inst{0-5} = opcode; @@ -39,13 +60,16 @@ class MBlazeInst<dag outs, dag ins, string asmstr, list<dag> pattern, let AsmString = asmstr; let Pattern = pattern; let Itinerary = itin; + + // TSFlags layout should be kept in sync with MBlazeInstrInfo.h. + let TSFlags{5-0} = FormBits; } //===----------------------------------------------------------------------===// // Pseudo instruction class //===----------------------------------------------------------------------===// class MBlazePseudo<dag outs, dag ins, string asmstr, list<dag> pattern>: - MBlazeInst<outs, ins, asmstr, pattern, IIPseudo>; + MBlazeInst<0x0, FPseudo, outs, ins, asmstr, pattern, IIPseudo>; //===----------------------------------------------------------------------===// // Type A instruction class in MBlaze : <|opcode|rd|ra|rb|flags|> @@ -53,194 +77,49 @@ class MBlazePseudo<dag outs, dag ins, string asmstr, list<dag> pattern>: class TA<bits<6> op, bits<11> flags, dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> + MBlazeInst<op,FRRR,outs, ins, asmstr, pattern, itin> { bits<5> rd; bits<5> ra; bits<5> rb; - let opcode = op; - let Inst{6-10} = rd; let Inst{11-15} = ra; let Inst{16-20} = rb; let Inst{21-31} = flags; } -class TAI<bits<6> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> rd; - bits<5> ra; - bits<16> imm16; - - let opcode = op; - - let Inst{6-10} = rd; - let Inst{11-15} = ra; - let Inst{16-31} = imm16; -} - -class TIMM<bits<6> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - bits<16> imm16; - - let opcode = op; - - let Inst{6-15} = 0; - let Inst{16-31} = imm16; -} - -class TADDR<bits<6> op, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<26> addr; - - let opcode = op; - - let Inst{6-31} = addr; -} - //===----------------------------------------------------------------------===// // Type B instruction class in MBlaze : <|opcode|rd|ra|immediate|> //===----------------------------------------------------------------------===// class TB<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> + MBlazeInst<op, FRRI, outs, ins, asmstr, pattern, itin> { bits<5> rd; bits<5> ra; bits<16> imm16; - let opcode = op; - let Inst{6-10} = rd; let Inst{11-15} = ra; let Inst{16-31} = imm16; } //===----------------------------------------------------------------------===// -// Float instruction class in MBlaze : <|opcode|rd|ra|flags|> +// Type B instruction class in MBlaze but with the operands reversed in +// the LLVM DAG : <|opcode|rd|ra|immediate|> //===----------------------------------------------------------------------===// +class TBR<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin> : + TB<op, outs, ins, asmstr, pattern, itin> { + bits<5> rrd; + bits<16> rimm16; + bits<5> rra; -class TF<bits<6> op, bits<11> flags, dag outs, dag ins, string asmstr, - list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> rd; - bits<5> ra; - - let opcode = op; - - let Inst{6-10} = rd; - let Inst{11-15} = ra; - let Inst{16-20} = 0; - let Inst{21-31} = flags; -} - -//===----------------------------------------------------------------------===// -// Branch instruction class in MBlaze : <|opcode|rd|br|ra|flags|> -//===----------------------------------------------------------------------===// - -class TBR<bits<6> op, bits<5> br, bits<11> flags, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - - let opcode = op; - - let Inst{6-10} = 0; - let Inst{11-15} = br; - let Inst{16-20} = ra; - let Inst{21-31} = flags; -} - -class TBRC<bits<6> op, bits<5> br, bits<11> flags, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - bits<5> rb; - - let opcode = op; - - let Inst{6-10} = br; - let Inst{11-15} = ra; - let Inst{16-20} = rb; - let Inst{21-31} = flags; -} - -class TBRL<bits<6> op, bits<5> br, bits<11> flags, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - - let opcode = op; - - let Inst{6-10} = 0xF; - let Inst{11-15} = br; - let Inst{16-20} = ra; - let Inst{21-31} = flags; -} - -class TBRI<bits<6> op, bits<5> br, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<16> imm16; - - let opcode = op; - - let Inst{6-10} = 0; - let Inst{11-15} = br; - let Inst{16-31} = imm16; -} - -class TBRLI<bits<6> op, bits<5> br, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<16> imm16; - - let opcode = op; - - let Inst{6-10} = 0xF; - let Inst{11-15} = br; - let Inst{16-31} = imm16; -} - -class TBRCI<bits<6> op, bits<5> br, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - bits<16> imm16; - - let opcode = op; - - let Inst{6-10} = br; - let Inst{11-15} = ra; - let Inst{16-31} = imm16; -} - -class TRET<bits<6> op, dag outs, dag ins, - string asmstr, list<dag> pattern, InstrItinClass itin> : - MBlazeInst<outs, ins, asmstr, pattern, itin> -{ - bits<5> ra; - bits<16> imm16; - - let opcode = op; + let Form = FRIR; - let Inst{6-10} = 0x10; - let Inst{11-15} = ra; - let Inst{16-31} = imm16; + let rd = rrd; + let ra = rra; + let imm16 = rimm16; } diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.h b/lib/Target/MBlaze/MBlazeInstrInfo.h index b3dba0e..eda16cc 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.h +++ b/lib/Target/MBlaze/MBlazeInstrInfo.h @@ -134,29 +134,47 @@ namespace MBlaze { /// instruction info tracks. /// namespace MBlazeII { - /// Target Operand Flag enum. - enum TOF { + enum { + // PseudoFrm - This represents an instruction that is a pseudo instruction + // or one that has not been implemented yet. It is illegal to code generate + // it, but tolerated for intermediate implementation stages. + Pseudo = 0, + + RegRegReg = 1, + RegRegImm = 2, + RegImmReg = 3, + FSL = 4, + FSLD = 5, + FSLT = 6, + FSLTD = 7, + Reg = 8, + Imm = 9, + RegReg = 10, + RegImm = 11, + + FormMask = 63 + //===------------------------------------------------------------------===// // MBlaze Specific MachineOperand flags. - MO_NO_FLAG, + // MO_NO_FLAG, /// MO_GOT - Represents the offset into the global offset table at which /// the address the relocation entry symbol resides during execution. - MO_GOT, + // MO_GOT, /// MO_GOT_CALL - Represents the offset into the global offset table at /// which the address of a call site relocation entry symbol resides /// during execution. This is different from the above since this flag /// can only be present in call instructions. - MO_GOT_CALL, + // MO_GOT_CALL, /// MO_GPREL - Represents the offset from the current gp value to be used /// for the relocatable object file being produced. - MO_GPREL, + // MO_GPREL, /// MO_ABS_HILO - Represents the hi or low part of an absolute symbol /// address. - MO_ABS_HILO + // MO_ABS_HILO }; } diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.td b/lib/Target/MBlaze/MBlazeInstrInfo.td index e5d1534..41c80ef 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.td +++ b/lib/Target/MBlaze/MBlazeInstrInfo.td @@ -13,36 +13,33 @@ include "MBlazeInstrFormats.td" //===----------------------------------------------------------------------===// -// MBlaze profiles and nodes +// MBlaze type profiles //===----------------------------------------------------------------------===// + +// def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>; def SDT_MBlazeRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_MBlazeJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; +def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; -// Call -def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink, - [SDNPHasChain,SDNPOptInFlag,SDNPOutFlag]>; +//===----------------------------------------------------------------------===// +// MBlaze specific nodes +//===----------------------------------------------------------------------===// -// Return -def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet, +def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet, [SDNPHasChain, SDNPOptInFlag]>; -// Hi and Lo nodes are used to handle global addresses. Used on -// MBlazeISelLowering to lower stuff like GlobalAddress, ExternalSymbol -// static model. -def MBWrapper : SDNode<"MBlazeISD::Wrap", SDTIntUnaryOp>; -def MBlazeGPRel : SDNode<"MBlazeISD::GPRel", SDTIntUnaryOp>; +def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink, + [SDNPHasChain,SDNPOptInFlag,SDNPOutFlag]>; -def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; -def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; +def MBWrapper : SDNode<"MBlazeISD::Wrap", SDTIntUnaryOp>; -// These are target-independent nodes, but have target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MBCallSeqStart, [SDNPHasChain, SDNPOutFlag]>; + def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MBCallSeqEnd, [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; -def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>; - //===----------------------------------------------------------------------===// // MBlaze Instruction Predicate Definitions. //===----------------------------------------------------------------------===// @@ -95,18 +92,7 @@ def memrr : Operand<i32> { let MIOperandInfo = (ops CPURegs, CPURegs); } -// Transformation Function - get the lower 16 bits. -def LO16 : SDNodeXForm<imm, [{ - return getI32Imm((unsigned)N->getZExtValue() & 0xFFFF); -}]>; - -// Transformation Function - get the higher 16 bits. -def HI16 : SDNodeXForm<imm, [{ - return getI32Imm((unsigned)N->getZExtValue() >> 16); -}]>; - // Node immediate fits as 16-bit sign extended on target immediate. -// e.g. addi, andi def immSExt16 : PatLeaf<(imm), [{ return (N->getZExtValue() >> 16) == 0; }]>; @@ -117,19 +103,19 @@ def immSExt16 : PatLeaf<(imm), [{ // e.g. addiu, sltiu def immZExt16 : PatLeaf<(imm), [{ return (N->getZExtValue() >> 16) == 0; -}], LO16>; +}]>; // FSL immediate field must fit in 4 bits. def immZExt4 : PatLeaf<(imm), [{ - return N->getZExtValue() == ((N->getZExtValue()) & 0xf) ; + return N->getZExtValue() == ((N->getZExtValue()) & 0xf) ; }]>; // shamt field must fit in 5 bits. def immZExt5 : PatLeaf<(imm), [{ - return N->getZExtValue() == ((N->getZExtValue()) & 0x1f) ; + return N->getZExtValue() == ((N->getZExtValue()) & 0x1f) ; }]>; -// MBlaze Address Mode! SDNode frameindex could possibily be a match +// MBlaze Address Mode. SDNode frameindex could possibily be a match // since load and store instructions from stack used it. def iaddr : ComplexPattern<i32, 2, "SelectAddrRegImm", [frameindex], []>; def xaddr : ComplexPattern<i32, 2, "SelectAddrRegReg", [], []>; @@ -141,28 +127,14 @@ def xaddr : ComplexPattern<i32, 2, "SelectAddrRegReg", [], []>; // As stack alignment is always done with addiu, we need a 16-bit immediate let Defs = [R1], Uses = [R1] in { def ADJCALLSTACKDOWN : MBlazePseudo<(outs), (ins simm16:$amt), - "${:comment} ADJCALLSTACKDOWN $amt", + "#ADJCALLSTACKDOWN $amt", [(callseq_start timm:$amt)]>; def ADJCALLSTACKUP : MBlazePseudo<(outs), (ins uimm16:$amt1, simm16:$amt2), - "${:comment} ADJCALLSTACKUP $amt1", + "#ADJCALLSTACKUP $amt1", [(callseq_end timm:$amt1, timm:$amt2)]>; } -// Some assembly macros need to avoid pseudoinstructions and assembler -// automatic reodering, we should reorder ourselves. -def MACRO : MBlazePseudo<(outs), (ins), ".set macro", []>; -def REORDER : MBlazePseudo<(outs), (ins), ".set reorder", []>; -def NOMACRO : MBlazePseudo<(outs), (ins), ".set nomacro", []>; -def NOREORDER : MBlazePseudo<(outs), (ins), ".set noreorder", []>; - -// When handling PIC code the assembler needs .cpload and .cprestore -// directives. If the real instructions corresponding these directives -// are used, we have the same behavior, but get also a bunch of warnings -// from the assembler. -def CPLOAD : MBlazePseudo<(outs), (ins CPURegs:$reg), ".cpload $reg", []>; -def CPRESTORE : MBlazePseudo<(outs), (ins uimm16:$l), ".cprestore $l\n", []>; - //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -178,19 +150,19 @@ class Arith<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode, class ArithI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - TAI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>; + TB<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>; class ArithR<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b), - !strconcat(instr_asm, " $dst, $c, $b"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>; + !strconcat(instr_asm, " $dst, $c, $b"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>; class ArithRI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : - TAI<op, (outs CPURegs:$dst), (ins Od:$b, CPURegs:$c), + TBR<op, (outs CPURegs:$dst), (ins Od:$b, CPURegs:$c), !strconcat(instr_asm, " $dst, $c, $b"), [(set CPURegs:$dst, (OpNode imm_type:$b, CPURegs:$c))], IIAlu>; @@ -201,9 +173,9 @@ class ArithN<bits<6> op, bits<11> flags, string instr_asm, [], itin>; class ArithNI<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> : - TAI<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [], IIAlu>; + TB<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; class ArithRN<bits<6> op, bits<11> flags, string instr_asm, InstrItinClass itin> : @@ -212,9 +184,9 @@ class ArithRN<bits<6> op, bits<11> flags, string instr_asm, [], itin>; class ArithRNI<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> : - TAI<op, (outs CPURegs:$dst), (ins Od:$c, CPURegs:$b), - !strconcat(instr_asm, " $dst, $b, $c"), - [], IIAlu>; + TB<op, (outs CPURegs:$dst), (ins Od:$c, CPURegs:$b), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; //===----------------------------------------------------------------------===// // Misc Arithmetic Instructions @@ -226,14 +198,10 @@ class Logic<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode> : [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>; class LogicI<bits<6> op, string instr_asm, SDNode OpNode> : - TAI<op, (outs CPURegs:$dst), (ins CPURegs:$b, uimm16:$c), - !strconcat(instr_asm, " $dst, $b, $c"), - [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], - IIAlu>; - -class EffectiveAddress<string instr_asm> : - TAI<0x08, (outs CPURegs:$dst), (ins memri:$addr), - instr_asm, [(set CPURegs:$dst, iaddr:$addr)], IIAlu>; + TB<op, (outs CPURegs:$dst), (ins CPURegs:$b, uimm16:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))], + IIAlu>; //===----------------------------------------------------------------------===// // Memory Access Instructions @@ -244,7 +212,7 @@ class LoadM<bits<6> op, string instr_asm, PatFrag OpNode> : [(set CPURegs:$dst, (OpNode xaddr:$addr))], IILoad>; class LoadMI<bits<6> op, string instr_asm, PatFrag OpNode> : - TAI<op, (outs CPURegs:$dst), (ins memri:$addr), + TBR<op, (outs CPURegs:$dst), (ins memri:$addr), !strconcat(instr_asm, " $dst, $addr"), [(set CPURegs:$dst, (OpNode iaddr:$addr))], IILoad>; @@ -254,7 +222,7 @@ class StoreM<bits<6> op, string instr_asm, PatFrag OpNode> : [(OpNode CPURegs:$dst, xaddr:$addr)], IIStore>; class StoreMI<bits<6> op, string instr_asm, PatFrag OpNode> : - TAI<op, (outs), (ins CPURegs:$dst, memri:$addr), + TBR<op, (outs), (ins CPURegs:$dst, memri:$addr), !strconcat(instr_asm, " $dst, $addr"), [(OpNode CPURegs:$dst, iaddr:$addr)], IIStore>; @@ -262,94 +230,108 @@ class StoreMI<bits<6> op, string instr_asm, PatFrag OpNode> : // Branch Instructions //===----------------------------------------------------------------------===// class Branch<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> : - TBR<op, br, flags, (outs), (ins CPURegs:$target), + TA<op, flags, (outs), (ins CPURegs:$target), !strconcat(instr_asm, " $target"), - [(brind CPURegs:$target)], IIBranch>; + [], IIBranch> { + let rd = 0x0; + let ra = br; +} -class BranchI<bits<6> op, bits<5> brf, string instr_asm> : - TBRI<op, brf, (outs), (ins brtarget:$target), - !strconcat(instr_asm, " $target"), - [(br bb:$target)], IIBranch>; +class BranchI<bits<6> op, bits<5> br, string instr_asm> : + TB<op, (outs), (ins brtarget:$target), + !strconcat(instr_asm, " $target"), + [], IIBranch> { + let rd = 0; + let ra = br; +} //===----------------------------------------------------------------------===// // Branch and Link Instructions //===----------------------------------------------------------------------===// class BranchL<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> : - TBRL<op, br, flags, (outs), (ins CPURegs:$target), - !strconcat(instr_asm, " r15, $target"), - [], IIBranch>; + TA<op, flags, (outs), (ins CPURegs:$target), + !strconcat(instr_asm, " r15, $target"), + [], IIBranch> { + let rd = 15; + let ra = br; +} class BranchLI<bits<6> op, bits<5> br, string instr_asm> : - TBRLI<op, br, (outs), (ins calltarget:$target), - !strconcat(instr_asm, " r15, $target"), - [], IIBranch>; + TB<op, (outs), (ins calltarget:$target), + !strconcat(instr_asm, " r15, $target"), + [], IIBranch> { + let rd = 15; + let ra = br; +} //===----------------------------------------------------------------------===// // Conditional Branch Instructions //===----------------------------------------------------------------------===// class BranchC<bits<6> op, bits<5> br, bits<11> flags, string instr_asm, PatFrag cond_op> : - TBRC<op, br, flags, (outs), - (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), - !strconcat(instr_asm, " $a, $b, $offset"), - [], IIBranch>; - //(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)], - //IIBranch>; + TA<op, flags, (outs), + (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), + !strconcat(instr_asm, " $a, $b, $offset"), + [], IIBranch> { + let rd = br; +} class BranchCI<bits<6> op, bits<5> br, string instr_asm, PatFrag cond_op> : - TBRCI<op, br, (outs), (ins CPURegs:$a, brtarget:$offset), - !strconcat(instr_asm, " $a, $offset"), - [], IIBranch>; + TB<op, (outs), (ins CPURegs:$a, brtarget:$offset), + !strconcat(instr_asm, " $a, $offset"), + [], IIBranch> { + let rd = br; +} //===----------------------------------------------------------------------===// // MBlaze arithmetic instructions //===----------------------------------------------------------------------===// let isCommutable = 1, isAsCheapAsAMove = 1 in { - def ADD : Arith<0x00, 0x000, "add ", add, IIAlu>; - def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; - def ADDK : Arith<0x04, 0x000, "addk ", addc, IIAlu>; - def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>; - def AND : Logic<0x21, 0x000, "and ", and>; - def OR : Logic<0x20, 0x000, "or ", or>; - def XOR : Logic<0x22, 0x000, "xor ", xor>; + def ADD : Arith<0x00, 0x000, "add ", add, IIAlu>; + def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; + def ADDK : Arith<0x04, 0x000, "addk ", addc, IIAlu>; + def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>; + def AND : Logic<0x21, 0x000, "and ", and>; + def OR : Logic<0x20, 0x000, "or ", or>; + def XOR : Logic<0x22, 0x000, "xor ", xor>; } let isAsCheapAsAMove = 1 in { - def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>; - def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>; - def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>; - def RSUB : ArithR<0x01, 0x000, "rsub ", sub, IIAlu>; - def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; - def RSUBK : ArithR<0x05, 0x000, "rsubk ", subc, IIAlu>; - def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>; + def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>; + def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>; + def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>; + def RSUB : ArithR<0x01, 0x000, "rsub ", sub, IIAlu>; + def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; + def RSUBK : ArithR<0x05, 0x000, "rsubk ", subc, IIAlu>; + def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>; } let isCommutable = 1, Predicates=[HasMul] in { - def MUL : Arith<0x10, 0x000, "mul ", mul, IIAlu>; + def MUL : Arith<0x10, 0x000, "mul ", mul, IIAlu>; } let isCommutable = 1, Predicates=[HasMul,HasMul64] in { - def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIAlu>; - def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIAlu>; + def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIAlu>; + def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIAlu>; } let Predicates=[HasMul,HasMul64] in { - def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIAlu>; + def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIAlu>; } let Predicates=[HasBarrel] in { - def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIAlu>; - def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIAlu>; - def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIAlu>; - def BSRLI : ArithI<0x11, "bsrli ", srl, uimm5, immZExt5>; - def BSRAI : ArithI<0x11, "bsrai ", sra, uimm5, immZExt5>; - def BSLLI : ArithI<0x11, "bslli ", shl, uimm5, immZExt5>; + def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIAlu>; + def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIAlu>; + def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIAlu>; + def BSRLI : ArithI<0x11, "bsrli ", srl, uimm5, immZExt5>; + def BSRAI : ArithI<0x11, "bsrai ", sra, uimm5, immZExt5>; + def BSLLI : ArithI<0x11, "bslli ", shl, uimm5, immZExt5>; } let Predicates=[HasDiv] in { - def IDIV : Arith<0x12, 0x000, "idiv ", sdiv, IIAlu>; - def IDIVU : Arith<0x12, 0x002, "idivu ", udiv, IIAlu>; + def IDIV : Arith<0x12, 0x000, "idiv ", sdiv, IIAlu>; + def IDIVU : Arith<0x12, 0x002, "idivu ", udiv, IIAlu>; } //===----------------------------------------------------------------------===// @@ -357,22 +339,22 @@ let Predicates=[HasDiv] in { //===----------------------------------------------------------------------===// let isAsCheapAsAMove = 1 in { - def ADDI : ArithI<0x08, "addi ", add, simm16, immSExt16>; - def ADDIC : ArithNI<0x0A, "addic ", simm16, immSExt16>; - def ADDIK : ArithNI<0x0C, "addik ", simm16, immSExt16>; - def ADDIKC : ArithI<0x0E, "addikc ", addc, simm16, immSExt16>; - def RSUBI : ArithRI<0x09, "rsubi ", sub, simm16, immSExt16>; - def RSUBIC : ArithRNI<0x0B, "rsubi ", simm16, immSExt16>; - def RSUBIK : ArithRNI<0x0E, "rsubic ", simm16, immSExt16>; - def RSUBIKC : ArithRI<0x0F, "rsubikc", subc, simm16, immSExt16>; - def ANDNI : ArithNI<0x2B, "andni ", uimm16, immZExt16>; - def ANDI : LogicI<0x29, "andi ", and>; - def ORI : LogicI<0x28, "ori ", or>; - def XORI : LogicI<0x2A, "xori ", xor>; + def ADDI : ArithI<0x08, "addi ", add, simm16, immSExt16>; + def ADDIC : ArithNI<0x0A, "addic ", simm16, immSExt16>; + def ADDIK : ArithNI<0x0C, "addik ", simm16, immSExt16>; + def ADDIKC : ArithI<0x0E, "addikc ", addc, simm16, immSExt16>; + def RSUBI : ArithRI<0x09, "rsubi ", sub, simm16, immSExt16>; + def RSUBIC : ArithRNI<0x0B, "rsubi ", simm16, immSExt16>; + def RSUBIK : ArithRNI<0x0E, "rsubic ", simm16, immSExt16>; + def RSUBIKC : ArithRI<0x0F, "rsubikc", subc, simm16, immSExt16>; + def ANDNI : ArithNI<0x2B, "andni ", uimm16, immZExt16>; + def ANDI : LogicI<0x29, "andi ", and>; + def ORI : LogicI<0x28, "ori ", or>; + def XORI : LogicI<0x2A, "xori ", xor>; } let Predicates=[HasMul] in { - def MULI : ArithI<0x18, "muli ", mul, simm16, immSExt16>; + def MULI : ArithI<0x18, "muli ", mul, simm16, immSExt16>; } //===----------------------------------------------------------------------===// @@ -380,115 +362,122 @@ let Predicates=[HasMul] in { //===----------------------------------------------------------------------===// let canFoldAsLoad = 1, isReMaterializable = 1 in { - def LBU : LoadM<0x30, "lbu ", zextloadi8>; - def LHU : LoadM<0x31, "lhu ", zextloadi16>; - def LW : LoadM<0x32, "lw ", load>; + def LBU : LoadM<0x30, "lbu ", zextloadi8>; + def LHU : LoadM<0x31, "lhu ", zextloadi16>; + def LW : LoadM<0x32, "lw ", load>; - def LBUI : LoadMI<0x30, "lbui ", zextloadi8>; - def LHUI : LoadMI<0x31, "lhui ", zextloadi16>; - def LWI : LoadMI<0x32, "lwi ", load>; + def LBUI : LoadMI<0x38, "lbui ", zextloadi8>; + def LHUI : LoadMI<0x39, "lhui ", zextloadi16>; + def LWI : LoadMI<0x3A, "lwi ", load>; } - def SB : StoreM<0x34, "sb ", truncstorei8>; - def SH : StoreM<0x35, "sh ", truncstorei16>; - def SW : StoreM<0x36, "sw ", store>; + def SB : StoreM<0x34, "sb ", truncstorei8>; + def SH : StoreM<0x35, "sh ", truncstorei16>; + def SW : StoreM<0x36, "sw ", store>; - def SBI : StoreMI<0x34, "sbi ", truncstorei8>; - def SHI : StoreMI<0x35, "shi ", truncstorei16>; - def SWI : StoreMI<0x36, "swi ", store>; + def SBI : StoreMI<0x3C, "sbi ", truncstorei8>; + def SHI : StoreMI<0x3D, "shi ", truncstorei16>; + def SWI : StoreMI<0x3E, "swi ", store>; //===----------------------------------------------------------------------===// // MBlaze branch instructions //===----------------------------------------------------------------------===// -let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { - def BRI : BranchI<0x2E, 0x00, "bri ">; - def BRAI : BranchI<0x2E, 0x08, "brai ">; - def BEQI : BranchCI<0x2F, 0x00, "beqi ", seteq>; - def BNEI : BranchCI<0x2F, 0x01, "bnei ", setne>; - def BLTI : BranchCI<0x2F, 0x02, "blti ", setlt>; - def BLEI : BranchCI<0x2F, 0x03, "blei ", setle>; - def BGTI : BranchCI<0x2F, 0x04, "bgti ", setgt>; - def BGEI : BranchCI<0x2F, 0x05, "bgei ", setge>; +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1, + Form = FI in { + def BRI : BranchI<0x2E, 0x00, "bri ">; + def BRAI : BranchI<0x2E, 0x08, "brai ">; } -let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { - def BR : Branch<0x26, 0x00, 0x000, "br ">; - def BRA : Branch<0x26, 0x08, 0x000, "bra ">; - def BEQ : BranchC<0x27, 0x00, 0x000, "beq ", seteq>; - def BNE : BranchC<0x27, 0x01, 0x000, "bne ", setne>; - def BLT : BranchC<0x27, 0x02, 0x000, "blt ", setlt>; - def BLE : BranchC<0x27, 0x03, 0x000, "ble ", setle>; - def BGT : BranchC<0x27, 0x04, 0x000, "bgt ", setgt>; - def BGE : BranchC<0x27, 0x05, 0x000, "bge ", setge>; +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, Form = FRI in { + def BEQI : BranchCI<0x2F, 0x00, "beqi ", seteq>; + def BNEI : BranchCI<0x2F, 0x01, "bnei ", setne>; + def BLTI : BranchCI<0x2F, 0x02, "blti ", setlt>; + def BLEI : BranchCI<0x2F, 0x03, "blei ", setle>; + def BGTI : BranchCI<0x2F, 0x04, "bgti ", setgt>; + def BGEI : BranchCI<0x2F, 0x05, "bgei ", setge>; } -let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1 in { - def BRID : BranchI<0x2E, 0x10, "brid ">; - def BRAID : BranchI<0x2E, 0x18, "braid ">; - def BEQID : BranchCI<0x2F, 0x10, "beqid ", seteq>; - def BNEID : BranchCI<0x2F, 0x11, "bneid ", setne>; - def BLTID : BranchCI<0x2F, 0x12, "bltid ", setlt>; - def BLEID : BranchCI<0x2F, 0x13, "bleid ", setle>; - def BGTID : BranchCI<0x2F, 0x14, "bgtid ", setgt>; - def BGEID : BranchCI<0x2F, 0x15, "bgeid ", setge>; +let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasCtrlDep = 1, + isBarrier = 1, Form = FR in { + def BR : Branch<0x26, 0x00, 0x000, "br ">; + def BRA : Branch<0x26, 0x08, 0x000, "bra ">; +} + +let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasCtrlDep = 1, + Form = FRR in { + def BEQ : BranchC<0x27, 0x00, 0x000, "beq ", seteq>; + def BNE : BranchC<0x27, 0x01, 0x000, "bne ", setne>; + def BLT : BranchC<0x27, 0x02, 0x000, "blt ", setlt>; + def BLE : BranchC<0x27, 0x03, 0x000, "ble ", setle>; + def BGT : BranchC<0x27, 0x04, 0x000, "bgt ", setgt>; + def BGE : BranchC<0x27, 0x05, 0x000, "bge ", setge>; +} + +let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1, + isBarrier = 1, Form = FI in { + def BRID : BranchI<0x2E, 0x10, "brid ">; + def BRAID : BranchI<0x2E, 0x18, "braid ">; +} + +let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1, + Form = FRI in { + def BEQID : BranchCI<0x2F, 0x10, "beqid ", seteq>; + def BNEID : BranchCI<0x2F, 0x11, "bneid ", setne>; + def BLTID : BranchCI<0x2F, 0x12, "bltid ", setlt>; + def BLEID : BranchCI<0x2F, 0x13, "bleid ", setle>; + def BGTID : BranchCI<0x2F, 0x14, "bgtid ", setgt>; + def BGEID : BranchCI<0x2F, 0x15, "bgeid ", setge>; +} + +let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, Form = FR, + hasDelaySlot = 1, hasCtrlDep = 1, isBarrier = 1 in { + def BRD : Branch<0x26, 0x10, 0x000, "brd ">; + def BRAD : Branch<0x26, 0x18, 0x000, "brad ">; } let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, - hasDelaySlot = 1, hasCtrlDep = 1 in { - def BRD : Branch<0x26, 0x10, 0x000, "brd ">; - def BRAD : Branch<0x26, 0x18, 0x000, "brad ">; - def BEQD : BranchC<0x27, 0x10, 0x000, "beqd ", seteq>; - def BNED : BranchC<0x27, 0x11, 0x000, "bned ", setne>; - def BLTD : BranchC<0x27, 0x12, 0x000, "bltd ", setlt>; - def BLED : BranchC<0x27, 0x13, 0x000, "bled ", setle>; - def BGTD : BranchC<0x27, 0x14, 0x000, "bgtd ", setgt>; - def BGED : BranchC<0x27, 0x15, 0x000, "bged ", setge>; -} - -let isCall = 1, hasCtrlDep = 1, isIndirectBranch = 1, - Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], - Uses = [R1,R5,R6,R7,R8,R9,R10] in { - def BRL : BranchL<0x26, 0x04, 0x000, "brl ">; - def BRAL : BranchL<0x26, 0x0C, 0x000, "bral ">; + hasDelaySlot = 1, hasCtrlDep = 1, Form = FRR in { + def BEQD : BranchC<0x27, 0x10, 0x000, "beqd ", seteq>; + def BNED : BranchC<0x27, 0x11, 0x000, "bned ", setne>; + def BLTD : BranchC<0x27, 0x12, 0x000, "bltd ", setlt>; + def BLED : BranchC<0x27, 0x13, 0x000, "bled ", setle>; + def BGTD : BranchC<0x27, 0x14, 0x000, "bgtd ", setgt>; + def BGED : BranchC<0x27, 0x15, 0x000, "bged ", setge>; } -let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, +let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, isBarrier = 1, Form = FI, Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], Uses = [R1,R5,R6,R7,R8,R9,R10] in { - def BRLID : BranchLI<0x2E, 0x14, "brlid ">; - def BRALID : BranchLI<0x2E, 0x1C, "bralid ">; + def BRLID : BranchLI<0x2E, 0x14, "brlid ">; + def BRALID : BranchLI<0x2E, 0x1C, "bralid ">; } let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, isIndirectBranch = 1, + isBarrier = 1, Form = FR, Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], Uses = [R1,R5,R6,R7,R8,R9,R10] in { - def BRLD : BranchL<0x26, 0x14, 0x000, "brld ">; - def BRALD : BranchL<0x26, 0x1C, 0x000, "brald ">; + def BRLD : BranchL<0x26, 0x14, 0x000, "brld ">; + def BRALD : BranchL<0x26, 0x1C, 0x000, "brald ">; } -let isReturn=1, isTerminator=1, hasDelaySlot=1, - isBarrier=1, hasCtrlDep=1, imm16=0x8 in { - def RTSD : TRET<0x2D, (outs), (ins CPURegs:$target), - "rtsd $target, 8", - [(MBlazeRet CPURegs:$target)], - IIBranch>; +let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, + hasCtrlDep=1, rd=0x10, imm16=0x8, Form=FR in { + def RTSD : TB<0x2D, (outs), (ins CPURegs:$target), + "rtsd $target, 8", + [(MBlazeRet CPURegs:$target)], + IIBranch>; } //===----------------------------------------------------------------------===// // MBlaze misc instructions //===----------------------------------------------------------------------===// -let addr = 0 in { - def NOP : TADDR<0x00, (outs), (ins), "nop ", [], IIAlu>; +let neverHasSideEffects = 1 in { + def NOP : MBlazeInst< 0x20, FRRR, (outs), (ins), "nop ", [], IIAlu>; } let usesCustomInserter = 1 in { - //class PseudoSelCC<RegisterClass RC, string asmstr>: - // MBlazePseudo<(outs RC:$D), (ins RC:$T, RC:$F, CPURegs:$CMP), asmstr, - // [(set RC:$D, (MBlazeSelectCC RC:$T, RC:$F, CPURegs:$CMP))]>; - //def Select_CC : PseudoSelCC<CPURegs, "# MBlazeSelect_CC">; - def Select_CC : MBlazePseudo<(outs CPURegs:$dst), (ins CPURegs:$T, CPURegs:$F, CPURegs:$CMP, i32imm:$CC), "; SELECT_CC PSEUDO!", @@ -512,19 +501,23 @@ let usesCustomInserter = 1 in { let rb = 0 in { - def SEXT16 : TA<0x24, 0x061, (outs CPURegs:$dst), (ins CPURegs:$src), - "sext16 $dst, $src", [], IIAlu>; - def SEXT8 : TA<0x24, 0x060, (outs CPURegs:$dst), (ins CPURegs:$src), - "sext8 $dst, $src", [], IIAlu>; - def SRL : TA<0x24, 0x041, (outs CPURegs:$dst), (ins CPURegs:$src), - "srl $dst, $src", [], IIAlu>; - def SRA : TA<0x24, 0x001, (outs CPURegs:$dst), (ins CPURegs:$src), - "sra $dst, $src", [], IIAlu>; - def SRC : TA<0x24, 0x021, (outs CPURegs:$dst), (ins CPURegs:$src), - "src $dst, $src", [], IIAlu>; + def SEXT16 : TA<0x24, 0x061, (outs CPURegs:$dst), (ins CPURegs:$src), + "sext16 $dst, $src", [], IIAlu>; + def SEXT8 : TA<0x24, 0x060, (outs CPURegs:$dst), (ins CPURegs:$src), + "sext8 $dst, $src", [], IIAlu>; + def SRL : TA<0x24, 0x041, (outs CPURegs:$dst), (ins CPURegs:$src), + "srl $dst, $src", [], IIAlu>; + def SRA : TA<0x24, 0x001, (outs CPURegs:$dst), (ins CPURegs:$src), + "sra $dst, $src", [], IIAlu>; + def SRC : TA<0x24, 0x021, (outs CPURegs:$dst), (ins CPURegs:$src), + "src $dst, $src", [], IIAlu>; } -def LEA_ADDI : EffectiveAddress<"addi $dst, ${addr:stackloc}">; +let opcode=0x08 in { + def LEA_ADDI : TB<0x08, (outs CPURegs:$dst), (ins memri:$addr), + "addi $dst, ${addr:stackloc}", + [(set CPURegs:$dst, iaddr:$addr)], IIAlu>; +} //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -610,6 +603,10 @@ def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETUGE), def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETULE), (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 6)>; +// BR instructions +def : Pat<(br bb:$T), (BRID bb:$T)>; +def : Pat<(brind CPURegs:$T), (BRD CPURegs:$T)>; + // BRCOND instructions def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETEQ), bb:$T), (BEQID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; diff --git a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp new file mode 100644 index 0000000..fec147d --- /dev/null +++ b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp @@ -0,0 +1,235 @@ +//===-- MBlazeMCCodeEmitter.cpp - Convert MBlaze 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 MBlazeMCCodeEmitter class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mblaze-emitter" +#include "MBlaze.h" +#include "MBlazeInstrInfo.h" +#include "MBlazeFixupKinds.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); + +namespace { +class MBlazeMCCodeEmitter : public MCCodeEmitter { + MBlazeMCCodeEmitter(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT + void operator=(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT + const TargetMachine &TM; + const TargetInstrInfo &TII; + MCContext &Ctx; + +public: + MBlazeMCCodeEmitter(TargetMachine &tm, MCContext &ctx) + : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) { + } + + ~MBlazeMCCodeEmitter() {} + + // getBinaryCodeForInstr - TableGen'erated function for getting the + // binary encoding for an instruction. + unsigned getBinaryCodeForInstr(const MCInst &MI) 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) const; + unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) const { + return getMachineOpValue(MI, MI.getOperand(OpIdx)); + } + + unsigned getNumFixupKinds() const { + return 2; + } + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo Infos[] = { + { "reloc_pcrel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel }, + { "reloc_pcrel_2byte", 0, 2 * 8, MCFixupKindInfo::FKF_IsPCRel } }; + + if (Kind < FirstTargetFixupKind) + return MCCodeEmitter::getFixupKindInfo(Kind); + + if (unsigned(Kind-FirstTargetFixupKind) < getNumFixupKinds()) + return Infos[Kind - FirstTargetFixupKind]; + + assert(0 && "Invalid fixup kind."); + return Infos[0]; + } + + static unsigned GetMBlazeRegNum(const MCOperand &MO) { + // FIXME: getMBlazeRegisterNumbering() is sufficient? + assert(0 && "MBlazeMCCodeEmitter::GetMBlazeRegNum() not yet implemented."); + return 0; + } + + void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const { + // The MicroBlaze uses a bit reversed format so we need to reverse the + // order of the bits. Taken from: + // http://graphics.stanford.edu/~seander/bithacks.html + C = ((C * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32; + + OS << (char)C; + ++CurByte; + } + + void EmitRawByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const { + OS << (char)C; + ++CurByte; + } + + void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte, + raw_ostream &OS) const { + assert(Size <= 8 && "size too big in emit constant" ); + + for (unsigned i = 0; i != Size; ++i) { + EmitByte(Val & 255, CurByte, OS); + Val >>= 8; + } + } + + void EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const; + + void EmitImmediate(const MCInst &MI, + unsigned opNo, MCFixupKind FixupKind, + unsigned &CurByte, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const; + + void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const; +}; + +} // end anonymous namespace + + +MCCodeEmitter *llvm::createMBlazeMCCodeEmitter(const Target &, + TargetMachine &TM, + MCContext &Ctx) { + return new MBlazeMCCodeEmitter(TM, Ctx); +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned MBlazeMCCodeEmitter::getMachineOpValue(const MCInst &MI, + const MCOperand &MO) const { + if (MO.isReg()) + return MBlazeRegisterInfo::getRegisterNumbering(MO.getReg()); + else if (MO.isImm()) + return static_cast<unsigned>(MO.getImm()); + else if (MO.isExpr() ) + return 0; // The relocation has already been recorded at this point. + else { +#ifndef NDEBUG + errs() << MO; +#endif + llvm_unreachable(0); + } + return 0; +} + +void MBlazeMCCodeEmitter:: +EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const { + int32_t val = (int32_t)imm.getImm(); + if (val > 32767 || val < -32678 ) { + EmitByte(0x0D, CurByte, OS); + EmitByte(0x00, CurByte, OS); + EmitRawByte((val >> 24) & 0xFF, CurByte, OS); + EmitRawByte((val >> 16) & 0xFF, CurByte, OS); + } +} + +void MBlazeMCCodeEmitter:: +EmitImmediate(const MCInst &MI, unsigned opNo, MCFixupKind FixupKind, + unsigned &CurByte, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const { + assert( MI.getNumOperands()>opNo && "Not enought operands for instruction" ); + + MCOperand oper = MI.getOperand(opNo); + if (oper.isImm()) { + EmitIMM( oper, CurByte, OS ); + } else if (oper.isExpr()) { + Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind)); + } +} + +void MBlazeMCCodeEmitter:: +EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups) const { + unsigned Opcode = MI.getOpcode(); + const TargetInstrDesc &Desc = TII.get(Opcode); + uint64_t TSFlags = Desc.TSFlags; + // Keep track of the current byte being emitted. + unsigned CurByte = 0; + + switch ((TSFlags & MBlazeII::FormMask)) { + default: break; + case MBlazeII::Pseudo: + // Pseudo instructions don't get encoded. + return; + + case MBlazeII::RegRegImm: + EmitImmediate( MI, 2, FK_Data_4, CurByte, OS, Fixups ); + break; + + case MBlazeII::RegImmReg: + EmitImmediate( MI, 1, FK_Data_4, CurByte, OS, Fixups ); + break; + + case MBlazeII::RegImm: + EmitImmediate( MI, 1, MCFixupKind(MBlaze::reloc_pcrel_2byte), CurByte, OS, + Fixups ); + break; + + case MBlazeII::Imm: + EmitImmediate( MI, 0, MCFixupKind(MBlaze::reloc_pcrel_4byte), CurByte, OS, + Fixups ); + break; + } + + ++MCNumEmitted; // Keep track of the # of mi's emitted + unsigned Value = getBinaryCodeForInstr(MI); + switch (Opcode) { + default: + EmitConstant(Value, 4, CurByte, OS); + break; + + case MBlaze::BRI: + case MBlaze::BRAI: + case MBlaze::BRID: + case MBlaze::BRAID: + case MBlaze::BRLID: + case MBlaze::BRALID: + MCOperand op = MI.getOperand(0); + if (op.isExpr()) { + EmitByte(0x0D, CurByte, OS); + EmitByte(0x00, CurByte, OS); + EmitRawByte(0, CurByte, OS); + EmitRawByte(0, CurByte, OS); + } + EmitConstant(Value, 4, CurByte, OS); + break; + } +} + +// FIXME: These #defines shouldn't be necessary. Instead, tblgen should +// be able to generate code emitter helpers for either variant, like it +// does for the AsmWriter. +#define MBlazeCodeEmitter MBlazeMCCodeEmitter +#define MachineInstr MCInst +#include "MBlazeGenCodeEmitter.inc" +#undef MBlazeCodeEmitter +#undef MachineInstr diff --git a/lib/Target/MBlaze/MBlazeMCInstLower.cpp b/lib/Target/MBlaze/MBlazeMCInstLower.cpp new file mode 100644 index 0000000..5a8c54e --- /dev/null +++ b/lib/Target/MBlaze/MBlazeMCInstLower.cpp @@ -0,0 +1,174 @@ +//===-- MBLazeMCInstLower.cpp - Convert MBlaze MachineInstr to an MCInst---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower MBlaze MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeMCInstLower.h" +#include "MBlazeInstrInfo.h" +#include "llvm/Constants.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallString.h" +using namespace llvm; + +MCSymbol *MBlazeMCInstLower:: +GetGlobalAddressSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + + case 0: break; + } + + return Printer.Mang->getSymbol(MO.getGlobal()); +} + +MCSymbol *MBlazeMCInstLower:: +GetExternalSymbolSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: + assert(0 && "Unknown target flag on GV operand"); + + case 0: break; + } + + return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); +} + +MCSymbol *MBlazeMCInstLower:: +GetJumpTableSymbol(const MachineOperand &MO) const { + SmallString<256> Name; + raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI" + << Printer.getFunctionNumber() << '_' + << MO.getIndex(); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + + case 0: break; + } + + // Create a symbol for the name. + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *MBlazeMCInstLower:: +GetConstantPoolIndexSymbol(const MachineOperand &MO) const { + SmallString<256> Name; + raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI" + << Printer.getFunctionNumber() << '_' + << MO.getIndex(); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + + case 0: break; + } + + // Create a symbol for the name. + return Ctx.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *MBlazeMCInstLower:: +GetBlockAddressSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: + assert(0 && "Unknown target flag on GV operand"); + + case 0: break; + } + + return Printer.GetBlockAddressSymbol(MO.getBlockAddress()); +} + +MCOperand MBlazeMCInstLower:: +LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const { + // FIXME: We would like an efficient form for this, so we don't have to do a + // lot of extra uniquing. + const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + + case 0: break; + } + + if (!MO.isJTI() && MO.getOffset()) + Expr = MCBinaryExpr::CreateAdd(Expr, + MCConstantExpr::Create(MO.getOffset(), Ctx), + Ctx); + return MCOperand::CreateExpr(Expr); +} + +void MBlazeMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + MCOperand MCOp; + switch (MO.getType()) { + default: + assert(0 && "unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) continue; + MCOp = MCOperand::CreateReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::CreateImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( + MO.getMBB()->getSymbol(), Ctx)); + break; + case MachineOperand::MO_GlobalAddress: + MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); + break; + case MachineOperand::MO_ExternalSymbol: + MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); + break; + case MachineOperand::MO_JumpTableIndex: + MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO)); + break; + case MachineOperand::MO_ConstantPoolIndex: + MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO)); + break; + case MachineOperand::MO_BlockAddress: + MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO)); + break; + case MachineOperand::MO_FPImmediate: + bool ignored; + APFloat FVal = MO.getFPImm()->getValueAPF(); + FVal.convert(APFloat::IEEEsingle, APFloat::rmTowardZero, &ignored); + + APInt IVal = FVal.bitcastToAPInt(); + uint64_t Val = *IVal.getRawData(); + MCOp = MCOperand::CreateImm(Val); + break; + } + + OutMI.addOperand(MCOp); + } +} diff --git a/lib/Target/MBlaze/MBlazeMCInstLower.h b/lib/Target/MBlaze/MBlazeMCInstLower.h new file mode 100644 index 0000000..92196f2 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeMCInstLower.h @@ -0,0 +1,50 @@ +//===-- MBlazeMCInstLower.h - Lower MachineInstr to MCInst ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZE_MCINSTLOWER_H +#define MBLAZE_MCINSTLOWER_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + class AsmPrinter; + class MCAsmInfo; + class MCContext; + class MCInst; + class MCOperand; + class MCSymbol; + class MachineInstr; + class MachineModuleInfoMachO; + class MachineOperand; + class Mangler; + + /// MBlazeMCInstLower - This class is used to lower an MachineInstr + /// into an MCInst. +class LLVM_LIBRARY_VISIBILITY MBlazeMCInstLower { + MCContext &Ctx; + Mangler &Mang; + + AsmPrinter &Printer; +public: + MBlazeMCInstLower(MCContext &ctx, Mangler &mang, AsmPrinter &printer) + : Ctx(ctx), Mang(mang), Printer(printer) {} + void Lower(const MachineInstr *MI, MCInst &OutMI) const; + + MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; + + MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const; + MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; + MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const; + MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const; + MCSymbol *GetBlockAddressSymbol(const MachineOperand &MO) const; +}; + +} + +#endif diff --git a/lib/Target/MBlaze/MBlazeRelocations.h b/lib/Target/MBlaze/MBlazeRelocations.h new file mode 100644 index 0000000..c298eda --- /dev/null +++ b/lib/Target/MBlaze/MBlazeRelocations.h @@ -0,0 +1,47 @@ +//===- MBlazeRelocations.h - MBlaze Code Relocations ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MBlaze target-specific relocation types. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZERELOCATIONS_H +#define MBLAZERELOCATIONS_H + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + namespace MBlaze { + enum RelocationType { + /// reloc_pcrel_word - PC relative relocation, add the relocated value to + /// the value already in memory, after we adjust it for where the PC is. + reloc_pcrel_word = 0, + + /// reloc_picrel_word - PIC base relative relocation, add the relocated + /// value to the value already in memory, after we adjust it for where the + /// PIC base is. + reloc_picrel_word = 1, + + /// reloc_absolute_word - absolute relocation, just add the relocated + /// value to the value already in memory. + reloc_absolute_word = 2, + + /// reloc_absolute_word_sext - absolute relocation, just add the relocated + /// value to the value already in memory. In object files, it represents a + /// value which must be sign-extended when resolving the relocation. + reloc_absolute_word_sext = 3, + + /// reloc_absolute_dword - absolute relocation, just add the relocated + /// value to the value already in memory. + reloc_absolute_dword = 4 + }; + } +} + +#endif diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/lib/Target/MBlaze/MBlazeTargetMachine.cpp index 4252953..f5b6501 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.cpp +++ b/lib/Target/MBlaze/MBlazeTargetMachine.cpp @@ -15,13 +15,51 @@ #include "MBlazeMCAsmInfo.h" #include "MBlazeTargetMachine.h" #include "llvm/PassManager.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" using namespace llvm; +static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, + MCContext &Ctx, TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll) { + Triple TheTriple(TT); + switch (TheTriple.getOS()) { + case Triple::Darwin: + llvm_unreachable("MBlaze does not support Darwin MACH-O format"); + return NULL; + case Triple::MinGW32: + case Triple::MinGW64: + case Triple::Cygwin: + case Triple::Win32: + llvm_unreachable("ARM does not support Windows COFF format"); + return NULL; + default: + return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll); + } +} + + extern "C" void LLVMInitializeMBlazeTarget() { // Register the target. RegisterTargetMachine<MBlazeTargetMachine> X(TheMBlazeTarget); RegisterAsmInfo<MBlazeMCAsmInfo> A(TheMBlazeTarget); + + // Register the MC code emitter + TargetRegistry::RegisterCodeEmitter(TheMBlazeTarget, + llvm::createMBlazeMCCodeEmitter); + + // Register the asm backend + TargetRegistry::RegisterAsmBackend(TheMBlazeTarget, + createMBlazeAsmBackend); + + // Register the object streamer + TargetRegistry::RegisterObjectStreamer(TheMBlazeTarget, + createMCStreamer); + } // DataLayout --> Big-endian, 32-bit pointer/ABI/alignment @@ -39,7 +77,7 @@ MBlazeTargetMachine(const Target &T, const std::string &TT, "f64:32:32-v64:32:32-v128:32:32-n32"), InstrInfo(*this), FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0), - TLInfo(*this), TSInfo(*this) { + TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this) { if (getRelocationModel() == Reloc::Default) { setRelocationModel(Reloc::Static); } diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.h b/lib/Target/MBlaze/MBlazeTargetMachine.h index 6a57e58..407d0e3 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.h +++ b/lib/Target/MBlaze/MBlazeTargetMachine.h @@ -19,6 +19,8 @@ #include "MBlazeISelLowering.h" #include "MBlazeSelectionDAGInfo.h" #include "MBlazeIntrinsicInfo.h" +#include "MBlazeELFWriterInfo.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" @@ -34,6 +36,7 @@ namespace llvm { MBlazeTargetLowering TLInfo; MBlazeSelectionDAGInfo TSInfo; MBlazeIntrinsicInfo IntrinsicInfo; + MBlazeELFWriterInfo ELFWriterInfo; public: MBlazeTargetMachine(const Target &T, const std::string &TT, const std::string &FS); @@ -62,6 +65,10 @@ namespace llvm { const TargetIntrinsicInfo *getIntrinsicInfo() const { return &IntrinsicInfo; } + virtual const MBlazeELFWriterInfo *getELFWriterInfo() const { + return &ELFWriterInfo; + } + // Pass Pipeline Configuration virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); diff --git a/lib/Target/MBlaze/Makefile b/lib/Target/MBlaze/Makefile index 19e508c..828bc62 100644 --- a/lib/Target/MBlaze/Makefile +++ b/lib/Target/MBlaze/Makefile @@ -14,10 +14,11 @@ TARGET = MBlaze BUILT_SOURCES = MBlazeGenRegisterInfo.h.inc MBlazeGenRegisterNames.inc \ MBlazeGenRegisterInfo.inc MBlazeGenInstrNames.inc \ MBlazeGenInstrInfo.inc MBlazeGenAsmWriter.inc \ - MBlazeGenDAGISel.inc MBlazeGenCallingConv.inc \ + MBlazeGenDAGISel.inc \ + MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \ MBlazeGenSubtarget.inc MBlazeGenIntrinsics.inc -DIRS = AsmPrinter TargetInfo +DIRS = InstPrinter TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/MBlaze/TODO b/lib/Target/MBlaze/TODO new file mode 100644 index 0000000..737f111 --- /dev/null +++ b/lib/Target/MBlaze/TODO @@ -0,0 +1,26 @@ +* Writing out ELF files is close to working but the following needs to + be examined more closely: + - ELF files are written with the wrong E_MACHINE value because + ELFObjectWriter::WriteHeader function does not yet support + target specific E_MACHINE values. + - ELF relocation records are incorrect because the function + ELFObjectWriter::RecordRelocation is hard coded for X86/X86-64. + - Relocations use 2-byte / 4-byte to terminology in reference to + the size of the immediate value being changed. The Xilinx + terminology seems to be (???) 4-byte / 8-byte in reference + to the number of bytes of instructions that are being changed. + - BRLID and like instructions are always assumed to use a 4-byte + immediate value for the relocation and BEQID and like instructions + are always assumed to use a 2-byte immediate value for the relocation. + I think this means that conditional branches like BEQID can only + branch += 32768 bytes (~8192 instructions). We should allow conditional + branches to use 4-byte relocations but I'm not sure how to do that + right now. + +* Code generation seems to work relatively well now but the following + needs to be examined more closely: + - The stack layout needs to be examined to make sure it meets + the standard, especially in regards to var arg functions. + - The delay slot filler is ad hoc but seems to work. Load and + store instructions were prevented from being moved to delay + slots but I'm not sure that is necessary. diff --git a/lib/Target/MBlaze/TargetInfo/CMakeLists.txt b/lib/Target/MBlaze/TargetInfo/CMakeLists.txt index 5afb14d..40696f6 100644 --- a/lib/Target/MBlaze/TargetInfo/CMakeLists.txt +++ b/lib/Target/MBlaze/TargetInfo/CMakeLists.txt @@ -1,4 +1,5 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/.. ) add_llvm_library(LLVMMBlazeInfo MBlazeTargetInfo.cpp |