diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/Alpha/Alpha.h | 41 | ||||
-rw-r--r-- | lib/Target/Alpha/Alpha.td | 56 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaAsmPrinter.cpp | 319 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaISelPattern.cpp | 797 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaInstrBuilder.h | 0 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaInstrFormats.td | 109 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaInstrInfo.cpp | 43 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaInstrInfo.h | 42 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaInstrInfo.td | 295 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaRegisterInfo.cpp | 268 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaRegisterInfo.h | 57 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaRegisterInfo.td | 93 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaTargetMachine.cpp | 111 | ||||
-rw-r--r-- | lib/Target/Alpha/AlphaTargetMachine.h | 54 | ||||
-rw-r--r-- | lib/Target/Alpha/Makefile | 20 |
15 files changed, 2305 insertions, 0 deletions
diff --git a/lib/Target/Alpha/Alpha.h b/lib/Target/Alpha/Alpha.h new file mode 100644 index 0000000..04daaff --- /dev/null +++ b/lib/Target/Alpha/Alpha.h @@ -0,0 +1,41 @@ +//===-- Alpha.h - Top-level interface for Alpha representation -*- C++ -*-// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the LLVM +// Alpha back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_ALPHA_H +#define TARGET_ALPHA_H + +#include <iosfwd> + +namespace llvm { + + class FunctionPass; + class TargetMachine; + + FunctionPass *createAlphaSimpleInstructionSelector(TargetMachine &TM); + FunctionPass *createAlphaCodePrinterPass(std::ostream &OS, + TargetMachine &TM); + FunctionPass *createAlphaPatternInstructionSelector(TargetMachine &TM); + +} // end namespace llvm; + +// Defines symbolic names for Alpha registers. This defines a mapping from +// register name to register number. +// +#include "AlphaGenRegisterNames.inc" + +// Defines symbolic names for the Alpha instructions. +// +#include "AlphaGenInstrNames.inc" + +#endif diff --git a/lib/Target/Alpha/Alpha.td b/lib/Target/Alpha/Alpha.td new file mode 100644 index 0000000..e48bea1 --- /dev/null +++ b/lib/Target/Alpha/Alpha.td @@ -0,0 +1,56 @@ +//===- Alpha.td - Describe the Alpha Target Machine ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +// Get the target-independent interfaces which we are implementing... +// +include "../Target.td" + +//Alpha is little endian + +//===----------------------------------------------------------------------===// +// Register File Description +//===----------------------------------------------------------------------===// + +include "AlphaRegisterInfo.td" + +//===----------------------------------------------------------------------===// +// Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "AlphaInstrInfo.td" + +def AlphaInstrInfo : InstrInfo { + let PHIInst = PHI; + + // Define how we want to layout our target-specific information field. + // let TSFlagsFields = []; + // let TSFlagsShifts = []; +} + +def Alpha : Target { + // Pointers on Alpha are 64-bits in size. + let PointerType = i64; + + let CalleeSavedRegisters = + //saved regs + [R9, R10, R11, R12, R13, R14, + //Frame pointer + R15, + //return address + R26, + //Stack Pointer + R30, + F2, F3, F4, F5, F6, F7, F8, F9]; + + // Pull in Instruction Info: + let InstructionSet = AlphaInstrInfo; +} diff --git a/lib/Target/Alpha/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AlphaAsmPrinter.cpp new file mode 100644 index 0000000..85feb9d --- /dev/null +++ b/lib/Target/Alpha/AlphaAsmPrinter.cpp @@ -0,0 +1,319 @@ +//===-- AlphaAsmPrinter.cpp - Alpha LLVM assembly writer --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and 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 Alpha assembly language. +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +#include "AlphaInstrInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/AsmPrinter.h" + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/MRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" + +#include "llvm/Support/Mangler.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include <cctype> +using namespace llvm; + +namespace { + Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); + + struct AlphaAsmPrinter : public AsmPrinter { + + /// Unique incrementer for label values for referencing Global values. + /// + unsigned LabelNumber; + + AlphaAsmPrinter(std::ostream &o, TargetMachine &tm) + : AsmPrinter(o, tm), LabelNumber(0) + { } + + /// We name each basic block in a Function with a unique number, so + /// that we can consistently refer to them later. This is cleared + /// at the beginning of each call to runOnMachineFunction(). + /// + typedef std::map<const Value *, unsigned> ValueMapTy; + ValueMapTy NumberForBB; + + virtual const char *getPassName() const { + return "Alpha Assembly Printer"; + } + bool printInstruction(const MachineInstr *MI); + void printOp(const MachineOperand &MO, bool IsCallOp = false); + void printConstantPool(MachineConstantPool *MCP); + void printOperand(const MachineInstr *MI, int opNum, MVT::ValueType VT); + void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true); + void printMachineInstruction(const MachineInstr *MI); + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); + }; +} // end of anonymous namespace + +/// createAlphaCodePrinterPass - Returns a pass that prints the Alpha +/// assembly code for a MachineFunction to the given output stream, +/// using the given target machine description. This should work +/// regardless of whether the function is in SSA form. +/// +FunctionPass *llvm::createAlphaCodePrinterPass (std::ostream &o, + TargetMachine &tm) { + return new AlphaAsmPrinter(o, tm); +} + +#include "AlphaGenAsmWriter.inc" + +void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum, MVT::ValueType VT) +{ + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.getType() == MachineOperand::MO_MachineRegister) { + assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??"); + O << LowercaseString(TM.getRegisterInfo()->get(MO.getReg()).Name); + } else if (MO.isImmediate()) { + O << MO.getImmedValue(); + } else { + printOp(MO); + } +} + + +void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) { + const MRegisterInfo &RI = *TM.getRegisterInfo(); + int new_symbol; + + switch (MO.getType()) { + case MachineOperand::MO_VirtualRegister: + if (Value *V = MO.getVRegValueOrNull()) { + O << "<" << V->getName() << ">"; + return; + } + // FALLTHROUGH + case MachineOperand::MO_MachineRegister: + case MachineOperand::MO_CCRegister: + O << LowercaseString(RI.get(MO.getReg()).Name); + return; + + case MachineOperand::MO_SignExtendedImmed: + case MachineOperand::MO_UnextendedImmed: + std::cerr << "printOp() does not handle immediate values\n"; + abort(); + return; + + case MachineOperand::MO_PCRelativeDisp: + std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs"; + abort(); + return; + + case MachineOperand::MO_MachineBasicBlock: { + MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); + O << "$LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) + << "_" << MBBOp->getNumber() << "\t" << CommentString << " " + << MBBOp->getBasicBlock()->getName(); + return; + } + + case MachineOperand::MO_ConstantPoolIndex: + O << "$CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex(); + return; + + case MachineOperand::MO_ExternalSymbol: + O << MO.getSymbolName(); + return; + + case MachineOperand::MO_GlobalAddress: + //std::cerr << "Global Addresses? Are you kidding?\n" + //abort(); + O << Mang->getValueName(MO.getGlobal()); + return; + + default: + O << "<unknown operand type: " << MO.getType() << ">"; + return; + } +} + +/// printMachineInstruction -- Print out a single Alpha MI to +/// the current output stream. +/// +void AlphaAsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + if (printInstruction(MI)) + return; // Printer was automatically generated + + assert(0 && "Unhandled instruction in asm writer!"); + abort(); + return; +} + + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + setupMachineFunction(MF); + O << "\n\n"; + + if (CurrentFnName.compare("main") == 0) + { + O << "\n\n#HACK\n\t.text\n\t.ent __main\n__main:\n\tret $31,($26),1\n\t.end __main\n#ENDHACK\n\n"; + } + + // Print out constants referenced by the function + printConstantPool(MF.getConstantPool()); + + // Print out labels for the function. + O << "\t.text\n"; + emitAlignment(2); + O << "\t.globl\t" << CurrentFnName << "\n"; + O << "\t.ent\t" << CurrentFnName << "\n"; + + O << CurrentFnName << ":\n"; + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + O << "$LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" + << CommentString << " " << I->getBasicBlock()->getName() << "\n"; + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << "\t"; + printMachineInstruction(II); + } + } + ++LabelNumber; + + O << "\t.end\t" << CurrentFnName << "\n"; + + // We didn't modify anything. + return false; +} + + +/// printConstantPool - Print to the current output stream assembly +/// representations of the constants in the constant pool MCP. This is +/// used to print out constants which have been "spilled to memory" by +/// the code generator. +/// +void AlphaAsmPrinter::printConstantPool(MachineConstantPool *MCP) { + const std::vector<Constant*> &CP = MCP->getConstants(); + const TargetData &TD = TM.getTargetData(); + + if (CP.empty()) return; + + abort(); +// for (unsigned i = 0, e = CP.size(); i != e; ++i) { +// O << "\t.section\t.rodata\n"; +// emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType())); +// O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString +// << *CP[i] << "\n"; +// //emitGlobalConstant(CP[i]); +// } +} + +bool AlphaAsmPrinter::doInitialization(Module &M) +{ + AsmPrinter::doInitialization(M); + O << "\t.arch ev56\n"; + return false; +} + + +// SwitchSection - Switch to the specified section of the executable if we are +// not already in it! +// +static void SwitchSection(std::ostream &OS, std::string &CurSection, + const char *NewSection) { + if (CurSection != NewSection) { + CurSection = NewSection; + if (!CurSection.empty()) + OS << "\t" << NewSection << "\n"; + } +} + +bool AlphaAsmPrinter::doFinalization(Module &M) { + const TargetData &TD = TM.getTargetData(); + std::string CurSection; + + for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) + if (I->hasInitializer()) { // External global require no code + O << "\n\n"; + std::string name = Mang->getValueName(I); + Constant *C = I->getInitializer(); + unsigned Size = TD.getTypeSize(C->getType()); + unsigned Align = TD.getTypeAlignmentShift(C->getType()); + + if (C->isNullValue() && + (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || + I->hasWeakLinkage() /* FIXME: Verify correct */)) { + SwitchSection(O, CurSection, ".data"); + if (I->hasInternalLinkage()) + O << "\t.local " << name << "\n"; + + O << "\t.comm " << name << "," << TD.getTypeSize(C->getType()) + << "," << (1 << Align); + O << "\t\t# "; + WriteAsOperand(O, I, true, true, &M); + O << "\n"; + } else { + switch (I->getLinkage()) { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. + // Nonnull linkonce -> weak + O << "\t.weak " << name << "\n"; + SwitchSection(O, CurSection, ""); + O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; + break; + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol + O << "\t.globl " << name << "\n"; + // FALL THROUGH + case GlobalValue::InternalLinkage: + if (C->isNullValue()) + SwitchSection(O, CurSection, ".bss"); + else + SwitchSection(O, CurSection, ".data"); + break; + case GlobalValue::GhostLinkage: + std::cerr << "GhostLinkage cannot appear in X86AsmPrinter!\n"; + abort(); + } + + emitAlignment(Align); + O << "\t.type " << name << ",@object\n"; + O << "\t.size " << name << "," << Size << "\n"; + O << name << ":\t\t\t\t# "; + WriteAsOperand(O, I, true, true, &M); + O << " = "; + WriteAsOperand(O, C, false, false, &M); + O << "\n"; + emitGlobalConstant(C); + } + } + + AsmPrinter::doFinalization(M); + return false; +} diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp new file mode 100644 index 0000000..4431d8f --- /dev/null +++ b/lib/Target/Alpha/AlphaISelPattern.cpp @@ -0,0 +1,797 @@ +//===-- AlphaISelPattern.cpp - A pattern matching inst selector for Alpha -----===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a pattern matching instruction selector for Alpha. +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +//#include "X86InstrBuilder.h" +#include "AlphaRegisterInfo.h" +#include "llvm/Constants.h" // FIXME: REMOVE +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/SSARegMap.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/ADT/Statistic.h" +#include <set> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// AlphaTargetLowering - Alpha Implementation of the TargetLowering interface +namespace { + class AlphaTargetLowering : public TargetLowering { + int VarArgsFrameIndex; // FrameIndex for start of varargs area. + unsigned GP; //GOT vreg + public: + AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) { + // Set up the TargetLowering object. + addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass); + addRegisterClass(MVT::f64, Alpha::FPRCRegisterClass); + + setOperationAction(ISD::EXTLOAD , MVT::i1 , Expand); + setOperationAction(ISD::EXTLOAD , MVT::i8 , Expand); + setOperationAction(ISD::EXTLOAD , MVT::i16 , Expand); + setOperationAction(ISD::ZEXTLOAD , MVT::i1 , Expand); + setOperationAction(ISD::ZEXTLOAD , MVT::i8 , Expand); + setOperationAction(ISD::ZEXTLOAD , MVT::i16 , Expand); + setOperationAction(ISD::ZEXTLOAD , MVT::i32 , Expand); + setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand); + setOperationAction(ISD::SEXTLOAD , MVT::i8 , Expand); + setOperationAction(ISD::SEXTLOAD , MVT::i16 , Expand); + + computeRegisterProperties(); + + // setOperationUnsupported(ISD::MUL, MVT::i8); + // setOperationUnsupported(ISD::SELECT, MVT::i1); + // setOperationUnsupported(ISD::SELECT, MVT::i8); + + // addLegalFPImmediate(+0.0); // FLD0 + // addLegalFPImmediate(+1.0); // FLD1 + // addLegalFPImmediate(-0.0); // FLD0/FCHS + // addLegalFPImmediate(-1.0); // FLD1/FCHS + } + + /// LowerArguments - This hook must be implemented to indicate how we should + /// lower the arguments for the specified function, into the specified DAG. + virtual std::vector<SDOperand> + LowerArguments(Function &F, SelectionDAG &DAG); + + /// LowerCallTo - This hook lowers an abstract call to a function into an + /// actual call. + virtual std::pair<SDOperand, SDOperand> + LowerCallTo(SDOperand Chain, const Type *RetTy, SDOperand Callee, + ArgListTy &Args, SelectionDAG &DAG); + + virtual std::pair<SDOperand, SDOperand> + LowerVAStart(SDOperand Chain, SelectionDAG &DAG); + + virtual std::pair<SDOperand,SDOperand> + LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, + const Type *ArgTy, SelectionDAG &DAG); + + virtual std::pair<SDOperand, SDOperand> + LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, + SelectionDAG &DAG); + + void restoreGP(MachineBasicBlock* BB) + { + BuildMI(BB, Alpha::BIS, 2, Alpha::R29).addReg(GP).addReg(GP); + } + }; +} + +//http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/AA-PY8AC-TET1_html/callCH3.html#BLOCK21 + +//For now, just use variable size stack frame format + +//In a standard call, the first six items are passed in registers $16 +//- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details +//of argument-to-register correspondence.) The remaining items are +//collected in a memory argument list that is a naturally aligned +//array of quadwords. In a standard call, this list, if present, must +//be passed at 0(SP). +//7 ... n 0(SP) ... (n-7)*8(SP) + +std::vector<SDOperand> +AlphaTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) +{ + std::vector<SDOperand> ArgValues; + + // //#define FP $15 + // //#define RA $26 + // //#define PV $27 + // //#define GP $29 + // //#define SP $30 + + // assert(0 && "TODO"); + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + GP = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64)); + MachineBasicBlock& BB = MF.front(); + + //Handle the return address + //BuildMI(&BB, Alpha::IDEF, 0, Alpha::R26); + + unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18, + Alpha::R19, Alpha::R20, Alpha::R21}; + std::vector<unsigned> argVreg; + + int count = 0; + for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I) + { + ++count; + assert(count <= 6 && "More than 6 args not supported"); + assert(getValueType(I->getType()) != MVT::f64 && "No floats yet"); + BuildMI(&BB, Alpha::IDEF, 0, args[count - 1]); + argVreg.push_back(MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::i64))); + } + + BuildMI(&BB, Alpha::IDEF, 0, Alpha::R29); + BuildMI(&BB, Alpha::BIS, 2, GP).addReg(Alpha::R29).addReg(Alpha::R29); + count = 0; + for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I) + { + BuildMI(&BB, Alpha::BIS, 2, argVreg[count]).addReg(args[count]).addReg(args[count]); + + SDOperand argt, newroot; + switch (getValueType(I->getType())) + { + case MVT::i64: + argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot()); + break; + case MVT::i32: + argt = newroot = DAG.getCopyFromReg(argVreg[count], MVT::i32, DAG.getRoot()); + break; + default: + newroot = DAG.getCopyFromReg(argVreg[count], MVT::i64, DAG.getRoot()); + argt = DAG.getNode(ISD::TRUNCATE, getValueType(I->getType()), newroot); + } + DAG.setRoot(newroot.getValue(1)); + ArgValues.push_back(argt); + ++count; + } + return ArgValues; +} + +std::pair<SDOperand, SDOperand> +AlphaTargetLowering::LowerCallTo(SDOperand Chain, + const Type *RetTy, SDOperand Callee, + ArgListTy &Args, SelectionDAG &DAG) { + int NumBytes = 0; + Chain = DAG.getNode(ISD::ADJCALLSTACKDOWN, MVT::Other, Chain, + DAG.getConstant(NumBytes, getPointerTy())); + std::vector<SDOperand> args_to_use; + for (unsigned i = 0, e = Args.size(); i != e; ++i) + { + switch (getValueType(Args[i].second)) { + default: assert(0 && "Unexpected ValueType for argument!"); + case MVT::i1: + case MVT::i8: + case MVT::i16: + case MVT::i32: + // Promote the integer to 64 bits. If the input type is signed use a + // sign extend, otherwise use a zero extend. + if (Args[i].second->isSigned()) + Args[i].first = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first); + else + Args[i].first = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first); + break; + case MVT::i64: + break; + } + args_to_use.push_back(Args[i].first); + } + + std::vector<MVT::ValueType> RetVals; + MVT::ValueType RetTyVT = getValueType(RetTy); + if (RetTyVT != MVT::isVoid) + RetVals.push_back(RetTyVT); + RetVals.push_back(MVT::Other); + + SDOperand TheCall = SDOperand(DAG.getCall(RetVals, Chain, Callee, args_to_use), 0); + Chain = TheCall.getValue(RetTyVT != MVT::isVoid); + Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain, + DAG.getConstant(NumBytes, getPointerTy())); + return std::make_pair(TheCall, Chain); +} + +std::pair<SDOperand, SDOperand> +AlphaTargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG) { + //vastart just returns the address of the VarArgsFrameIndex slot. + return std::make_pair(DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64), Chain); +} + +std::pair<SDOperand,SDOperand> AlphaTargetLowering:: +LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList, + const Type *ArgTy, SelectionDAG &DAG) { + abort(); +} + + +std::pair<SDOperand, SDOperand> AlphaTargetLowering:: +LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, + SelectionDAG &DAG) { + abort(); +} + + + + + +namespace { + + //===--------------------------------------------------------------------===// + /// ISel - Alpha specific code to select Alpha machine instructions for + /// SelectionDAG operations. + /// + class ISel : public SelectionDAGISel { + + /// AlphaLowering - This object fully describes how to lower LLVM code to an + /// Alpha-specific SelectionDAG. + AlphaTargetLowering AlphaLowering; + + + /// ExprMap - As shared expressions are codegen'd, we keep track of which + /// vreg the value is produced in, so we only emit one copy of each compiled + /// tree. + std::map<SDOperand, unsigned> ExprMap; + std::set<SDOperand> LoweredTokens; + + public: + ISel(TargetMachine &TM) : SelectionDAGISel(AlphaLowering), AlphaLowering(TM) { + } + + /// InstructionSelectBasicBlock - This callback is invoked by + /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. + virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { + // Codegen the basic block. + Select(DAG.getRoot()); + + // Clear state used for selection. + ExprMap.clear(); + LoweredTokens.clear(); + } + + unsigned SelectExpr(SDOperand N); + void Select(SDOperand N); + }; +} + +unsigned ISel::SelectExpr(SDOperand N) { + unsigned Result; + unsigned Tmp1, Tmp2, Tmp3; + unsigned Opc = 0; + + SDNode *Node = N.Val; + + unsigned &Reg = ExprMap[N]; + if (Reg) return Reg; + + if (N.getOpcode() != ISD::CALL) + Reg = Result = (N.getValueType() != MVT::Other) ? + MakeReg(N.getValueType()) : 1; + else { + // If this is a call instruction, make sure to prepare ALL of the result + // values as well as the chain. + if (Node->getNumValues() == 1) + Reg = Result = 1; // Void call, just a chain. + else { + Result = MakeReg(Node->getValueType(0)); + ExprMap[N.getValue(0)] = Result; + for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) + ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); + ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1; + } + } + + switch (N.getOpcode()) { + default: + Node->dump(); + assert(0 && "Node not handled!\n"); + + case ISD::FrameIndex: + Tmp1 = cast<FrameIndexSDNode>(N)->getIndex(); + BuildMI(BB, Alpha::LDA, 2, Result).addImm(Tmp1 * 8).addReg(Alpha::R30); + return Result; + + case ISD::EXTLOAD: + case ISD::SEXTLOAD: + // Make sure we generate both values. + if (Result != 1) + ExprMap[N.getValue(1)] = 1; // Generate the token + else + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + Select(Node->getOperand(0)); // chain + Tmp1 = SelectExpr(Node->getOperand(1)); + switch(Node->getValueType(0)) { + default: assert(0 && "Unknown type to sign extend to."); + case MVT::i64: + switch (cast<MVTSDNode>(Node)->getExtraValueType()) { + default: + assert(0 && "Bad sign extend!"); + case MVT::i32: + BuildMI(BB, Alpha::LDL, 2, Result).addImm(0).addReg(Tmp1); + break; + case MVT::i16: + BuildMI(BB, Alpha::LDW, 2, Result).addImm(0).addReg(Tmp1); + break; + case MVT::i8: + BuildMI(BB, Alpha::LDB, 2, Result).addImm(0).addReg(Tmp1); + break; + } + break; + } + return Result; + + case ISD::GlobalAddress: + AlphaLowering.restoreGP(BB); + BuildMI(BB, Alpha::LOAD_ADDR, 1, Result) + .addGlobalAddress(cast<GlobalAddressSDNode>(N)->getGlobal()); + return Result; + + case ISD::CALL: + { + Select(N.getOperand(0)); + + // The chain for this call is now lowered. + ExprMap.insert(std::make_pair(N.getValue(Node->getNumValues()-1), 1)); + + //grab the arguments + std::vector<unsigned> argvregs; + assert(Node->getNumOperands() < 8 && "Only 6 args supported"); + for(int i = 2, e = Node->getNumOperands(); i < e; ++i) + { + argvregs.push_back(SelectExpr(N.getOperand(i))); + } + for(int i = 0, e = argvregs.size(); i < e; ++i) + { + unsigned args[] = {Alpha::R16, Alpha::R17, Alpha::R18, + Alpha::R19, Alpha::R20, Alpha::R21}; + + BuildMI(BB, Alpha::BIS, 2, args[i]).addReg(argvregs[i]).addReg(argvregs[i]); + } + + //build the right kind of call + if (GlobalAddressSDNode *GASD = + dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) + { + Select(N.getOperand(0)); + AlphaLowering.restoreGP(BB); + BuildMI(BB, Alpha::CALL, 1).addGlobalAddress(GASD->getGlobal(),true); + } + else if (ExternalSymbolSDNode *ESSDN = + dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) + { + Select(N.getOperand(0)); + AlphaLowering.restoreGP(BB); + BuildMI(BB, Alpha::CALL, 0).addExternalSymbol(ESSDN->getSymbol(), true); + } + else { + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::CALL, 1).addReg(Tmp1); + AlphaLowering.restoreGP(BB); + } + + //push the result into a virtual register + // if (Result != 1) + // BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0); + + switch (Node->getValueType(0)) { + default: assert(0 && "Unknown value type for call result!"); + case MVT::Other: return 1; + case MVT::i1: + case MVT::i8: + case MVT::i16: + case MVT::i32: + case MVT::i64: + BuildMI(BB, Alpha::BIS, 2, Result).addReg(Alpha::R0).addReg(Alpha::R0); + break; + } + return Result+N.ResNo; + } + + case ISD::SIGN_EXTEND: + { + std::cerr << "DestT: " << N.getValueType() << "\n"; + std::cerr << "SrcT: " << N.getOperand(0).getValueType() << "\n"; + assert(0 && "Sign Extend not there yet"); + return Result; + } + case ISD::SIGN_EXTEND_INREG: + { + Tmp1 = SelectExpr(N.getOperand(0)); + MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node); + std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n"; + switch(MVN->getExtraValueType()) + { + default: + assert(0 && "Sign Extend InReg not there yet"); + break; + case MVT::i32: + { + Tmp2 = MakeReg(MVT::i64); + unsigned Tmp3 = MakeReg(MVT::i64); + BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(16); + BuildMI(BB, Alpha::SL, 2, Tmp3).addReg(Tmp1).addReg(Tmp2); + BuildMI(BB, Alpha::SRA, 2, Result).addReg(Tmp3).addReg(Tmp2); + break; + } + case MVT::i16: + BuildMI(BB, Alpha::SEXTW, 1, Result).addReg(Tmp1); + break; + case MVT::i8: + BuildMI(BB, Alpha::SEXTB, 1, Result).addReg(Tmp1); + break; + } + return Result; + } + case ISD::ZERO_EXTEND_INREG: + { + Tmp1 = SelectExpr(N.getOperand(0)); + MVTSDNode* MVN = dyn_cast<MVTSDNode>(Node); + std::cerr << "SrcT: " << MVN->getExtraValueType() << "\n"; + switch(MVN->getExtraValueType()) + { + default: + assert(0 && "Zero Extend InReg not there yet"); + break; + case MVT::i32: + { + Tmp2 = MakeReg(MVT::i64); + BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xf0); + BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + } + case MVT::i16: + Tmp2 = MakeReg(MVT::i64); + BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xfc); + BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + case MVT::i8: + Tmp2 = MakeReg(MVT::i64); + BuildMI(BB, Alpha::LOAD_IMM, 1, Tmp2).addImm(0xfe); + BuildMI(BB, Alpha::ZAP, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + } + return Result; + } + + case ISD::SETCC: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) { + if (MVT::isInteger(SetCC->getOperand(0).getValueType())) { + switch (SetCC->getCondition()) { + default: assert(0 && "Unknown integer comparison!"); + case ISD::SETEQ: + BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + case ISD::SETGT: + BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp2).addReg(Tmp1); + break; + case ISD::SETGE: + BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp2).addReg(Tmp1); + break; + case ISD::SETLT: + BuildMI(BB, Alpha::CMPLT, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + case ISD::SETLE: + BuildMI(BB, Alpha::CMPLE, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + case ISD::SETNE: + { + unsigned Tmp3 = MakeReg(MVT::i64); + BuildMI(BB, Alpha::CMPEQ, 2, Tmp3).addReg(Tmp1).addReg(Tmp2); + BuildMI(BB, Alpha::CMPEQ, 2, Result).addReg(Tmp3).addReg(Alpha::R31); + break; + } + case ISD::SETULT: + BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + case ISD::SETUGT: + BuildMI(BB, Alpha::CMPULT, 2, Result).addReg(Tmp2).addReg(Tmp1); + break; + case ISD::SETULE: + BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + case ISD::SETUGE: + BuildMI(BB, Alpha::CMPULE, 2, Result).addReg(Tmp2).addReg(Tmp1); + break; + } + } + else + assert(0 && "only integer"); + } + else + assert(0 && "Not a setcc in setcc"); + + return Result; + + case ISD::CopyFromReg: + { + if (Result == 1) + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + SDOperand Chain = N.getOperand(0); + + Select(Chain); + unsigned r = dyn_cast<RegSDNode>(Node)->getReg(); + //std::cerr << "CopyFromReg " << Result << " = " << r << "\n"; + BuildMI(BB, Alpha::BIS, 2, Result).addReg(r).addReg(r); + return Result; + } + + case ISD::ADD: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::ADDQ, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + case ISD::SUB: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::AND: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::AND, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + case ISD::OR: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::BIS, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + case ISD::XOR: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::XOR, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::MUL: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::MULQ, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + case ISD::UREM: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::REMQU, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::SELECT: + { + Tmp2 = SelectExpr(N.getOperand(1)); //Use if TRUE + Tmp3 = SelectExpr(N.getOperand(2)); //Use if FALSE + Tmp1 = SelectExpr(N.getOperand(0)); //Cond + // Get the condition into the zero flag. + unsigned dummy = MakeReg(MVT::i64); + BuildMI(BB, Alpha::BIS, 2, dummy).addReg(Tmp3).addReg(Tmp3); + BuildMI(BB, Alpha::CMOVEQ, 2, Result).addReg(Tmp2).addReg(Tmp1); + return Result; + } + + case ISD::SHL: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::SL, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + case ISD::SRL: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::SRL, 1, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + case ISD::SRA: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::SRA, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::Constant: + { + long val = cast<ConstantSDNode>(N)->getValue(); + BuildMI(BB, Alpha::LOAD_IMM, 1, Result).addImm(val); + return Result; + } + + + + case ISD::LOAD: + { + // Make sure we generate both values. + if (Result != 1) + ExprMap[N.getValue(1)] = 1; // Generate the token + else + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + SDOperand Chain = N.getOperand(0); + SDOperand Address = N.getOperand(1); + + if (Address.getOpcode() == ISD::GlobalAddress) + { + Select(Chain); + AlphaLowering.restoreGP(BB); + BuildMI(BB, Alpha::LOAD, 1, Result).addGlobalAddress(cast<GlobalAddressSDNode>(Address)->getGlobal()); + } + else + { + Select(Chain); + Tmp2 = SelectExpr(Address); + BuildMI(BB, Alpha::LDQ, 2, Result).addImm(0).addReg(Tmp2); + } + return Result; + } + } + + return 0; +} + +void ISel::Select(SDOperand N) { + unsigned Tmp1, Tmp2, Opc; + + // FIXME: Disable for our current expansion model! + if (/*!N->hasOneUse() &&*/ !LoweredTokens.insert(N).second) + return; // Already selected. + + SDNode *Node = N.Val; + + switch (N.getOpcode()) { + + default: + Node->dump(); std::cerr << "\n"; + assert(0 && "Node not handled yet!"); + + case ISD::BRCOND: { + MachineBasicBlock *Dest = + cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock(); + + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Alpha::BNE, 2).addReg(Tmp1).addMBB(Dest); + return; + } + + case ISD::BR: { + MachineBasicBlock *Dest = + cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock(); + + Select(N.getOperand(0)); + BuildMI(BB, Alpha::BR, 1, Alpha::R31).addMBB(Dest); + return; + } + + case ISD::ImplicitDef: + Select(N.getOperand(0)); + BuildMI(BB, Alpha::IDEF, 0, cast<RegSDNode>(N)->getReg()); + return; + + case ISD::EntryToken: return; // Noop + + case ISD::TokenFactor: + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + Select(Node->getOperand(i)); + + //N.Val->dump(); std::cerr << "\n"; + //assert(0 && "Node not handled yet!"); + + return; + + case ISD::CopyToReg: + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + Tmp2 = cast<RegSDNode>(N)->getReg(); + + if (Tmp1 != Tmp2) { + BuildMI(BB, Alpha::BIS, 2, Tmp2).addReg(Tmp1).addReg(Tmp1); + } + return; + + case ISD::RET: + switch (N.getNumOperands()) { + default: + std::cerr << N.getNumOperands() << "\n"; + for (unsigned i = 0; i < N.getNumOperands(); ++i) + std::cerr << N.getOperand(i).getValueType() << "\n"; + assert(0 && "Unknown return instruction!"); + case 2: + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + switch (N.getOperand(1).getValueType()) { + default: assert(0 && "All other types should have been promoted!!"); + case MVT::i64: + BuildMI(BB, Alpha::BIS, 2, Alpha::R0).addReg(Tmp1).addReg(Tmp1); + break; + } + break; + case 1: + Select(N.getOperand(0)); + break; + } + //Tmp2 = AlphaLowering.getRetAddr(); + //BuildMI(BB, Alpha::BIS, 2, Alpha::R26).addReg(Tmp2).addReg(Tmp2); + BuildMI(BB, Alpha::RETURN, 0); // Just emit a 'ret' instruction + return; + + case ISD::STORE: + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); //value + if (N.getOperand(2).getOpcode() == ISD::GlobalAddress) + { + AlphaLowering.restoreGP(BB); + BuildMI(BB, Alpha::STORE, 2).addReg(Tmp1).addGlobalAddress(cast<GlobalAddressSDNode>(N.getOperand(2))->getGlobal()); + } + else + { + Tmp2 = SelectExpr(N.getOperand(2)); //address + BuildMI(BB, Alpha::STQ, 3).addReg(Tmp1).addImm(0).addReg(Tmp2); + } + return; + + case ISD::EXTLOAD: + case ISD::SEXTLOAD: + case ISD::ZEXTLOAD: + case ISD::LOAD: + case ISD::CopyFromReg: + case ISD::CALL: +// case ISD::DYNAMIC_STACKALLOC: + SelectExpr(N); + return; + + + case ISD::TRUNCSTORE: { // truncstore chain, val, ptr :storety + MVT::ValueType StoredTy = cast<MVTSDNode>(Node)->getExtraValueType(); + assert(StoredTy != MVT::i64 && "Unsupported TRUNCSTORE for this target!"); + + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + Tmp2 = SelectExpr(N.getOperand(2)); + + switch (StoredTy) { + default: assert(0 && "Unhandled Type"); break; + case MVT::i8: Opc = Alpha::STB; break; + case MVT::i16: Opc = Alpha::STW; break; + case MVT::i32: Opc = Alpha::STL; break; + } + + BuildMI(BB, Opc, 2).addReg(Tmp1).addImm(0).addReg(Tmp2); + return; + } + + case ISD::ADJCALLSTACKDOWN: + case ISD::ADJCALLSTACKUP: + Select(N.getOperand(0)); + Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue(); + + Opc = N.getOpcode() == ISD::ADJCALLSTACKDOWN ? Alpha::ADJUSTSTACKDOWN : + Alpha::ADJUSTSTACKUP; + BuildMI(BB, Opc, 1).addImm(Tmp1); + return; + } + assert(0 && "Should not be reached!"); +} + + +/// createAlphaPatternInstructionSelector - This pass converts an LLVM function +/// into a machine code representation using pattern matching and a machine +/// description file. +/// +FunctionPass *llvm::createAlphaPatternInstructionSelector(TargetMachine &TM) { + return new ISel(TM); +} diff --git a/lib/Target/Alpha/AlphaInstrBuilder.h b/lib/Target/Alpha/AlphaInstrBuilder.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/Target/Alpha/AlphaInstrBuilder.h diff --git a/lib/Target/Alpha/AlphaInstrFormats.td b/lib/Target/Alpha/AlphaInstrFormats.td new file mode 100644 index 0000000..e7def75 --- /dev/null +++ b/lib/Target/Alpha/AlphaInstrFormats.td @@ -0,0 +1,109 @@ +//===- AlphaInstrFormats.td - Alpha Instruction Formats --*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//3.3: +//Memory +//Branch +//Operate +//Floating-point +//PALcode + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// + +class InstAlpha<bits<6> op, dag OL, string asmstr> : Instruction { // Alpha instruction baseline + field bits<32> Inst; +// let Name = asmstr; + let Namespace = "Alpha"; + let OperandList = OL; + let AsmString = asmstr; + + + let Inst{31-26} = op; +} + +//3.3.1 +class MForm<bits<6> opcode, dag OL, string asmstr> : InstAlpha<opcode, OL, asmstr> { + bits<5> Ra; + bits<5> Rb; + bits<16> disp; + + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-0} = disp; +} + +//3.3.2 +let isBranch = 1, isTerminator = 1 in +class BForm<bits<6> opcode, dag OL, string asmstr> : InstAlpha<opcode, OL, asmstr> { + bits<5> Ra; + bits<21> disp; + + let Inst{25-21} = Ra; + let Inst{20-0} = disp; +} + +//3.3.3 +class OForm<bits<6> opcode, bits<7> fun, dag OL, string asmstr> : InstAlpha<opcode, OL, asmstr> { + bits<5> Ra; + bits<5> Rb; + bits<3> SBZ; + bits<7> Function = fun; + bits<5> Rc; + + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-13} = SBZ; + let Inst{12} = 0; + let Inst{11-5} = Function; + let Inst{4-0} = Rc; +} + + +class OFormL<bits<6> opcode, dag OL, string asmstr> : InstAlpha<opcode, OL, asmstr> { + bits<5> Ra; + bits<8> LIT; + bits<7> Function; + bits<5> Rc; + + let Inst{25-21} = Ra; + let Inst{20-13} = LIT; + let Inst{12} = 1; + let Inst{11-5} = Function; + let Inst{4-0} = Rc; +} + +//3.3.4 +class FPForm<bits<6> opcode, dag OL, string asmstr> : InstAlpha<opcode, OL, asmstr> { + bits<5> Fa; + bits<5> Fb; + bits<11> Function; + bits<5> Fc; + + let Inst{25-21} = Fa; + let Inst{20-16} = Fb; + let Inst{15-5} = Function; + let Inst{4-0} = Fc; +} + +//3.3.5 +class PALForm<bits<6> opcode, dag OL, string asmstr> : InstAlpha<opcode, OL, asmstr> { + bits<26> Function; + + let Inst{25-0} = Function; +} + + +// Pseudo instructions. +class PseudoInstAlpha<dag OL, string nm> : InstAlpha<0, OL, nm> { +} diff --git a/lib/Target/Alpha/AlphaInstrInfo.cpp b/lib/Target/Alpha/AlphaInstrInfo.cpp new file mode 100644 index 0000000..3ca0ebd --- /dev/null +++ b/lib/Target/Alpha/AlphaInstrInfo.cpp @@ -0,0 +1,43 @@ +//===- AlphaInstrInfo.cpp - Alpha Instruction Information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Alpha implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +#include "AlphaInstrInfo.h" +#include "AlphaGenInstrInfo.inc" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include <iostream> +using namespace llvm; + +AlphaInstrInfo::AlphaInstrInfo() + : TargetInstrInfo(AlphaInsts, sizeof(AlphaInsts)/sizeof(AlphaInsts[0])) { } + + +bool AlphaInstrInfo::isMoveInstr(const MachineInstr& MI, + unsigned& sourceReg, + unsigned& destReg) const { + //assert(0 && "TODO"); + MachineOpCode oc = MI.getOpcode(); + if (oc == Alpha::BIS) { // or r1, r2, r2 + assert(MI.getNumOperands() == 3 && + MI.getOperand(0).isRegister() && + MI.getOperand(1).isRegister() && + MI.getOperand(2).isRegister() && + "invalid Alpha BIS instruction!"); + if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + } + return false; +} diff --git a/lib/Target/Alpha/AlphaInstrInfo.h b/lib/Target/Alpha/AlphaInstrInfo.h new file mode 100644 index 0000000..921528e --- /dev/null +++ b/lib/Target/Alpha/AlphaInstrInfo.h @@ -0,0 +1,42 @@ +//===- AlphaInstrInfo.h - Alpha Instruction Information -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Alpha implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAINSTRUCTIONINFO_H +#define ALPHAINSTRUCTIONINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "AlphaRegisterInfo.h" + +namespace llvm { + +class AlphaInstrInfo : public TargetInstrInfo { + const AlphaRegisterInfo RI; +public: + AlphaInstrInfo(); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + virtual const MRegisterInfo &getRegisterInfo() const { return RI; } + + /// Return true if the instruction is a register to register move and + /// leave the source and dest operands in the passed parameters. + /// + virtual bool isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg) const; +}; + +} + +#endif diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td new file mode 100644 index 0000000..b94c14a --- /dev/null +++ b/lib/Target/Alpha/AlphaInstrInfo.td @@ -0,0 +1,295 @@ +//===- AlphaInstrInfo.td - The Alpha Instruction Set -----*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +include "AlphaInstrFormats.td" + + // //#define FP $15 + // //#define RA $26 + // //#define PV $27 + // //#define GP $29 + // //#define SP $30 + +def s14imm : Operand<i16>; +def s16imm : Operand<i16>; +def s21imm : Operand<i32>; +def s64imm : Operand<i64>; + +def PHI : PseudoInstAlpha<(ops ), "#phi">; +def IDEF : PseudoInstAlpha<(ops ), "#idef">; +def WTF : PseudoInstAlpha<(ops ), "#wtf">; +def ADJUSTSTACKUP : PseudoInstAlpha<(ops ), "ADJUP">; +def ADJUSTSTACKDOWN : PseudoInstAlpha<(ops ), "ADJDOWN">; + +//***************** +//These are shortcuts, the assembler expands them +//***************** +//AT = R28 +//T0-T7 = R1 - R8 +//T8-T11 = R22-R25 + +let Defs = [R29] in + let Uses = [R27] in + def LDGP : PseudoInstAlpha<(ops), "ldgp $$29, 0($$27)">; + +let isCall = 1, + Defs = [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R29], + Uses = [R27, R29] in + def CALL : PseudoInstAlpha< (ops s64imm:$TARGET), "jsr $TARGET">; //Jump to subroutine + +let isReturn = 1, isTerminator = 1 in + def RETURN : PseudoInstAlpha<(ops ), "ret $$31,($$26),1">; //Return from subroutine + +def LOAD_IMM : PseudoInstAlpha<(ops GPRC:$RC, s64imm:$IMM), "ldiq $RC,$IMM">; //Load Immediate Quadword + +let Uses = [R29] in + def STORE : PseudoInstAlpha<(ops GPRC:$RA, s64imm:$DISP), "stq $RA,$DISP">; //Store quadword + +let Uses = [R29] in + def LOAD_ADDR : PseudoInstAlpha<(ops GPRC:$RA, s64imm:$DISP), "lda $RA,$DISP">; //Load address + +let Uses = [R29] in + def LOAD : PseudoInstAlpha<(ops GPRC:$RA, s64imm:$DISP), "ldq $RA,$DISP">; //Load quadword + +def LDW : PseudoInstAlpha<(ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "ldw $RA,$DISP($RB)">; // Load sign-extended word +def LDB : PseudoInstAlpha<(ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "ldb $RA,$DISP($RB)">; //Load byte + +let Uses = [R28, R23, R24, R25, R26] in + def REMQU : PseudoInstAlpha<(ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "remqu $RA,$RB,$RC">; //unsigned remander + +//*********************** +//Real instructions +//*********************** + +//Operation Form: +def ADDL : OForm<0x10, 0x00, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "addl $RA,$RB,$RC">; //Add longword +def ADDL_V : OForm< 0x10, 0x40, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "ADDL/V $RA,$RB,$RC">; +def ADDQ : OForm< 0x10, 0x20, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "addq $RA,$RB,$RC">; //Add quadword +def ADDQ_V : OForm< 0x10, 0x60, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "ADDQ/V $RA,$RB,$RC">; +def AMASK : OForm< 0x11, 0x61, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "AMASK $RA,$RB,$RC">; //Architecture mask +def AND : OForm< 0x11, 0x00, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "AND $RA,$RB,$RC">; //Logical product +def BIC : OForm< 0x11, 0x08, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "BIC $RA,$RB,$RC">; //Bit clear +def BIS : OForm<0x11, 0x20, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "bis $RA,$RB,$RC">; //Logical sum + +//let isTwoAddress = 1 in { + def CMOVEQ : OForm< 0x11, 0x24, + (ops GPRC:$RDEST, GPRC:$RSRC, GPRC:$RCOND), + "cmoveq $RCOND,$RSRC,$RDEST">; //CMOVE if RCOND = zero + def CMOVGE : OForm< 0x11, 0x46, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMOVGE $RA,$RB,$RC">; //CMOVE if ³ zero + def CMOVGT : OForm<0x11, 0x66, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMOVGT $RA,$RB,$RC">; //CMOVE if > zero + def CMOVLBC : OForm< 0x11, 0x16, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMOVLBC $RA,$RB,$RC">; //CMOVE if low bit clear + def CMOVLBS : OForm< 0x11, 0x14, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMOVLBS $RA,$RB,$RC">; //CMOVE if low bit set + def CMOVLE : OForm<0x11, 0x64, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMOVLE $RA,$RB,$RC">; //CMOVE if £ zero + def CMOVLT : OForm< 0x11, 0x44, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMOVLT $RA,$RB,$RC">; //CMOVE if < zero + def CMOVNE : OForm< 0x11, 0x26, + (ops GPRC:$RC, GPRC:$DUMMY, GPRC:$RA, GPRC:$RB), + "cmovne $RA,$RB,$RC">; //CMOVE if ¹ zero +//} + +def CMPBGE : OForm< 0x10, 0x0F, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMPBGE $RA,$RB,$RC">; //Compare byte +def CMPEQ : OForm< 0x10, 0x2D, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMPEQ $RA,$RB,$RC">; //Compare signed quadword equal +def CMPLE : OForm< 0x10, 0x6D, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMPLE $RA,$RB,$RC">; //Compare signed quadword less than or equal +def CMPLT : OForm< 0x10, 0x4D, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMPLT $RA,$RB,$RC">; //Compare signed quadword less than +def CMPULE : OForm< 0x10, 0x3D, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMPULE $RA,$RB,$RC">; //Compare unsigned quadword less than or equal +def CMPULT : OForm< 0x10, 0x1D, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CMPULT $RA,$RB,$RC">; //Compare unsigned quadword less than +def CTLZ : OForm< 0x1C, 0x32, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CTLZ $RA,$RB,$RC">; //Count leading zero +def CTPOP : OForm< 0x1C, 0x30, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CTPOP $RA,$RB,$RC">; //Count population +def CTTZ : OForm<0x1C, 0x33, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CTTZ $RA,$RB,$RC">; //Count trailing zero +def EQV : OForm< 0x11, 0x48, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EQV $RA,$RB,$RC">; //Logical equivalence +def EXTBL : OForm< 0x12, 0x06, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTBL $RA,$RB,$RC">; //Extract byte low +def EXTLH : OForm< 0x12, 0x6A, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTLH $RA,$RB,$RC">; //Extract longword high +def EXTLL : OForm< 0x12, 0x26, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTLL $RA,$RB,$RC">; //Extract longword low +def EXTQH : OForm< 0x12, 0x7A, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTQH $RA,$RB,$RC">; //Extract quadword high +def EXTQ : OForm< 0x12, 0x36, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTQ $RA,$RB,$RC">; //Extract quadword low +def EXTWH : OForm< 0x12, 0x5A, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTWH $RA,$RB,$RC">; //Extract word high +def EXTWL : OForm< 0x12, 0x16, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTWL $RA,$RB,$RC">; //Extract word low +def IMPLVER : OForm< 0x11, 0x6C, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "IMPLVER $RA,$RB,$RC">; //Implementation version +def INSBL : OForm< 0x12, 0x0B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "INSBL $RA,$RB,$RC">; //Insert byte low +def INSLH : OForm< 0x12, 0x67, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "INSLH $RA,$RB,$RC">; //Insert longword high +def INSLL : OForm< 0x12, 0x2B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "INSLL $RA,$RB,$RC">; //Insert longword low +def INSQH : OForm< 0x12, 0x77, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "INSQH $RA,$RB,$RC">; //Insert quadword high +def INSQL : OForm< 0x12, 0x3B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "INSQL $RA,$RB,$RC">; //Insert quadword low +def INSWH : OForm< 0x12, 0x57, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "INSWH $RA,$RB,$RC">; //Insert word high +def INSWL : OForm< 0x12, 0x1B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "INSWL $RA,$RB,$RC">; //Insert word low +def MAXSB8 : OForm<0x1C, 0x3E, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MAXSB8 $RA,$RB,$RC">; //Vector signed byte maximum +def MAXSW4 : OForm< 0x1C, 0x3F, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MAXSW4 $RA,$RB,$RC">; //Vector signed word maximum +def MAXUB8 : OForm<0x1C, 0x3C, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MAXUB8 $RA,$RB,$RC">; //Vector unsigned byte maximum +def MAXUW4 : OForm< 0x1C, 0x3D, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MAXUW4 $RA,$RB,$RC">; //Vector unsigned word maximum +def MINSB8 : OForm< 0x1C, 0x38, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MINSB8 $RA,$RB,$RC">; //Vector signed byte minimum +def MINSW4 : OForm< 0x1C, 0x39, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MINSW4 $RA,$RB,$RC">; //Vector signed word minimum +def MINUB8 : OForm< 0x1C, 0x3A, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MINUB8 $RA,$RB,$RC">; //Vector unsigned byte minimum +def MINUW4 : OForm< 0x1C, 0x3B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MINUW4 $RA,$RB,$RC">; //Vector unsigned word minimum +def MSKBL : OForm< 0x12, 0x02, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MSKBL $RA,$RB,$RC">; //Mask byte low +def MSKLH : OForm< 0x12, 0x62, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MSKLH $RA,$RB,$RC">; //Mask longword high +def MSKLL : OForm< 0x12, 0x22, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MSKLL $RA,$RB,$RC">; //Mask longword low +def MSKQH : OForm< 0x12, 0x72, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MSKQH $RA,$RB,$RC">; //Mask quadword high +def MSKQL : OForm< 0x12, 0x32, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MSKQL $RA,$RB,$RC">; //Mask quadword low +def MSKWH : OForm< 0x12, 0x52, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MSKWH $RA,$RB,$RC">; //Mask word high +def MSKWL : OForm< 0x12, 0x12, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MSKWL $RA,$RB,$RC">; //Mask word low +def MULL : OForm< 0x13, 0x00, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MULL $RA,$RB,$RC">; //Multiply longword +def MULL_V : OForm< 0x13, 0x40, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MULL/V $RA,$RB,$RC">; +def MULQ : OForm< 0x13, 0x20, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MULQ $RA,$RB,$RC">; //Multiply quadword +def MULQ_V : OForm< 0x13, 0x60, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "MULQ/V $RA,$RB,$RC">; +def ORNOT : OForm< 0x11, 0x28, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "ORNOT $RA,$RB,$RC">; //Logical sum with complement +def PERR : OForm< 0x1C, 0x31, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "PERR $RA,$RB,$RC">; //Pixel error +def PKLB : OForm< 0x1C, 0x37, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "PKLB $RA,$RB,$RC">; //Pack longwords to bytes +def PKWB : OForm<0x1C, 0x36, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "PKWB $RA,$RB,$RC">; //Pack words to bytes +def S4ADDL : OForm< 0x10, 0x02, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "S4ADDL $RA,$RB,$RC">; //Scaled add longword by 4 +def S4ADDQ : OForm< 0x10, 0x22, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "S4ADDQ $RA,$RB,$RC">; //Scaled add quadword by 4 +def S4SUBL : OForm< 0x10, 0x0B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "S4SUBL $RA,$RB,$RC">; //Scaled subtract longword by 4 +def S4SUBQ : OForm< 0x10, 0x2B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "S4SUBQ $RA,$RB,$RC">; //Scaled subtract quadword by 4 +def S8ADDL : OForm< 0x10, 0x12, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "S8ADDL $RA,$RB,$RC">; //Scaled add longword by 8 +def S8ADDQ : OForm< 0x10, 0x32, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "S8ADDQ $RA,$RB,$RC">; //Scaled add quadword by 8 +def S8SUBL : OForm< 0x10, 0x1B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "S8SUBL $RA,$RB,$RC">; //Scaled subtract longword by 8 +def S8SUBQ : OForm< 0x10, 0x3B, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "S8SUBQ $RA,$RB,$RC">; //Scaled subtract quadword by 8 +def SEXTB : OForm< 0x1C, 0x00, (ops GPRC:$RC, GPRC:$RB), "sextb $RB,$RC">; //Sign extend byte +def SEXTW : OForm< 0x1C, 0x01, (ops GPRC:$RC, GPRC:$RB), "sextw $RB,$RC">; //Sign extend word +def SL : OForm< 0x12, 0x39, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "SLL $RA,$RB,$RC">; //Shift left logical +def SRA : OForm< 0x12, 0x3C, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "SRA $RA,$RB,$RC">; //Shift right arithmetic +def SRL : OForm< 0x12, 0x34, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "SRL $RA,$RB,$RC">; //Shift right logical +def SUBL : OForm< 0x10, 0x09, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "SUBL $RA,$RB,$RC">; //Subtract longword +def SUBL_V : OForm< 0x10, 0x49, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "SUBL/V $RA,$RB,$RC">; +def SUBQ : OForm< 0x10, 0x29, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "SUBQ $RA,$RB,$RC">; //Subtract quadword +def SUBQ_V : OForm< 0x10, 0x69, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "SUBQ/V $RA,$RB,$RC">; +def UMULH : OForm< 0x13, 0x30, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "UMULH $RA,$RB,$RC">; //Unsigned multiply quadword high +def UNPKBL : OForm< 0x1C, 0x35, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "UNPKBL $RA,$RB,$RC">; //Unpack bytes to longwords +def UNPKBW : OForm< 0x1C, 0x34, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "UNPKBW $RA,$RB,$RC">; //Unpack bytes to words +def XOR : OForm< 0x11, 0x40, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "XOR $RA,$RB,$RC">; //Logical difference +def ZAP : OForm< 0x12, 0x30, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "ZAP $RA,$RB,$RC">; //Zero bytes +def ZAPNOT : OForm< 0x12, 0x31, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "ZAPNOT $RA,$RB,$RC">; //Zero bytes not + +let isReturn = 1, isTerminator = 1 in + def RET : MForm< 0x1A, (ops GPRC:$RD, GPRC:$RS), "ret $RD,($RS),1">; //Return from subroutine + +def JMP : MForm< 0x1A, (ops GPRC:$RD, GPRC:$RS), "jmp $RD,($RS),0">; //Jump +let isCall = 1 in + let Defs = [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R27, R29] in + def JSR : MForm< 0x1A, (ops GPRC:$RD, GPRC:$RS, s14imm:$DISP), "jsr $RD,($RS),$DISP">; //Jump to subroutine +def JSR_COROUTINE : MForm< 0x1A, (ops GPRC:$RD, GPRC:$RS), "jsr_coroutine $RD,($RS),1">; //Jump to subroutine return + +def BR : BForm<0x30, (ops GPRC:$RD, s21imm:$DISP), "br $RD,$DISP">; //Branch +let isCall = 1 in + let Defs = [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R27, R29] in + def BSR : BForm<0x34, (ops GPRC:$RD, s21imm:$DISP), "bsr $RD,$DISP">; //Branch to subroutine + +def STB : MForm<0x0E, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "stb $RA,$DISP($RB)">; // Store byte +def STW : MForm<0x0D, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "stw $RA,$DISP($RB)">; // Store word +def STL : MForm<0x2C, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "stl $RA,$DISP($RB)">; // Store longword +def STQ : MForm<0x2D, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "stq $RA,$DISP($RB)">; //Store quadword + +def LDA : MForm<0x08, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "lda $RA,$DISP($RB)">; //Load address + +def LDL : MForm<0x28, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "ldq $RA,$DISP($RB)">; // Load sign-extended longword +def LDQ : MForm<0x29, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), "ldq $RA,$DISP($RB)">; //Load quadword + +def BEQ : BForm<0x39, (ops GPRC:$RA, s21imm:$DISP), "beq $RA,$DISP">; //Branch if = zero +def BGE : BForm<0x3E, (ops GPRC:$RA, s21imm:$DISP), "bge $RA,$DISP">; //Branch if >= zero +def BGT : BForm<0x3F, (ops GPRC:$RA, s21imm:$DISP), "bgt $RA,$DISP">; //Branch if > zero +def BLBC : BForm<0x38, (ops GPRC:$RA, s21imm:$DISP), "blbc $RA,$DISP">; //Branch if low bit clear +def BLBS : BForm<0x3C, (ops GPRC:$RA, s21imm:$DISP), "blbs $RA,$DISP">; //Branch if low bit set +def BLE : BForm<0x3B, (ops GPRC:$RA, s21imm:$DISP), "ble $RA,$DISP">; //Branch if <= zero +def BLT : BForm<0x3A, (ops GPRC:$RA, s21imm:$DISP), "blt $RA,$DISP">; //Branch if < zero +def BNE : BForm<0x3D, (ops GPRC:$RA, s21imm:$DISP), "bne $RA,$DISP">; //Branch if != zero + +//Mnemonic Format Opcode Description +//ADDF F-P 15.080 Add F_floating +//ADDG F-P 15.0A0 Add G_floating +//ADDS F-P 16.080 Add S_floating +//ADDT F-P 16.0A0 Add T_floating +//CALL_PAL Pcd 00 Trap to PALcode +//ECB Mfc 18.E800 Evict cache block +//EXCB Mfc 18.0400 Exception barrier +//FETCH Mfc 18.8000 Prefetch data +//FETCH_M Mfc 18.A000 Prefetch data, modify intent +//LDAH Mem 09 Load address high +//LDBU Mem 0A Load zero-extended byte +//LDWU Mem 0C Load zero-extended word +//LDL_L Mem 2A Load sign-extended longword locked +//LDQ_L Mem 2B Load quadword locked +//LDQ_U Mem 0B Load unaligned quadword +//MB Mfc 18.4000 Memory barrier +//RC Mfc 18.E000 Read and clear +//RPCC Mfc 18.C000 Read process cycle counter +//RS Mfc 18.F000 Read and set +//STL_C Mem 2E Store longword conditional +//STQ_C Mem 2F Store quadword conditional +//STQ_U Mem 0F Store unaligned quadword +//TRAPB Mfc 18.0000 Trap barrier +//WH64 Mfc 18.F800 Write hint 64 bytes +//WMB Mfc 18.4400 Write memory barrier + + +//CMPGEQ F-P 15.0A5 Compare G_floating equal +//CMPGLE F-P 15.0A7 Compare G_floating less than or equal +//CMPGLT F-P 15.0A6 Compare G_floating less than +//CMPTEQ F-P 16.0A5 Compare T_floating equal +//CMPTLE F-P 16.0A7 Compare T_floating less than or equal +//CMPTLT F-P 16.0A6 Compare T_floating less than +//CMPTUN F-P 16.0A4 Compare T_floating unordered +//CPYS F-P 17.020 Copy sign +//CPYSE F-P 17.022 Copy sign and exponent +//CPYSN F-P 17.021 Copy sign negate +//CVTDG F-P 15.09E Convert D_floating to G_floating +//CVTGD F-P 15.0AD Convert G_floating to D_floating +//CVTGF F-P 15.0AC Convert G_floating to F_floating +//CVTGQ F-P 15.0AF Convert G_floating to quadword +//CVTLQ F-P 17.010 Convert longword to quadword +//CVTQF F-P 15.0BC Convert quadword to F_floating +//CVTQG F-P 15.0BE Convert quadword to G_floating +//CVTQL F-P 17.030 Convert quadword to longword +//CVTQS F-P 16.0BC Convert quadword to S_floating +//CVTQT F-P 16.0BE Convert quadword to T_floating +//CVTST F-P 16.2AC Convert S_floating to T_floating +//CVTTQ F-P 16.0AF Convert T_floating to quadword +//CVTTS F-P 16.0AC Convert T_floating to S_floating +//DIVF F-P 15.083 Divide F_floating +//DIVG F-P 15.0A3 Divide G_floating +//DIVS F-P 16.083 Divide S_floating +//DIVT F-P 16.0A3 Divide T_floating +//FBEQ Bra 31 Floating branch if = zero +//FBGE Bra 36 Floating branch if ³ zero +//FBGT Bra 37 Floating branch if > zero +//FBLE Bra 33 Floating branch if £ zero +//FBLT Bra 32 Floating branch if < zero +//FBNE Bra 35 Floating branch if ¹ zero +//FCMOVEQ F-P 17.02A FCMOVE if = zero +//FCMOVGE F-P 17.02D FCMOVE if ³ zero +//FCMOVGT F-P 17.02F FCMOVE if > zero +//FCMOVLE F-P 17.02E FCMOVE if £ zero +//FCMOVLT F-P 17.02C FCMOVE if < zero +//FCMOVNE F-P 17.02B FCMOVE if ¹ zero +//FTOIS F-P 1C.78 Floating to integer move, S_floating +//FTOIT F-P 1C.70 Floating to integer move, T_floating +//ITOFF F-P 14.014 Integer to floating move, F_floating +//ITOFS F-P 14.004 Integer to floating move, S_floating +//ITOFT F-P 14.024 Integer to floating move, T_floating +//LDF Mem 20 Load F_floating +//LDG Mem 21 Load G_floating +//LDS Mem 22 Load S_floating +//LDT Mem 23 Load T_floating +//MF_FPCR F-P 17.025 Move from FPCR +//MT_FPCR F-P 17.024 Move to FPCR +//MULF F-P 15.082 Multiply F_floating +//MULG F-P 15.0A2 Multiply G_floating +//MULS F-P 16.082 Multiply S_floating +//MULT F-P 16.0A2 Multiply T_floating +//SQRTF F-P 14.08A Square root F_floating +//SQRTG F-P 14.0AA Square root G_floating +//SQRTS F-P 14.08B Square root S_floating +//SQRTT F-P 14.0AB Square root T_floating +//STF Mem 24 Store F_floating +//STG Mem 25 Store G_floating +//STS Mem 26 Store S_floating +//STT Mem 27 Store T_floating +//SUBF F-P 15.081 Subtract F_floating +//SUBG F-P 15.0A1 Subtract G_floating +//SUBS F-P 16.081 Subtract S_floating +//SUBT F-P 16.0A1 Subtract T_floating diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp new file mode 100644 index 0000000..58a1a8d --- /dev/null +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -0,0 +1,268 @@ +//===- PPC64RegisterInfo.cpp - PowerPC64 Register Information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC64 implementation of the MRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "reginfo" +#include "Alpha.h" +#include "AlphaInstrBuilder.h" +#include "AlphaRegisterInfo.h" +#include "llvm/Constants.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/STLExtras.h" +#include <cstdlib> +#include <iostream> +using namespace llvm; + + +AlphaRegisterInfo::AlphaRegisterInfo() + : AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP) +{ +} + +static const TargetRegisterClass *getClass(unsigned SrcReg) { + if (Alpha::FPRCRegisterClass->contains(SrcReg)) + return Alpha::FPRCRegisterClass; + assert(Alpha::GPRCRegisterClass->contains(SrcReg) && "Reg not FPR or GPR"); + return Alpha::GPRCRegisterClass; +} + +void +AlphaRegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, int FrameIdx) const { + std::cerr << "Trying to store " << getPrettyName(SrcReg) << " to " << FrameIdx << "\n"; + //BuildMI(MBB, MI, Alpha::WTF, 0).addReg(SrcReg); + BuildMI(MBB, MI, Alpha::STQ, 3).addReg(SrcReg).addImm(FrameIdx * 8).addReg(Alpha::R30); + // assert(0 && "TODO"); +} + +void +AlphaRegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIdx) const{ + std::cerr << "Trying to load " << getPrettyName(DestReg) << " to " << FrameIdx << "\n"; + //BuildMI(MBB, MI, Alpha::WTF, 0, DestReg); + BuildMI(MBB, MI, Alpha::LDQ, 2, DestReg).addImm(FrameIdx * 8).addReg(Alpha::R30); + // assert(0 && "TODO"); +} + +void AlphaRegisterInfo::copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const { + // std::cerr << "copyRegToReg " << DestReg << " <- " << SrcReg << "\n"; + if (RC == Alpha::GPRCRegisterClass) { + BuildMI(MBB, MI, Alpha::BIS, 2, DestReg).addReg(SrcReg).addReg(SrcReg); +// } else if (RC == Alpha::FPRCRegisterClass) { +// BuildMI(MBB, MI, PPC::FMR, 1, DestReg).addReg(SrcReg); + } else { + std::cerr << "Attempt to copy register that is not GPR or FPR"; + abort(); + } +} + +//===----------------------------------------------------------------------===// +// Stack Frame Processing methods +//===----------------------------------------------------------------------===// + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +// +static bool hasFP(MachineFunction &MF) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + return MFI->hasVarSizedObjects(); +} + +void AlphaRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (hasFP(MF)) { + assert(0 && "TODO"); + // If we have a frame pointer, turn the adjcallstackup instruction into a + // 'sub ESP, <amt>' and the adjcallstackdown instruction into 'add ESP, + // <amt>' + MachineInstr *Old = I; + unsigned Amount = Old->getOperand(0).getImmedValue(); + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); + Amount = (Amount+Align-1)/Align*Align; + + MachineInstr *New; +// if (Old->getOpcode() == X86::ADJCALLSTACKDOWN) { +// New=BuildMI(X86::SUB32ri, 1, X86::ESP, MachineOperand::UseAndDef) +// .addZImm(Amount); +// } else { +// assert(Old->getOpcode() == X86::ADJCALLSTACKUP); +// New=BuildMI(X86::ADD32ri, 1, X86::ESP, MachineOperand::UseAndDef) +// .addZImm(Amount); +// } + + // Replace the pseudo instruction with a new instruction... + MBB.insert(I, New); + } + } + + MBB.erase(I); +} + +void +AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const { + assert(0 && "TODO"); +// unsigned i = 0; +// MachineInstr &MI = *II; +// MachineBasicBlock &MBB = *MI.getParent(); +// MachineFunction &MF = *MBB.getParent(); + +// while (!MI.getOperand(i).isFrameIndex()) { +// ++i; +// assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); +// } + +// int FrameIndex = MI.getOperand(i).getFrameIndex(); + +// // Replace the FrameIndex with base register with GPR1 (SP) or GPR31 (FP). +// MI.SetMachineOperandReg(i, hasFP(MF) ? PPC::R31 : PPC::R1); + +// // Take into account whether it's an add or mem instruction +// unsigned OffIdx = (i == 2) ? 1 : 2; + +// // Now add the frame object offset to the offset from r1. +// int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + +// MI.getOperand(OffIdx).getImmedValue(); + +// // If we're not using a Frame Pointer that has been set to the value of the +// // SP before having the stack size subtracted from it, then add the stack size +// // to Offset to get the correct offset. +// Offset += MF.getFrameInfo()->getStackSize(); + +// if (Offset > 32767 || Offset < -32768) { +// // Insert a set of r0 with the full offset value before the ld, st, or add +// MachineBasicBlock *MBB = MI.getParent(); +// MBB->insert(II, BuildMI(PPC::LIS, 1, PPC::R0).addSImm(Offset >> 16)); +// MBB->insert(II, BuildMI(PPC::ORI, 2, PPC::R0).addReg(PPC::R0) +// .addImm(Offset)); +// // convert into indexed form of the instruction +// // sth 0:rA, 1:imm 2:(rB) ==> sthx 0:rA, 2:rB, 1:r0 +// // addi 0:rA 1:rB, 2, imm ==> add 0:rA, 1:rB, 2:r0 +// unsigned NewOpcode = +// const_cast<std::map<unsigned, unsigned>& >(ImmToIdxMap)[MI.getOpcode()]; +// assert(NewOpcode && "No indexed form of load or store available!"); +// MI.setOpcode(NewOpcode); +// MI.SetMachineOperandReg(1, MI.getOperand(i).getReg()); +// MI.SetMachineOperandReg(2, PPC::R0); +// } else { +// MI.SetMachineOperandConst(OffIdx, MachineOperand::MO_SignExtendedImmed, +// Offset); +// } +} + + +void AlphaRegisterInfo::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineInstr *MI; + + //handle GOP offset + MI = BuildMI(Alpha::LDGP, 0); + MBB.insert(MBBI, MI); + + // Get the number of bytes to allocate from the FrameInfo + unsigned NumBytes = MFI->getStackSize(); + + // Do we need to allocate space on the stack? + if (NumBytes == 0) return; + + // Add the size of R30 to NumBytes size for the store of R30 to the + // stack +// std::cerr << "Spillsize of R30 is " << getSpillSize(Alpha::R30) << "\n"; +// NumBytes = NumBytes + getSpillSize(Alpha::R30)/8; + + // Update frame info to pretend that this is part of the stack... + MFI->setStackSize(NumBytes); + + // adjust stack pointer: r30 -= numbytes + + if (NumBytes <= 32000) //FIXME: do this better + { + MI=BuildMI(Alpha::LDA, 2, Alpha::R30).addImm(-NumBytes).addReg(Alpha::R30); + MBB.insert(MBBI, MI); + } else { + std::cerr << "Too big a stack frame\n"; + abort(); + } +} + +void AlphaRegisterInfo::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + MachineInstr *MI; + assert((MBBI->getOpcode() == Alpha::RET || MBBI->getOpcode() == Alpha::RETURN) && + "Can only insert epilog into returning blocks"); + + // Get the number of bytes allocated from the FrameInfo... + unsigned NumBytes = MFI->getStackSize(); + + if (NumBytes != 0) + { + if (NumBytes <= 32000) //FIXME: do this better + { + MI=BuildMI(Alpha::LDA, 2, Alpha::R30).addImm(NumBytes).addReg(Alpha::R30); + MBB.insert(MBBI, MI); + } else { + std::cerr << "Too big a stack frame\n"; + abort(); + } + } +} + +#include "AlphaGenRegisterInfo.inc" + +const TargetRegisterClass* +AlphaRegisterInfo::getRegClassForType(const Type* Ty) const { + switch (Ty->getTypeID()) { + default: assert(0 && "Invalid type to getClass!"); + case Type::BoolTyID: + case Type::SByteTyID: + case Type::UByteTyID: + case Type::ShortTyID: + case Type::UShortTyID: + case Type::IntTyID: + case Type::UIntTyID: + case Type::PointerTyID: + case Type::LongTyID: + case Type::ULongTyID: return &GPRCInstance; + + case Type::FloatTyID: + case Type::DoubleTyID: return &FPRCInstance; + } +} + +std::string AlphaRegisterInfo::getPrettyName(unsigned reg) +{ + std::string s(RegisterDescriptors[reg].Name); + return s; +} diff --git a/lib/Target/Alpha/AlphaRegisterInfo.h b/lib/Target/Alpha/AlphaRegisterInfo.h new file mode 100644 index 0000000..f29ff80 --- /dev/null +++ b/lib/Target/Alpha/AlphaRegisterInfo.h @@ -0,0 +1,57 @@ +//===- AlphaRegisterInfo.h - Alpha Register Information Impl -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Alpha implementation of the MRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAREGISTERINFO_H +#define ALPHAREGISTERINFO_H + +#include "llvm/Target/MRegisterInfo.h" +#include "AlphaGenRegisterInfo.h.inc" + +namespace llvm { + +class Type; + +struct AlphaRegisterInfo : public AlphaGenRegisterInfo { + AlphaRegisterInfo(); + const TargetRegisterClass* getRegClassForType(const Type* Ty) const; + + /// Code Generation virtual methods... + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, int FrameIndex) const; + + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex) const; + + void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + void eliminateFrameIndex(MachineBasicBlock::iterator II) const; + + //void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + static std::string getPrettyName(unsigned reg); +}; + +} // end namespace llvm + +#endif diff --git a/lib/Target/Alpha/AlphaRegisterInfo.td b/lib/Target/Alpha/AlphaRegisterInfo.td new file mode 100644 index 0000000..80f264b --- /dev/null +++ b/lib/Target/Alpha/AlphaRegisterInfo.td @@ -0,0 +1,93 @@ +//===- AlphaRegisterInfo.td - The Alpha Register File --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +class AlphaReg<string n> : Register<n> { + field bits<5> Num; + let Namespace = "Alpha"; +} + +// We identify all our registers with a 5-bit ID, for consistency's sake. + +// GPR - One of the 32 32-bit general-purpose registers +class GPR<bits<5> num, string n> : AlphaReg<n> { + let Num = num; +} + +// FPR - One of the 32 64-bit floating-point registers +class FPR<bits<5> num, string n> : AlphaReg<n> { + let Num = num; +} + +//#define FP $15 +//#define RA $26 +//#define PV $27 +//#define GP $29 +//#define SP $30 + +// General-purpose registers +def R0 : GPR< 0, "$0">; def R1 : GPR< 1, "$1">; +def R2 : GPR< 2, "$2">; def R3 : GPR< 3, "$3">; +def R4 : GPR< 4, "$4">; def R5 : GPR< 5, "$5">; +def R6 : GPR< 6, "$6">; def R7 : GPR< 7, "$7">; +def R8 : GPR< 8, "$8">; def R9 : GPR< 9, "$9">; +def R10 : GPR<10, "$10">; def R11 : GPR<11, "$11">; +def R12 : GPR<12, "$12">; def R13 : GPR<13, "$13">; +def R14 : GPR<14, "$14">; def R15 : GPR<15, "$15">; +def R16 : GPR<16, "$16">; def R17 : GPR<17, "$17">; +def R18 : GPR<18, "$18">; def R19 : GPR<19, "$19">; +def R20 : GPR<20, "$20">; def R21 : GPR<21, "$21">; +def R22 : GPR<22, "$22">; def R23 : GPR<23, "$23">; +def R24 : GPR<24, "$24">; def R25 : GPR<25, "$25">; +def R26 : GPR<26, "$26">; def R27 : GPR<27, "$27">; +def R28 : GPR<28, "$28">; def R29 : GPR<29, "$29">; +def R30 : GPR<30, "$30">; def R31 : GPR<31, "$31">; + +// Floating-point registers +def F0 : FPR< 0, "F0">; def F1 : FPR< 1, "F1">; +def F2 : FPR< 2, "F2">; def F3 : FPR< 3, "F3">; +def F4 : FPR< 4, "F4">; def F5 : FPR< 5, "F5">; +def F6 : FPR< 6, "F6">; def F7 : FPR< 7, "F7">; +def F8 : FPR< 8, "F8">; def F9 : FPR< 9, "F9">; +def F10 : FPR<10, "F10">; def F11 : FPR<11, "F11">; +def F12 : FPR<12, "F12">; def F13 : FPR<13, "F13">; +def F14 : FPR<14, "F14">; def F15 : FPR<15, "F15">; +def F16 : FPR<16, "F16">; def F17 : FPR<17, "F17">; +def F18 : FPR<18, "F18">; def F19 : FPR<19, "F19">; +def F20 : FPR<20, "F20">; def F21 : FPR<21, "F21">; +def F22 : FPR<22, "F22">; def F23 : FPR<23, "F23">; +def F24 : FPR<24, "F24">; def F25 : FPR<25, "F25">; +def F26 : FPR<26, "F26">; def F27 : FPR<27, "F27">; +def F28 : FPR<28, "F28">; def F29 : FPR<29, "F29">; +def F30 : FPR<30, "F30">; def F31 : FPR<31, "F31">; + + // //#define FP $15 + // //#define RA $26 + // //#define PV $27 + // //#define GP $29 + // //#define SP $30 + // $28 is undefined after any and all calls + +/// Register classes +def GPRC : RegisterClass<i64, 64, +//Volitle + [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R27, +//Non-Volitile + R9, R10, R11, R12, R13, R14, R15, R26, /*R28,*/ R29, R30, R31]>; +//R28 is reserved for the assembler + +//Don't allocate 15, 29, 30, 31 +//Allocation volatiles only for now +def FPRC : RegisterClass<f64, 64, [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, + F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, + F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>; + + diff --git a/lib/Target/Alpha/AlphaTargetMachine.cpp b/lib/Target/Alpha/AlphaTargetMachine.cpp new file mode 100644 index 0000000..baf3ca8 --- /dev/null +++ b/lib/Target/Alpha/AlphaTargetMachine.cpp @@ -0,0 +1,111 @@ +//===-- AlphaTargetMachine.cpp - Define TargetMachine for Alpha -------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +#include "AlphaTargetMachine.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetMachineRegistry.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/CommandLine.h" +#include <iostream> +using namespace llvm; + +namespace { + // Register the targets + RegisterTarget<AlphaTargetMachine> X("alpha", " Alpha (incomplete)"); +} + +AlphaTargetMachine::AlphaTargetMachine( const Module &M, IntrinsicLowering *IL) + : TargetMachine("alpha", IL, true), + FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) //TODO: check these + //JITInfo(*this) +{} + +bool AlphaTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE) +{ + assert(0 && "TODO"); + return false; +} + + +/// addPassesToEmitAssembly - Add passes to the specified pass manager +/// to implement a static compiler for this target. +/// +bool AlphaTargetMachine::addPassesToEmitAssembly(PassManager &PM, + std::ostream &Out) { + + // FIXME: Implement efficient support for garbage collection intrinsics. + PM.add(createLowerGCPass()); + + // FIXME: Implement the invoke/unwind instructions! + PM.add(createLowerInvokePass()); + + // FIXME: Implement the switch instruction in the instruction selector! + PM.add(createLowerSwitchPass()); + + PM.add(createLowerConstantExpressionsPass()); + + // Make sure that no unreachable blocks are instruction selected. + PM.add(createUnreachableBlockEliminationPass()); + + PM.add(createAlphaPatternInstructionSelector(*this)); + + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(&std::cerr)); + + PM.add(createRegisterAllocator()); + + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(&std::cerr)); + + PM.add(createPrologEpilogCodeInserter()); + + // Must run branch selection immediately preceding the asm printer + //PM.add(createAlphaBranchSelectionPass()); + + PM.add(createAlphaCodePrinterPass(Out, *this)); + + PM.add(createMachineCodeDeleter()); + return false; +} + +//void AlphaJITInfo::addPassesToJITCompile(FunctionPassManager &PM) { +// // FIXME: Implement efficient support for garbage collection intrinsics. +// PM.add(createLowerGCPass()); + +// // FIXME: Implement the invoke/unwind instructions! +// PM.add(createLowerInvokePass()); + +// // FIXME: Implement the switch instruction in the instruction selector! +// PM.add(createLowerSwitchPass()); + +// PM.add(createLowerConstantExpressionsPass()); + +// // Make sure that no unreachable blocks are instruction selected. +// PM.add(createUnreachableBlockEliminationPass()); + +// PM.add(createPPC32ISelSimple(TM)); +// PM.add(createRegisterAllocator()); +// PM.add(createPrologEpilogCodeInserter()); + +// // Must run branch selection immediately preceding the asm printer +// PM.add(createPPCBranchSelectionPass()); + +// if (PrintMachineCode) +// PM.add(createMachineFunctionPrinterPass(&std::cerr)); +//} + diff --git a/lib/Target/Alpha/AlphaTargetMachine.h b/lib/Target/Alpha/AlphaTargetMachine.h new file mode 100644 index 0000000..af18601 --- /dev/null +++ b/lib/Target/Alpha/AlphaTargetMachine.h @@ -0,0 +1,54 @@ +//===-- AlphaTargetMachine.h - Define TargetMachine for PowerPC -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Alpha-specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHA_TARGETMACHINE_H +#define ALPHA_TARGETMACHINE_H + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/PassManager.h" +#include "AlphaInstrInfo.h" +//#include "AlphaJITInfo.h" + +namespace llvm { + +class GlobalValue; +class IntrinsicLowering; + +class AlphaTargetMachine : public TargetMachine { + AlphaInstrInfo InstrInfo; + TargetFrameInfo FrameInfo; + // AlphaJITInfo JITInfo; + +public: + AlphaTargetMachine(const Module &M, IntrinsicLowering *IL); + + virtual const AlphaInstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; } + virtual const MRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + // virtual TargetJITInfo *getJITInfo() { + // return &JITInfo; + // } + + virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE); + + virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out); + +}; + +} // end namespace llvm + +#endif diff --git a/lib/Target/Alpha/Makefile b/lib/Target/Alpha/Makefile new file mode 100644 index 0000000..49cb1cd --- /dev/null +++ b/lib/Target/Alpha/Makefile @@ -0,0 +1,20 @@ +##===- lib/Target/Alpha/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file was developed by the LLVM research group and is distributed under +# the University of Illinois Open Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMAlpha +TARGET = Alpha +SHARED_LIBRARY=1 + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = AlphaGenRegisterInfo.h.inc AlphaGenRegisterNames.inc \ + AlphaGenRegisterInfo.inc AlphaGenInstrNames.inc \ + AlphaGenInstrInfo.inc AlphaGenCodeEmitter.inc \ + AlphaGenAsmWriter.inc + +include $(LEVEL)/Makefile.common |