diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Alpha')
32 files changed, 5159 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/Alpha/Alpha.h b/contrib/llvm/lib/Target/Alpha/Alpha.h new file mode 100644 index 0000000..6ffaf45 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/Alpha.h @@ -0,0 +1,43 @@ +//===-- Alpha.h - Top-level interface for Alpha representation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 "MCTargetDesc/AlphaMCTargetDesc.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + namespace Alpha { + // These describe LDAx + + static const int IMM_LOW = -32768; + static const int IMM_HIGH = 32767; + static const int IMM_MULT = 65536; + } + + class AlphaTargetMachine; + class FunctionPass; + class formatted_raw_ostream; + + FunctionPass *createAlphaISelDag(AlphaTargetMachine &TM); + FunctionPass *createAlphaPatternInstructionSelector(TargetMachine &TM); + FunctionPass *createAlphaJITCodeEmitterPass(AlphaTargetMachine &TM, + JITCodeEmitter &JCE); + FunctionPass *createAlphaLLRPPass(AlphaTargetMachine &tm); + FunctionPass *createAlphaBranchSelectionPass(); + +} // end namespace llvm; + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/Alpha.td b/contrib/llvm/lib/Target/Alpha/Alpha.td new file mode 100644 index 0000000..ae79c2e --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/Alpha.td @@ -0,0 +1,68 @@ +//===- Alpha.td - Describe the Alpha Target Machine --------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 "llvm/Target/Target.td" + +//Alpha is little endian + +//===----------------------------------------------------------------------===// +// Subtarget Features +//===----------------------------------------------------------------------===// + +def FeatureCIX : SubtargetFeature<"cix", "HasCT", "true", + "Enable CIX extensions">; + +//===----------------------------------------------------------------------===// +// Register File Description +//===----------------------------------------------------------------------===// + +include "AlphaRegisterInfo.td" + +//===----------------------------------------------------------------------===// +// Calling Convention Description +//===----------------------------------------------------------------------===// + +include "AlphaCallingConv.td" + +//===----------------------------------------------------------------------===// +// Schedule Description +//===----------------------------------------------------------------------===// + +include "AlphaSchedule.td" + +//===----------------------------------------------------------------------===// +// Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "AlphaInstrInfo.td" + +def AlphaInstrInfo : InstrInfo; + +//===----------------------------------------------------------------------===// +// Alpha Processor Definitions +//===----------------------------------------------------------------------===// + +def : Processor<"generic", Alpha21264Itineraries, []>; +def : Processor<"ev6" , Alpha21264Itineraries, []>; +def : Processor<"ev67" , Alpha21264Itineraries, [FeatureCIX]>; + +//===----------------------------------------------------------------------===// +// The Alpha Target +//===----------------------------------------------------------------------===// + + +def Alpha : Target { + // Pull in Instruction Info: + let InstructionSet = AlphaInstrInfo; +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaAsmPrinter.cpp b/contrib/llvm/lib/Target/Alpha/AlphaAsmPrinter.cpp new file mode 100644 index 0000000..5dce06a --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaAsmPrinter.cpp @@ -0,0 +1,166 @@ +//===-- AlphaAsmPrinter.cpp - Alpha 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 Alpha assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "Alpha.h" +#include "AlphaInstrInfo.h" +#include "AlphaTargetMachine.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct AlphaAsmPrinter : public AsmPrinter { + /// Unique incrementer for label values for referencing Global values. + /// + + explicit AlphaAsmPrinter(TargetMachine &tm, MCStreamer &Streamer) + : AsmPrinter(tm, Streamer) {} + + virtual const char *getPassName() const { + return "Alpha Assembly Printer"; + } + void printInstruction(const MachineInstr *MI, raw_ostream &O); + void EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); + } + static const char *getRegisterName(unsigned RegNo); + + void printOp(const MachineOperand &MO, raw_ostream &O); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd(); + void EmitStartOfAsmFile(Module &M); + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + bool PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O); + }; +} // end of anonymous namespace + +#include "AlphaGenAsmWriter.inc" + +void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.isReg()) { + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Not physreg??"); + O << getRegisterName(MO.getReg()); + } else if (MO.isImm()) { + O << MO.getImm(); + assert(MO.getImm() < (1 << 30)); + } else { + printOp(MO, O); + } +} + + +void AlphaAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << getRegisterName(MO.getReg()); + return; + + case MachineOperand::MO_Immediate: + assert(0 && "printOp() does not handle immediate values"); + return; + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" + << MO.getIndex(); + return; + + case MachineOperand::MO_ExternalSymbol: + O << MO.getSymbolName(); + return; + + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + return; + + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + return; + + default: + O << "<unknown operand type: " << MO.getType() << ">"; + return; + } +} + +/// EmitFunctionBodyStart - Targets can override this to emit stuff before +/// the first basic block in the function. +void AlphaAsmPrinter::EmitFunctionBodyStart() { + OutStreamer.EmitRawText("\t.ent " + Twine(CurrentFnSym->getName())); +} + +/// EmitFunctionBodyEnd - Targets can override this to emit stuff after +/// the last basic block in the function. +void AlphaAsmPrinter::EmitFunctionBodyEnd() { + OutStreamer.EmitRawText("\t.end " + Twine(CurrentFnSym->getName())); +} + +void AlphaAsmPrinter::EmitStartOfAsmFile(Module &M) { + OutStreamer.EmitRawText(StringRef("\t.arch ev6")); + OutStreamer.EmitRawText(StringRef("\t.set noat")); +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + printOperand(MI, OpNo, O); + return false; +} + +bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + O << "0("; + printOperand(MI, OpNo, O); + O << ")"; + return false; +} + +// Force static initialization. +extern "C" void LLVMInitializeAlphaAsmPrinter() { + RegisterAsmPrinter<AlphaAsmPrinter> X(TheAlphaTarget); +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaBranchSelector.cpp b/contrib/llvm/lib/Target/Alpha/AlphaBranchSelector.cpp new file mode 100644 index 0000000..3768117 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaBranchSelector.cpp @@ -0,0 +1,66 @@ +//===-- AlphaBranchSelector.cpp - Convert Pseudo branchs ----------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Replace Pseudo COND_BRANCH_* with their appropriate real branch +// Simplified version of the PPC Branch Selector +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +#include "AlphaInstrInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/MC/MCAsmInfo.h" +using namespace llvm; + +namespace { + struct AlphaBSel : public MachineFunctionPass { + static char ID; + AlphaBSel() : MachineFunctionPass(ID) {} + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "Alpha Branch Selection"; + } + }; + char AlphaBSel::ID = 0; +} + +/// createAlphaBranchSelectionPass - returns an instance of the Branch Selection +/// Pass +/// +FunctionPass *llvm::createAlphaBranchSelectionPass() { + return new AlphaBSel(); +} + +bool AlphaBSel::runOnMachineFunction(MachineFunction &Fn) { + + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock *MBB = MFI; + + for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end(); + MBBI != EE; ++MBBI) { + if (MBBI->getOpcode() == Alpha::COND_BRANCH_I || + MBBI->getOpcode() == Alpha::COND_BRANCH_F) { + + // condbranch operands: + // 0. bc opcode + // 1. reg + // 2. target MBB + const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); + MBBI->setDesc(TII->get(MBBI->getOperand(0).getImm())); + } + } + } + + return true; +} + diff --git a/contrib/llvm/lib/Target/Alpha/AlphaCallingConv.td b/contrib/llvm/lib/Target/Alpha/AlphaCallingConv.td new file mode 100644 index 0000000..bde8819 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaCallingConv.td @@ -0,0 +1,38 @@ +//===- AlphaCallingConv.td - Calling Conventions for Alpha -*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This describes the calling conventions for Alpha architecture. +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Alpha Return Value Calling Convention +//===----------------------------------------------------------------------===// +def RetCC_Alpha : CallingConv<[ + // i64 is returned in register R0 + // R1 is an llvm extension, I don't know what gcc does + CCIfType<[i64], CCAssignToReg<[R0,R1]>>, + + // f32 / f64 are returned in F0/F1 + CCIfType<[f32, f64], CCAssignToReg<[F0, F1]>> +]>; + +//===----------------------------------------------------------------------===// +// Alpha Argument Calling Conventions +//===----------------------------------------------------------------------===// +def CC_Alpha : CallingConv<[ + // The first 6 arguments are passed in registers, whether integer or + // floating-point + CCIfType<[i64], CCAssignToRegWithShadow<[R16, R17, R18, R19, R20, R21], + [F16, F17, F18, F19, F20, F21]>>, + + CCIfType<[f32, f64], CCAssignToRegWithShadow<[F16, F17, F18, F19, F20, F21], + [R16, R17, R18, R19, R20, R21]>>, + + // Stack slots are 8 bytes in size and 8-byte aligned. + CCIfType<[i64, f32, f64], CCAssignToStack<8, 8>> +]>; diff --git a/contrib/llvm/lib/Target/Alpha/AlphaFrameLowering.cpp b/contrib/llvm/lib/Target/Alpha/AlphaFrameLowering.cpp new file mode 100644 index 0000000..690cd1d --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaFrameLowering.cpp @@ -0,0 +1,143 @@ +//=====- AlphaFrameLowering.cpp - Alpha Frame Information ------*- C++ -*-====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Alpha implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "AlphaFrameLowering.h" +#include "AlphaInstrInfo.h" +#include "AlphaMachineFunctionInfo.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/ADT/Twine.h" + +using namespace llvm; + +static long getUpper16(long l) { + long y = l / Alpha::IMM_MULT; + if (l % Alpha::IMM_MULT > Alpha::IMM_HIGH) + ++y; + return y; +} + +static long getLower16(long l) { + long h = getUpper16(l); + return l - h * Alpha::IMM_MULT; +} + +// 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. +// +bool AlphaFrameLowering::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return MFI->hasVarSizedObjects(); +} + +void AlphaFrameLowering::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + DebugLoc dl = (MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc()); + bool FP = hasFP(MF); + + // Handle GOP offset + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAHg), Alpha::R29) + .addGlobalAddress(MF.getFunction()).addReg(Alpha::R27).addImm(++curgpdist); + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAg), Alpha::R29) + .addGlobalAddress(MF.getFunction()).addReg(Alpha::R29).addImm(curgpdist); + + BuildMI(MBB, MBBI, dl, TII.get(Alpha::ALTENT)) + .addGlobalAddress(MF.getFunction()); + + // Get the number of bytes to allocate from the FrameInfo + long NumBytes = MFI->getStackSize(); + + if (FP) + NumBytes += 8; //reserve space for the old FP + + // Do we need to allocate space on the stack? + if (NumBytes == 0) return; + + unsigned Align = getStackAlignment(); + NumBytes = (NumBytes+Align-1)/Align*Align; + + // Update frame info to pretend that this is part of the stack... + MFI->setStackSize(NumBytes); + + // adjust stack pointer: r30 -= numbytes + NumBytes = -NumBytes; + if (NumBytes >= Alpha::IMM_LOW) { + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30).addImm(NumBytes) + .addReg(Alpha::R30); + } else if (getUpper16(NumBytes) >= Alpha::IMM_LOW) { + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAH), Alpha::R30) + .addImm(getUpper16(NumBytes)).addReg(Alpha::R30); + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30) + .addImm(getLower16(NumBytes)).addReg(Alpha::R30); + } else { + report_fatal_error("Too big a stack frame at " + Twine(NumBytes)); + } + + // Now if we need to, save the old FP and set the new + if (FP) { + BuildMI(MBB, MBBI, dl, TII.get(Alpha::STQ)) + .addReg(Alpha::R15).addImm(0).addReg(Alpha::R30); + // This must be the last instr in the prolog + BuildMI(MBB, MBBI, dl, TII.get(Alpha::BISr), Alpha::R15) + .addReg(Alpha::R30).addReg(Alpha::R30); + } + +} + +void AlphaFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + assert((MBBI->getOpcode() == Alpha::RETDAG || + MBBI->getOpcode() == Alpha::RETDAGp) + && "Can only insert epilog into returning blocks"); + DebugLoc dl = MBBI->getDebugLoc(); + + bool FP = hasFP(MF); + + // Get the number of bytes allocated from the FrameInfo... + long NumBytes = MFI->getStackSize(); + + //now if we need to, restore the old FP + if (FP) { + //copy the FP into the SP (discards allocas) + BuildMI(MBB, MBBI, dl, TII.get(Alpha::BISr), Alpha::R30).addReg(Alpha::R15) + .addReg(Alpha::R15); + //restore the FP + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDQ), Alpha::R15) + .addImm(0).addReg(Alpha::R15); + } + + if (NumBytes != 0) { + if (NumBytes <= Alpha::IMM_HIGH) { + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30).addImm(NumBytes) + .addReg(Alpha::R30); + } else if (getUpper16(NumBytes) <= Alpha::IMM_HIGH) { + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAH), Alpha::R30) + .addImm(getUpper16(NumBytes)).addReg(Alpha::R30); + BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30) + .addImm(getLower16(NumBytes)).addReg(Alpha::R30); + } else { + report_fatal_error("Too big a stack frame at " + Twine(NumBytes)); + } + } +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaFrameLowering.h b/contrib/llvm/lib/Target/Alpha/AlphaFrameLowering.h new file mode 100644 index 0000000..ebd9e1b --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaFrameLowering.h @@ -0,0 +1,43 @@ +//==-- AlphaFrameLowering.h - Define frame lowering for Alpha --*- C++ -*---==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHA_FRAMEINFO_H +#define ALPHA_FRAMEINFO_H + +#include "Alpha.h" +#include "AlphaSubtarget.h" +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { + class AlphaSubtarget; + +class AlphaFrameLowering : public TargetFrameLowering { + const AlphaSubtarget &STI; + // FIXME: This should end in MachineFunctionInfo, not here! + mutable int curgpdist; +public: + explicit AlphaFrameLowering(const AlphaSubtarget &sti) + : TargetFrameLowering(StackGrowsDown, 16, 0), STI(sti), curgpdist(0) { + } + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + bool hasFP(const MachineFunction &MF) const; +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/AlphaISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Alpha/AlphaISelDAGToDAG.cpp new file mode 100644 index 0000000..f877c65 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaISelDAGToDAG.cpp @@ -0,0 +1,425 @@ +//===-- AlphaISelDAGToDAG.cpp - Alpha pattern matching inst selector ------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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, +// converting from a legalized dag to a Alpha dag. +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +#include "AlphaTargetMachine.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalValue.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +using namespace llvm; + +namespace { + + //===--------------------------------------------------------------------===// + /// AlphaDAGToDAGISel - Alpha specific code to select Alpha machine + /// instructions for SelectionDAG operations. + class AlphaDAGToDAGISel : public SelectionDAGISel { + static const int64_t IMM_LOW = -32768; + static const int64_t IMM_HIGH = 32767; + static const int64_t IMM_MULT = 65536; + static const int64_t IMM_FULLHIGH = IMM_HIGH + IMM_HIGH * IMM_MULT; + static const int64_t IMM_FULLLOW = IMM_LOW + IMM_LOW * IMM_MULT; + + static int64_t get_ldah16(int64_t x) { + int64_t y = x / IMM_MULT; + if (x % IMM_MULT > IMM_HIGH) + ++y; + return y; + } + + static int64_t get_lda16(int64_t x) { + return x - get_ldah16(x) * IMM_MULT; + } + + /// get_zapImm - Return a zap mask if X is a valid immediate for a zapnot + /// instruction (if not, return 0). Note that this code accepts partial + /// zap masks. For example (and LHS, 1) is a valid zap, as long we know + /// that the bits 1-7 of LHS are already zero. If LHS is non-null, we are + /// in checking mode. If LHS is null, we assume that the mask has already + /// been validated before. + uint64_t get_zapImm(SDValue LHS, uint64_t Constant) const { + uint64_t BitsToCheck = 0; + unsigned Result = 0; + for (unsigned i = 0; i != 8; ++i) { + if (((Constant >> 8*i) & 0xFF) == 0) { + // nothing to do. + } else { + Result |= 1 << i; + if (((Constant >> 8*i) & 0xFF) == 0xFF) { + // If the entire byte is set, zapnot the byte. + } else if (LHS.getNode() == 0) { + // Otherwise, if the mask was previously validated, we know its okay + // to zapnot this entire byte even though all the bits aren't set. + } else { + // Otherwise we don't know that the it's okay to zapnot this entire + // byte. Only do this iff we can prove that the missing bits are + // already null, so the bytezap doesn't need to really null them. + BitsToCheck |= ~Constant & (0xFFULL << 8*i); + } + } + } + + // If there are missing bits in a byte (for example, X & 0xEF00), check to + // see if the missing bits (0x1000) are already known zero if not, the zap + // isn't okay to do, as it won't clear all the required bits. + if (BitsToCheck && + !CurDAG->MaskedValueIsZero(LHS, + APInt(LHS.getValueSizeInBits(), + BitsToCheck))) + return 0; + + return Result; + } + + static uint64_t get_zapImm(uint64_t x) { + unsigned build = 0; + for(int i = 0; i != 8; ++i) { + if ((x & 0x00FF) == 0x00FF) + build |= 1 << i; + else if ((x & 0x00FF) != 0) + return 0; + x >>= 8; + } + return build; + } + + + static uint64_t getNearPower2(uint64_t x) { + if (!x) return 0; + unsigned at = CountLeadingZeros_64(x); + uint64_t complow = 1ULL << (63 - at); + uint64_t comphigh = complow << 1; + if (x - complow <= comphigh - x) + return complow; + else + return comphigh; + } + + static bool chkRemNearPower2(uint64_t x, uint64_t r, bool swap) { + uint64_t y = getNearPower2(x); + if (swap) + return (y - x) == r; + else + return (x - y) == r; + } + + public: + explicit AlphaDAGToDAGISel(AlphaTargetMachine &TM) + : SelectionDAGISel(TM) + {} + + /// getI64Imm - Return a target constant with the specified value, of type + /// i64. + inline SDValue getI64Imm(int64_t Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i64); + } + + // Select - Convert the specified operand from a target-independent to a + // target-specific node if it hasn't already been changed. + SDNode *Select(SDNode *N); + + virtual const char *getPassName() const { + return "Alpha DAG->DAG Pattern Instruction Selection"; + } + + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for + /// inline asm expressions. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector<SDValue> &OutOps) { + SDValue Op0; + switch (ConstraintCode) { + default: return true; + case 'm': // memory + Op0 = Op; + break; + } + + OutOps.push_back(Op0); + return false; + } + +// Include the pieces autogenerated from the target description. +#include "AlphaGenDAGISel.inc" + +private: + /// getTargetMachine - Return a reference to the TargetMachine, casted + /// to the target-specific type. + const AlphaTargetMachine &getTargetMachine() { + return static_cast<const AlphaTargetMachine &>(TM); + } + + /// getInstrInfo - Return a reference to the TargetInstrInfo, casted + /// to the target-specific type. + const AlphaInstrInfo *getInstrInfo() { + return getTargetMachine().getInstrInfo(); + } + + SDNode *getGlobalBaseReg(); + SDNode *getGlobalRetAddr(); + void SelectCALL(SDNode *Op); + + }; +} + +/// getGlobalBaseReg - Output the instructions required to put the +/// GOT address into a register. +/// +SDNode *AlphaDAGToDAGISel::getGlobalBaseReg() { + unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); + return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); +} + +/// getGlobalRetAddr - Grab the return address. +/// +SDNode *AlphaDAGToDAGISel::getGlobalRetAddr() { + unsigned GlobalRetAddr = getInstrInfo()->getGlobalRetAddr(MF); + return CurDAG->getRegister(GlobalRetAddr, TLI.getPointerTy()).getNode(); +} + +// Select - Convert the specified operand from a target-independent to a +// target-specific node if it hasn't already been changed. +SDNode *AlphaDAGToDAGISel::Select(SDNode *N) { + if (N->isMachineOpcode()) + return NULL; // Already selected. + DebugLoc dl = N->getDebugLoc(); + + switch (N->getOpcode()) { + default: break; + case AlphaISD::CALL: + SelectCALL(N); + return NULL; + + case ISD::FrameIndex: { + int FI = cast<FrameIndexSDNode>(N)->getIndex(); + return CurDAG->SelectNodeTo(N, Alpha::LDA, MVT::i64, + CurDAG->getTargetFrameIndex(FI, MVT::i32), + getI64Imm(0)); + } + case ISD::GLOBAL_OFFSET_TABLE: + return getGlobalBaseReg(); + case AlphaISD::GlobalRetAddr: + return getGlobalRetAddr(); + + case AlphaISD::DivCall: { + SDValue Chain = CurDAG->getEntryNode(); + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + Chain = CurDAG->getCopyToReg(Chain, dl, Alpha::R24, N1, + SDValue(0,0)); + Chain = CurDAG->getCopyToReg(Chain, dl, Alpha::R25, N2, + Chain.getValue(1)); + Chain = CurDAG->getCopyToReg(Chain, dl, Alpha::R27, N0, + Chain.getValue(1)); + SDNode *CNode = + CurDAG->getMachineNode(Alpha::JSRs, dl, MVT::Other, MVT::Glue, + Chain, Chain.getValue(1)); + Chain = CurDAG->getCopyFromReg(Chain, dl, Alpha::R27, MVT::i64, + SDValue(CNode, 1)); + return CurDAG->SelectNodeTo(N, Alpha::BISr, MVT::i64, Chain, Chain); + } + + case ISD::READCYCLECOUNTER: { + SDValue Chain = N->getOperand(0); + return CurDAG->getMachineNode(Alpha::RPCC, dl, MVT::i64, MVT::Other, + Chain); + } + + case ISD::Constant: { + uint64_t uval = cast<ConstantSDNode>(N)->getZExtValue(); + + if (uval == 0) { + SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, + Alpha::R31, MVT::i64); + ReplaceUses(SDValue(N, 0), Result); + return NULL; + } + + int64_t val = (int64_t)uval; + int32_t val32 = (int32_t)val; + if (val <= IMM_HIGH + IMM_HIGH * IMM_MULT && + val >= IMM_LOW + IMM_LOW * IMM_MULT) + break; //(LDAH (LDA)) + if ((uval >> 32) == 0 && //empty upper bits + val32 <= IMM_HIGH + IMM_HIGH * IMM_MULT) + // val32 >= IMM_LOW + IMM_LOW * IMM_MULT) //always true + break; //(zext (LDAH (LDA))) + //Else use the constant pool + ConstantInt *C = ConstantInt::get( + Type::getInt64Ty(*CurDAG->getContext()), uval); + SDValue CPI = CurDAG->getTargetConstantPool(C, MVT::i64); + SDNode *Tmp = CurDAG->getMachineNode(Alpha::LDAHr, dl, MVT::i64, CPI, + SDValue(getGlobalBaseReg(), 0)); + return CurDAG->SelectNodeTo(N, Alpha::LDQr, MVT::i64, MVT::Other, + CPI, SDValue(Tmp, 0), CurDAG->getEntryNode()); + } + case ISD::TargetConstantFP: + case ISD::ConstantFP: { + ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N); + bool isDouble = N->getValueType(0) == MVT::f64; + EVT T = isDouble ? MVT::f64 : MVT::f32; + if (CN->getValueAPF().isPosZero()) { + return CurDAG->SelectNodeTo(N, isDouble ? Alpha::CPYST : Alpha::CPYSS, + T, CurDAG->getRegister(Alpha::F31, T), + CurDAG->getRegister(Alpha::F31, T)); + } else if (CN->getValueAPF().isNegZero()) { + return CurDAG->SelectNodeTo(N, isDouble ? Alpha::CPYSNT : Alpha::CPYSNS, + T, CurDAG->getRegister(Alpha::F31, T), + CurDAG->getRegister(Alpha::F31, T)); + } else { + report_fatal_error("Unhandled FP constant type"); + } + break; + } + + case ISD::SETCC: + if (N->getOperand(0).getNode()->getValueType(0).isFloatingPoint()) { + ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); + + unsigned Opc = Alpha::WTF; + bool rev = false; + bool inv = false; + switch(CC) { + default: DEBUG(N->dump(CurDAG)); llvm_unreachable("Unknown FP comparison!"); + case ISD::SETEQ: case ISD::SETOEQ: case ISD::SETUEQ: + Opc = Alpha::CMPTEQ; break; + case ISD::SETLT: case ISD::SETOLT: case ISD::SETULT: + Opc = Alpha::CMPTLT; break; + case ISD::SETLE: case ISD::SETOLE: case ISD::SETULE: + Opc = Alpha::CMPTLE; break; + case ISD::SETGT: case ISD::SETOGT: case ISD::SETUGT: + Opc = Alpha::CMPTLT; rev = true; break; + case ISD::SETGE: case ISD::SETOGE: case ISD::SETUGE: + Opc = Alpha::CMPTLE; rev = true; break; + case ISD::SETNE: case ISD::SETONE: case ISD::SETUNE: + Opc = Alpha::CMPTEQ; inv = true; break; + case ISD::SETO: + Opc = Alpha::CMPTUN; inv = true; break; + case ISD::SETUO: + Opc = Alpha::CMPTUN; break; + }; + SDValue tmp1 = N->getOperand(rev?1:0); + SDValue tmp2 = N->getOperand(rev?0:1); + SDNode *cmp = CurDAG->getMachineNode(Opc, dl, MVT::f64, tmp1, tmp2); + if (inv) + cmp = CurDAG->getMachineNode(Alpha::CMPTEQ, dl, + MVT::f64, SDValue(cmp, 0), + CurDAG->getRegister(Alpha::F31, MVT::f64)); + switch(CC) { + case ISD::SETUEQ: case ISD::SETULT: case ISD::SETULE: + case ISD::SETUNE: case ISD::SETUGT: case ISD::SETUGE: + { + SDNode* cmp2 = CurDAG->getMachineNode(Alpha::CMPTUN, dl, MVT::f64, + tmp1, tmp2); + cmp = CurDAG->getMachineNode(Alpha::ADDT, dl, MVT::f64, + SDValue(cmp2, 0), SDValue(cmp, 0)); + break; + } + default: break; + } + + SDNode* LD = CurDAG->getMachineNode(Alpha::FTOIT, dl, + MVT::i64, SDValue(cmp, 0)); + return CurDAG->getMachineNode(Alpha::CMPULT, dl, MVT::i64, + CurDAG->getRegister(Alpha::R31, MVT::i64), + SDValue(LD,0)); + } + break; + + case ISD::AND: { + ConstantSDNode* SC = NULL; + ConstantSDNode* MC = NULL; + if (N->getOperand(0).getOpcode() == ISD::SRL && + (MC = dyn_cast<ConstantSDNode>(N->getOperand(1))) && + (SC = dyn_cast<ConstantSDNode>(N->getOperand(0).getOperand(1)))) { + uint64_t sval = SC->getZExtValue(); + uint64_t mval = MC->getZExtValue(); + // If the result is a zap, let the autogened stuff handle it. + if (get_zapImm(N->getOperand(0), mval)) + break; + // given mask X, and shift S, we want to see if there is any zap in the + // mask if we play around with the botton S bits + uint64_t dontcare = (~0ULL) >> (64 - sval); + uint64_t mask = mval << sval; + + if (get_zapImm(mask | dontcare)) + mask = mask | dontcare; + + if (get_zapImm(mask)) { + SDValue Z = + SDValue(CurDAG->getMachineNode(Alpha::ZAPNOTi, dl, MVT::i64, + N->getOperand(0).getOperand(0), + getI64Imm(get_zapImm(mask))), 0); + return CurDAG->getMachineNode(Alpha::SRLr, dl, MVT::i64, Z, + getI64Imm(sval)); + } + } + break; + } + + } + + return SelectCode(N); +} + +void AlphaDAGToDAGISel::SelectCALL(SDNode *N) { + //TODO: add flag stuff to prevent nondeturministic breakage! + + SDValue Chain = N->getOperand(0); + SDValue Addr = N->getOperand(1); + SDValue InFlag = N->getOperand(N->getNumOperands() - 1); + DebugLoc dl = N->getDebugLoc(); + + if (Addr.getOpcode() == AlphaISD::GPRelLo) { + SDValue GOT = SDValue(getGlobalBaseReg(), 0); + Chain = CurDAG->getCopyToReg(Chain, dl, Alpha::R29, GOT, InFlag); + InFlag = Chain.getValue(1); + Chain = SDValue(CurDAG->getMachineNode(Alpha::BSR, dl, MVT::Other, + MVT::Glue, Addr.getOperand(0), + Chain, InFlag), 0); + } else { + Chain = CurDAG->getCopyToReg(Chain, dl, Alpha::R27, Addr, InFlag); + InFlag = Chain.getValue(1); + Chain = SDValue(CurDAG->getMachineNode(Alpha::JSR, dl, MVT::Other, + MVT::Glue, Chain, InFlag), 0); + } + InFlag = Chain.getValue(1); + + ReplaceUses(SDValue(N, 0), Chain); + ReplaceUses(SDValue(N, 1), InFlag); +} + + +/// createAlphaISelDag - This pass converts a legalized DAG into a +/// Alpha-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createAlphaISelDag(AlphaTargetMachine &TM) { + return new AlphaDAGToDAGISel(TM); +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp new file mode 100644 index 0000000..3057eb8 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp @@ -0,0 +1,962 @@ +//===-- AlphaISelLowering.cpp - Alpha DAG Lowering Implementation ---------===// +// +// 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 AlphaISelLowering class. +// +//===----------------------------------------------------------------------===// + +#include "AlphaISelLowering.h" +#include "AlphaTargetMachine.h" +#include "AlphaMachineFunctionInfo.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/Intrinsics.h" +#include "llvm/Type.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// AddLiveIn - This helper function adds the specified physical register to the +/// MachineFunction as a live in value. It also creates a corresponding virtual +/// register for it. +static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, + TargetRegisterClass *RC) { + assert(RC->contains(PReg) && "Not the correct regclass!"); + unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); + MF.getRegInfo().addLiveIn(PReg, VReg); + return VReg; +} + +AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) + : TargetLowering(TM, new TargetLoweringObjectFileELF()) { + // Set up the TargetLowering object. + //I am having problems with shr n i8 1 + setBooleanContents(ZeroOrOneBooleanContent); + setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? + + addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass); + addRegisterClass(MVT::f64, Alpha::F8RCRegisterClass); + addRegisterClass(MVT::f32, Alpha::F4RCRegisterClass); + + // We want to custom lower some of our intrinsics. + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + + setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + + setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Expand); + + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + + // setOperationAction(ISD::BRIND, MVT::Other, Expand); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); + + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + setOperationAction(ISD::FREM, MVT::f32, Expand); + setOperationAction(ISD::FREM, MVT::f64, Expand); + + setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); + setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); + setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); + setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); + + if (!TM.getSubtarget<AlphaSubtarget>().hasCT()) { + setOperationAction(ISD::CTPOP , MVT::i64 , Expand); + setOperationAction(ISD::CTTZ , MVT::i64 , Expand); + setOperationAction(ISD::CTLZ , MVT::i64 , Expand); + } + setOperationAction(ISD::BSWAP , MVT::i64, Expand); + setOperationAction(ISD::ROTL , MVT::i64, Expand); + setOperationAction(ISD::ROTR , MVT::i64, Expand); + + setOperationAction(ISD::SREM , MVT::i64, Custom); + setOperationAction(ISD::UREM , MVT::i64, Custom); + setOperationAction(ISD::SDIV , MVT::i64, Custom); + setOperationAction(ISD::UDIV , MVT::i64, Custom); + + setOperationAction(ISD::ADDC , MVT::i64, Expand); + setOperationAction(ISD::ADDE , MVT::i64, Expand); + setOperationAction(ISD::SUBC , MVT::i64, Expand); + setOperationAction(ISD::SUBE , MVT::i64, Expand); + + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + + setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand); + setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand); + + // We don't support sin/cos/sqrt/pow + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + + setOperationAction(ISD::FSQRT, MVT::f64, Expand); + setOperationAction(ISD::FSQRT, MVT::f32, Expand); + + setOperationAction(ISD::FPOW , MVT::f32, Expand); + setOperationAction(ISD::FPOW , MVT::f64, Expand); + + setOperationAction(ISD::FMA, MVT::f64, Expand); + setOperationAction(ISD::FMA, MVT::f32, Expand); + + setOperationAction(ISD::SETCC, MVT::f32, Promote); + + setOperationAction(ISD::BITCAST, MVT::f32, Promote); + + setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); + + // Not implemented yet. + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); + + // We want to legalize GlobalAddress and ConstantPool and + // ExternalSymbols nodes into the appropriate instructions to + // materialize the address. + setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); + setOperationAction(ISD::ConstantPool, MVT::i64, Custom); + setOperationAction(ISD::ExternalSymbol, MVT::i64, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); + + setOperationAction(ISD::VASTART, MVT::Other, Custom); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Custom); + setOperationAction(ISD::VAARG, MVT::Other, Custom); + setOperationAction(ISD::VAARG, MVT::i32, Custom); + + setOperationAction(ISD::JumpTable, MVT::i64, Custom); + setOperationAction(ISD::JumpTable, MVT::i32, Custom); + + setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand); + + setStackPointerRegisterToSaveRestore(Alpha::R30); + + setJumpBufSize(272); + setJumpBufAlignment(16); + + setMinFunctionAlignment(4); + + setInsertFencesForAtomic(true); + + computeRegisterProperties(); +} + +EVT AlphaTargetLowering::getSetCCResultType(EVT VT) const { + return MVT::i64; +} + +const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return 0; + case AlphaISD::CVTQT_: return "Alpha::CVTQT_"; + case AlphaISD::CVTQS_: return "Alpha::CVTQS_"; + case AlphaISD::CVTTQ_: return "Alpha::CVTTQ_"; + case AlphaISD::GPRelHi: return "Alpha::GPRelHi"; + case AlphaISD::GPRelLo: return "Alpha::GPRelLo"; + case AlphaISD::RelLit: return "Alpha::RelLit"; + case AlphaISD::GlobalRetAddr: return "Alpha::GlobalRetAddr"; + case AlphaISD::CALL: return "Alpha::CALL"; + case AlphaISD::DivCall: return "Alpha::DivCall"; + case AlphaISD::RET_FLAG: return "Alpha::RET_FLAG"; + case AlphaISD::COND_BRANCH_I: return "Alpha::COND_BRANCH_I"; + case AlphaISD::COND_BRANCH_F: return "Alpha::COND_BRANCH_F"; + } +} + +static SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) { + EVT PtrVT = Op.getValueType(); + JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); + SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); + // FIXME there isn't really any debug info here + DebugLoc dl = Op.getDebugLoc(); + + SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, dl, MVT::i64, JTI, + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); + SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, JTI, Hi); + return Lo; +} + +//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) + +// //#define FP $15 +// //#define RA $26 +// //#define PV $27 +// //#define GP $29 +// //#define SP $30 + +#include "AlphaGenCallingConv.inc" + +SDValue +AlphaTargetLowering::LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const { + // Alpha target does not yet support tail call optimization. + isTailCall = false; + + // Analyze operands of the call, assigning locations to each operand. + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), ArgLocs, *DAG.getContext()); + + CCInfo.AnalyzeCallOperands(Outs, CC_Alpha); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + + Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes, + getPointerTy(), true)); + + SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; + SmallVector<SDValue, 12> MemOpChains; + SDValue StackPtr; + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + SDValue Arg = OutVals[i]; + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: assert(0 && "Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + break; + } + + // Arguments that can be passed on register must be kept at RegsToPass + // vector + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + assert(VA.isMemLoc()); + + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, Alpha::R30, MVT::i64); + + SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), + StackPtr, + DAG.getIntPtrConstant(VA.getLocMemOffset())); + + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo(),false, false, 0)); + } + } + + // Transform all store nodes into one single node because all store nodes are + // independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token chain and + // flag operands which copy the outgoing args into registers. The InFlag in + // necessary since all emitted instructions must be stuck together. + SDValue InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // Returns a chain & a flag for retval copy to use. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + SmallVector<SDValue, 8> Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are + // known live into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + if (InFlag.getNode()) + Ops.push_back(InFlag); + + Chain = DAG.getNode(AlphaISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Create the CALLSEQ_END node. + Chain = DAG.getCALLSEQ_END(Chain, + DAG.getConstant(NumBytes, getPointerTy(), true), + DAG.getConstant(0, getPointerTy(), true), + InFlag); + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, + Ins, dl, DAG, InVals); +} + +/// LowerCallResult - Lower the result values of a call into the +/// appropriate copies out of appropriate physical registers. +/// +SDValue +AlphaTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const { + + // Assign locations to each value returned by this call. + SmallVector<CCValAssign, 16> RVLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); + + CCInfo.AnalyzeCallResult(Ins, RetCC_Alpha); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + + Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), + VA.getLocVT(), InFlag).getValue(1); + SDValue RetValue = Chain.getValue(0); + InFlag = Chain.getValue(2); + + // If this is an 8/16/32-bit value, it is really passed promoted to 64 + // bits. Insert an assert[sz]ext to capture this, then truncate to the + // right size. + if (VA.getLocInfo() == CCValAssign::SExt) + RetValue = DAG.getNode(ISD::AssertSext, dl, VA.getLocVT(), RetValue, + DAG.getValueType(VA.getValVT())); + else if (VA.getLocInfo() == CCValAssign::ZExt) + RetValue = DAG.getNode(ISD::AssertZext, dl, VA.getLocVT(), RetValue, + DAG.getValueType(VA.getValVT())); + + if (VA.getLocInfo() != CCValAssign::Full) + RetValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RetValue); + + InVals.push_back(RetValue); + } + + return Chain; +} + +SDValue +AlphaTargetLowering::LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> + &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) + const { + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + AlphaMachineFunctionInfo *FuncInfo = MF.getInfo<AlphaMachineFunctionInfo>(); + + unsigned args_int[] = { + Alpha::R16, Alpha::R17, Alpha::R18, Alpha::R19, Alpha::R20, Alpha::R21}; + unsigned args_float[] = { + Alpha::F16, Alpha::F17, Alpha::F18, Alpha::F19, Alpha::F20, Alpha::F21}; + + for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) { + SDValue argt; + EVT ObjectVT = Ins[ArgNo].VT; + SDValue ArgVal; + + if (ArgNo < 6) { + switch (ObjectVT.getSimpleVT().SimpleTy) { + default: + assert(false && "Invalid value type!"); + case MVT::f64: + args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], + &Alpha::F8RCRegClass); + ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT); + break; + case MVT::f32: + args_float[ArgNo] = AddLiveIn(MF, args_float[ArgNo], + &Alpha::F4RCRegClass); + ArgVal = DAG.getCopyFromReg(Chain, dl, args_float[ArgNo], ObjectVT); + break; + case MVT::i64: + args_int[ArgNo] = AddLiveIn(MF, args_int[ArgNo], + &Alpha::GPRCRegClass); + ArgVal = DAG.getCopyFromReg(Chain, dl, args_int[ArgNo], MVT::i64); + break; + } + } else { //more args + // Create the frame index object for this incoming parameter... + int FI = MFI->CreateFixedObject(8, 8 * (ArgNo - 6), true); + + // Create the SelectionDAG nodes corresponding to a load + //from this parameter + SDValue FIN = DAG.getFrameIndex(FI, MVT::i64); + ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, MachinePointerInfo(), + false, false, 0); + } + InVals.push_back(ArgVal); + } + + // If the functions takes variable number of arguments, copy all regs to stack + if (isVarArg) { + FuncInfo->setVarArgsOffset(Ins.size() * 8); + std::vector<SDValue> LS; + for (int i = 0; i < 6; ++i) { + if (TargetRegisterInfo::isPhysicalRegister(args_int[i])) + args_int[i] = AddLiveIn(MF, args_int[i], &Alpha::GPRCRegClass); + SDValue argt = DAG.getCopyFromReg(Chain, dl, args_int[i], MVT::i64); + int FI = MFI->CreateFixedObject(8, -8 * (6 - i), true); + if (i == 0) FuncInfo->setVarArgsBase(FI); + SDValue SDFI = DAG.getFrameIndex(FI, MVT::i64); + LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, MachinePointerInfo(), + false, false, 0)); + + if (TargetRegisterInfo::isPhysicalRegister(args_float[i])) + args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass); + argt = DAG.getCopyFromReg(Chain, dl, args_float[i], MVT::f64); + FI = MFI->CreateFixedObject(8, - 8 * (12 - i), true); + SDFI = DAG.getFrameIndex(FI, MVT::i64); + LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, MachinePointerInfo(), + false, false, 0)); + } + + //Set up a token factor with all the stack traffic + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &LS[0], LS.size()); + } + + return Chain; +} + +SDValue +AlphaTargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + DebugLoc dl, SelectionDAG &DAG) const { + + SDValue Copy = DAG.getCopyToReg(Chain, dl, Alpha::R26, + DAG.getNode(AlphaISD::GlobalRetAddr, + DebugLoc(), MVT::i64), + SDValue()); + switch (Outs.size()) { + default: + llvm_unreachable("Do not know how to return this many arguments!"); + case 0: + break; + //return SDValue(); // ret void is legal + case 1: { + EVT ArgVT = Outs[0].VT; + unsigned ArgReg; + if (ArgVT.isInteger()) + ArgReg = Alpha::R0; + else { + assert(ArgVT.isFloatingPoint()); + ArgReg = Alpha::F0; + } + Copy = DAG.getCopyToReg(Copy, dl, ArgReg, + OutVals[0], Copy.getValue(1)); + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) + DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg); + break; + } + case 2: { + EVT ArgVT = Outs[0].VT; + unsigned ArgReg1, ArgReg2; + if (ArgVT.isInteger()) { + ArgReg1 = Alpha::R0; + ArgReg2 = Alpha::R1; + } else { + assert(ArgVT.isFloatingPoint()); + ArgReg1 = Alpha::F0; + ArgReg2 = Alpha::F1; + } + Copy = DAG.getCopyToReg(Copy, dl, ArgReg1, + OutVals[0], Copy.getValue(1)); + if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(), + DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg1) + == DAG.getMachineFunction().getRegInfo().liveout_end()) + DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg1); + Copy = DAG.getCopyToReg(Copy, dl, ArgReg2, + OutVals[1], Copy.getValue(1)); + if (std::find(DAG.getMachineFunction().getRegInfo().liveout_begin(), + DAG.getMachineFunction().getRegInfo().liveout_end(), ArgReg2) + == DAG.getMachineFunction().getRegInfo().liveout_end()) + DAG.getMachineFunction().getRegInfo().addLiveOut(ArgReg2); + break; + } + } + return DAG.getNode(AlphaISD::RET_FLAG, dl, + MVT::Other, Copy, Copy.getValue(1)); +} + +void AlphaTargetLowering::LowerVAARG(SDNode *N, SDValue &Chain, + SDValue &DataPtr, + SelectionDAG &DAG) const { + Chain = N->getOperand(0); + SDValue VAListP = N->getOperand(1); + const Value *VAListS = cast<SrcValueSDNode>(N->getOperand(2))->getValue(); + DebugLoc dl = N->getDebugLoc(); + + SDValue Base = DAG.getLoad(MVT::i64, dl, Chain, VAListP, + MachinePointerInfo(VAListS), + false, false, 0); + SDValue Tmp = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP, + DAG.getConstant(8, MVT::i64)); + SDValue Offset = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Base.getValue(1), + Tmp, MachinePointerInfo(), + MVT::i32, false, false, 0); + DataPtr = DAG.getNode(ISD::ADD, dl, MVT::i64, Base, Offset); + if (N->getValueType(0).isFloatingPoint()) + { + //if fp && Offset < 6*8, then subtract 6*8 from DataPtr + SDValue FPDataPtr = DAG.getNode(ISD::SUB, dl, MVT::i64, DataPtr, + DAG.getConstant(8*6, MVT::i64)); + SDValue CC = DAG.getSetCC(dl, MVT::i64, Offset, + DAG.getConstant(8*6, MVT::i64), ISD::SETLT); + DataPtr = DAG.getNode(ISD::SELECT, dl, MVT::i64, CC, FPDataPtr, DataPtr); + } + + SDValue NewOffset = DAG.getNode(ISD::ADD, dl, MVT::i64, Offset, + DAG.getConstant(8, MVT::i64)); + Chain = DAG.getTruncStore(Offset.getValue(1), dl, NewOffset, Tmp, + MachinePointerInfo(), + MVT::i32, false, false, 0); +} + +/// LowerOperation - Provide custom lowering hooks for some operations. +/// +SDValue AlphaTargetLowering::LowerOperation(SDValue Op, + SelectionDAG &DAG) const { + DebugLoc dl = Op.getDebugLoc(); + switch (Op.getOpcode()) { + default: llvm_unreachable("Wasn't expecting to be able to lower this!"); + case ISD::JumpTable: return LowerJumpTable(Op, DAG); + + case ISD::INTRINSIC_WO_CHAIN: { + unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); + switch (IntNo) { + default: break; // Don't custom lower most intrinsics. + case Intrinsic::alpha_umulh: + return DAG.getNode(ISD::MULHU, dl, MVT::i64, + Op.getOperand(1), Op.getOperand(2)); + } + } + + case ISD::SRL_PARTS: { + SDValue ShOpLo = Op.getOperand(0); + SDValue ShOpHi = Op.getOperand(1); + SDValue ShAmt = Op.getOperand(2); + SDValue bm = DAG.getNode(ISD::SUB, dl, MVT::i64, + DAG.getConstant(64, MVT::i64), ShAmt); + SDValue BMCC = DAG.getSetCC(dl, MVT::i64, bm, + DAG.getConstant(0, MVT::i64), ISD::SETLE); + // if 64 - shAmt <= 0 + SDValue Hi_Neg = DAG.getConstant(0, MVT::i64); + SDValue ShAmt_Neg = DAG.getNode(ISD::SUB, dl, MVT::i64, + DAG.getConstant(0, MVT::i64), bm); + SDValue Lo_Neg = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpHi, ShAmt_Neg); + // else + SDValue carries = DAG.getNode(ISD::SHL, dl, MVT::i64, ShOpHi, bm); + SDValue Hi_Pos = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpHi, ShAmt); + SDValue Lo_Pos = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpLo, ShAmt); + Lo_Pos = DAG.getNode(ISD::OR, dl, MVT::i64, Lo_Pos, carries); + // Merge + SDValue Hi = DAG.getNode(ISD::SELECT, dl, MVT::i64, BMCC, Hi_Neg, Hi_Pos); + SDValue Lo = DAG.getNode(ISD::SELECT, dl, MVT::i64, BMCC, Lo_Neg, Lo_Pos); + SDValue Ops[2] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); + } + // case ISD::SRA_PARTS: + + // case ISD::SHL_PARTS: + + + case ISD::SINT_TO_FP: { + assert(Op.getOperand(0).getValueType() == MVT::i64 && + "Unhandled SINT_TO_FP type in custom expander!"); + SDValue LD; + bool isDouble = Op.getValueType() == MVT::f64; + LD = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Op.getOperand(0)); + SDValue FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, dl, + isDouble?MVT::f64:MVT::f32, LD); + return FP; + } + case ISD::FP_TO_SINT: { + bool isDouble = Op.getOperand(0).getValueType() == MVT::f64; + SDValue src = Op.getOperand(0); + + if (!isDouble) //Promote + src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, src); + + src = DAG.getNode(AlphaISD::CVTTQ_, dl, MVT::f64, src); + + return DAG.getNode(ISD::BITCAST, dl, MVT::i64, src); + } + case ISD::ConstantPool: { + ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); + const Constant *C = CP->getConstVal(); + SDValue CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment()); + // FIXME there isn't really any debug info here + + SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, dl, MVT::i64, CPI, + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); + SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, CPI, Hi); + return Lo; + } + case ISD::GlobalTLSAddress: + llvm_unreachable("TLS not implemented for Alpha."); + case ISD::GlobalAddress: { + GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); + const GlobalValue *GV = GSDN->getGlobal(); + SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i64, + GSDN->getOffset()); + // FIXME there isn't really any debug info here + + // if (!GV->hasWeakLinkage() && !GV->isDeclaration() + // && !GV->hasLinkOnceLinkage()) { + if (GV->hasLocalLinkage()) { + SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, dl, MVT::i64, GA, + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); + SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, GA, Hi); + return Lo; + } else + return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64, GA, + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); + } + case ISD::ExternalSymbol: { + return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64, + DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op) + ->getSymbol(), MVT::i64), + DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); + } + + case ISD::UREM: + case ISD::SREM: + //Expand only on constant case + if (Op.getOperand(1).getOpcode() == ISD::Constant) { + EVT VT = Op.getNode()->getValueType(0); + SDValue Tmp1 = Op.getNode()->getOpcode() == ISD::UREM ? + BuildUDIV(Op.getNode(), DAG, NULL) : + BuildSDIV(Op.getNode(), DAG, NULL); + Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Op.getOperand(1)); + Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Op.getOperand(0), Tmp1); + return Tmp1; + } + //fall through + case ISD::SDIV: + case ISD::UDIV: + if (Op.getValueType().isInteger()) { + if (Op.getOperand(1).getOpcode() == ISD::Constant) + return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.getNode(), DAG, NULL) + : BuildUDIV(Op.getNode(), DAG, NULL); + const char* opstr = 0; + switch (Op.getOpcode()) { + case ISD::UREM: opstr = "__remqu"; break; + case ISD::SREM: opstr = "__remq"; break; + case ISD::UDIV: opstr = "__divqu"; break; + case ISD::SDIV: opstr = "__divq"; break; + } + SDValue Tmp1 = Op.getOperand(0), + Tmp2 = Op.getOperand(1), + Addr = DAG.getExternalSymbol(opstr, MVT::i64); + return DAG.getNode(AlphaISD::DivCall, dl, MVT::i64, Addr, Tmp1, Tmp2); + } + break; + + case ISD::VAARG: { + SDValue Chain, DataPtr; + LowerVAARG(Op.getNode(), Chain, DataPtr, DAG); + + SDValue Result; + if (Op.getValueType() == MVT::i32) + Result = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Chain, DataPtr, + MachinePointerInfo(), MVT::i32, false, false, 0); + else + Result = DAG.getLoad(Op.getValueType(), dl, Chain, DataPtr, + MachinePointerInfo(), + false, false, 0); + return Result; + } + case ISD::VACOPY: { + SDValue Chain = Op.getOperand(0); + SDValue DestP = Op.getOperand(1); + SDValue SrcP = Op.getOperand(2); + const Value *DestS = cast<SrcValueSDNode>(Op.getOperand(3))->getValue(); + const Value *SrcS = cast<SrcValueSDNode>(Op.getOperand(4))->getValue(); + + SDValue Val = DAG.getLoad(getPointerTy(), dl, Chain, SrcP, + MachinePointerInfo(SrcS), + false, false, 0); + SDValue Result = DAG.getStore(Val.getValue(1), dl, Val, DestP, + MachinePointerInfo(DestS), + false, false, 0); + SDValue NP = DAG.getNode(ISD::ADD, dl, MVT::i64, SrcP, + DAG.getConstant(8, MVT::i64)); + Val = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Result, + NP, MachinePointerInfo(), MVT::i32, false, false, 0); + SDValue NPD = DAG.getNode(ISD::ADD, dl, MVT::i64, DestP, + DAG.getConstant(8, MVT::i64)); + return DAG.getTruncStore(Val.getValue(1), dl, Val, NPD, + MachinePointerInfo(), MVT::i32, + false, false, 0); + } + case ISD::VASTART: { + MachineFunction &MF = DAG.getMachineFunction(); + AlphaMachineFunctionInfo *FuncInfo = MF.getInfo<AlphaMachineFunctionInfo>(); + + SDValue Chain = Op.getOperand(0); + SDValue VAListP = Op.getOperand(1); + const Value *VAListS = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); + + // vastart stores the address of the VarArgsBase and VarArgsOffset + SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsBase(), MVT::i64); + SDValue S1 = DAG.getStore(Chain, dl, FR, VAListP, + MachinePointerInfo(VAListS), false, false, 0); + SDValue SA2 = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP, + DAG.getConstant(8, MVT::i64)); + return DAG.getTruncStore(S1, dl, + DAG.getConstant(FuncInfo->getVarArgsOffset(), + MVT::i64), + SA2, MachinePointerInfo(), + MVT::i32, false, false, 0); + } + case ISD::RETURNADDR: + return DAG.getNode(AlphaISD::GlobalRetAddr, DebugLoc(), MVT::i64); + //FIXME: implement + case ISD::FRAMEADDR: break; + } + + return SDValue(); +} + +void AlphaTargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl<SDValue>&Results, + SelectionDAG &DAG) const { + DebugLoc dl = N->getDebugLoc(); + assert(N->getValueType(0) == MVT::i32 && + N->getOpcode() == ISD::VAARG && + "Unknown node to custom promote!"); + + SDValue Chain, DataPtr; + LowerVAARG(N, Chain, DataPtr, DAG); + SDValue Res = DAG.getLoad(N->getValueType(0), dl, Chain, DataPtr, + MachinePointerInfo(), + false, false, 0); + Results.push_back(Res); + Results.push_back(SDValue(Res.getNode(), 1)); +} + + +//Inline Asm + +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target. +AlphaTargetLowering::ConstraintType +AlphaTargetLowering::getConstraintType(const std::string &Constraint) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: break; + case 'f': + case 'r': + return C_RegisterClass; + } + } + return TargetLowering::getConstraintType(Constraint); +} + +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +AlphaTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'f': + weight = CW_Register; + break; + } + return weight; +} + +/// Given a register class constraint, like 'r', if this corresponds directly +/// to an LLVM register class, return a register of 0 and the register class +/// pointer. +std::pair<unsigned, const TargetRegisterClass*> AlphaTargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const +{ + if (Constraint.size() == 1) { + switch (Constraint[0]) { + case 'r': + return std::make_pair(0U, Alpha::GPRCRegisterClass); + case 'f': + return VT == MVT::f64 ? std::make_pair(0U, Alpha::F8RCRegisterClass) : + std::make_pair(0U, Alpha::F4RCRegisterClass); + } + } + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); +} + +//===----------------------------------------------------------------------===// +// Other Lowering Code +//===----------------------------------------------------------------------===// + +MachineBasicBlock * +AlphaTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + assert((MI->getOpcode() == Alpha::CAS32 || + MI->getOpcode() == Alpha::CAS64 || + MI->getOpcode() == Alpha::LAS32 || + MI->getOpcode() == Alpha::LAS64 || + MI->getOpcode() == Alpha::SWAP32 || + MI->getOpcode() == Alpha::SWAP64) && + "Unexpected instr type to insert"); + + bool is32 = MI->getOpcode() == Alpha::CAS32 || + MI->getOpcode() == Alpha::LAS32 || + MI->getOpcode() == Alpha::SWAP32; + + //Load locked store conditional for atomic ops take on the same form + //start: + //ll + //do stuff (maybe branch to exit) + //sc + //test sc and maybe branck to start + //exit: + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + DebugLoc dl = MI->getDebugLoc(); + MachineFunction::iterator It = BB; + ++It; + + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *llscMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + + sinkMBB->splice(sinkMBB->begin(), thisMBB, + llvm::next(MachineBasicBlock::iterator(MI)), + thisMBB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(thisMBB); + + F->insert(It, llscMBB); + F->insert(It, sinkMBB); + + BuildMI(thisMBB, dl, TII->get(Alpha::BR)).addMBB(llscMBB); + + unsigned reg_res = MI->getOperand(0).getReg(), + reg_ptr = MI->getOperand(1).getReg(), + reg_v2 = MI->getOperand(2).getReg(), + reg_store = F->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass); + + BuildMI(llscMBB, dl, TII->get(is32 ? Alpha::LDL_L : Alpha::LDQ_L), + reg_res).addImm(0).addReg(reg_ptr); + switch (MI->getOpcode()) { + case Alpha::CAS32: + case Alpha::CAS64: { + unsigned reg_cmp + = F->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass); + BuildMI(llscMBB, dl, TII->get(Alpha::CMPEQ), reg_cmp) + .addReg(reg_v2).addReg(reg_res); + BuildMI(llscMBB, dl, TII->get(Alpha::BEQ)) + .addImm(0).addReg(reg_cmp).addMBB(sinkMBB); + BuildMI(llscMBB, dl, TII->get(Alpha::BISr), reg_store) + .addReg(Alpha::R31).addReg(MI->getOperand(3).getReg()); + break; + } + case Alpha::LAS32: + case Alpha::LAS64: { + BuildMI(llscMBB, dl,TII->get(is32 ? Alpha::ADDLr : Alpha::ADDQr), reg_store) + .addReg(reg_res).addReg(reg_v2); + break; + } + case Alpha::SWAP32: + case Alpha::SWAP64: { + BuildMI(llscMBB, dl, TII->get(Alpha::BISr), reg_store) + .addReg(reg_v2).addReg(reg_v2); + break; + } + } + BuildMI(llscMBB, dl, TII->get(is32 ? Alpha::STL_C : Alpha::STQ_C), reg_store) + .addReg(reg_store).addImm(0).addReg(reg_ptr); + BuildMI(llscMBB, dl, TII->get(Alpha::BEQ)) + .addImm(0).addReg(reg_store).addMBB(llscMBB); + BuildMI(llscMBB, dl, TII->get(Alpha::BR)).addMBB(sinkMBB); + + thisMBB->addSuccessor(llscMBB); + llscMBB->addSuccessor(llscMBB); + llscMBB->addSuccessor(sinkMBB); + MI->eraseFromParent(); // The pseudo instruction is gone now. + + return sinkMBB; +} + +bool +AlphaTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // The Alpha target isn't yet aware of offsets. + return false; +} + +bool AlphaTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { + if (VT != MVT::f32 && VT != MVT::f64) + return false; + // +0.0 F31 + // +0.0f F31 + // -0.0 -F31 + // -0.0f -F31 + return Imm.isZero() || Imm.isNegZero(); +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h new file mode 100644 index 0000000..80f8efa --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h @@ -0,0 +1,142 @@ +//===-- AlphaISelLowering.h - Alpha DAG Lowering Interface ------*- 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 interfaces that Alpha uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ALPHA_ALPHAISELLOWERING_H +#define LLVM_TARGET_ALPHA_ALPHAISELLOWERING_H + +#include "llvm/ADT/VectorExtras.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "Alpha.h" + +namespace llvm { + + namespace AlphaISD { + enum NodeType { + // Start the numbering where the builting ops and target ops leave off. + FIRST_NUMBER = ISD::BUILTIN_OP_END, + //These corrospond to the identical Instruction + CVTQT_, CVTQS_, CVTTQ_, + + /// GPRelHi/GPRelLo - These represent the high and low 16-bit + /// parts of a global address respectively. + GPRelHi, GPRelLo, + + /// RetLit - Literal Relocation of a Global + RelLit, + + /// GlobalRetAddr - used to restore the return address + GlobalRetAddr, + + /// CALL - Normal call. + CALL, + + /// DIVCALL - used for special library calls for div and rem + DivCall, + + /// return flag operand + RET_FLAG, + + /// CHAIN = COND_BRANCH CHAIN, OPC, (G|F)PRC, DESTBB [, INFLAG] - This + /// corresponds to the COND_BRANCH pseudo instruction. + /// *PRC is the input register to compare to zero, + /// OPC is the branch opcode to use (e.g. Alpha::BEQ), + /// DESTBB is the destination block to branch to, and INFLAG is + /// an optional input flag argument. + COND_BRANCH_I, COND_BRANCH_F + + }; + } + + class AlphaTargetLowering : public TargetLowering { + public: + explicit AlphaTargetLowering(TargetMachine &TM); + + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i64; } + + /// getSetCCResultType - Get the SETCC result ValueType + virtual EVT getSetCCResultType(EVT VT) const; + + /// LowerOperation - Provide custom lowering hooks for some operations. + /// + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + + /// ReplaceNodeResults - Replace the results of node with an illegal result + /// type with new values built out of custom code. + /// + virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, + SelectionDAG &DAG) const; + + // Friendly names for dumps + const char *getTargetNodeName(unsigned Opcode) const; + + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const; + + ConstraintType getConstraintType(const std::string &Constraint) const; + + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + + std::pair<unsigned, const TargetRegisterClass*> + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + MachineBasicBlock * + EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const; + + virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + + /// isFPImmLegal - Returns true if the target can instruction select the + /// specified FP immediate natively. If false, the legalizer will + /// materialize the FP immediate as a load from a constant pool. + virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const; + + private: + // Helpers for custom lowering. + void LowerVAARG(SDNode *N, SDValue &Chain, SDValue &DataPtr, + SelectionDAG &DAG) const; + + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const; + + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, bool &isTailCall, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const; + + virtual SDValue + LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + DebugLoc dl, SelectionDAG &DAG) const; + }; +} + +#endif // LLVM_TARGET_ALPHA_ALPHAISELLOWERING_H diff --git a/contrib/llvm/lib/Target/Alpha/AlphaInstrFormats.td b/contrib/llvm/lib/Target/Alpha/AlphaInstrFormats.td new file mode 100644 index 0000000..6f4ebf2 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaInstrFormats.td @@ -0,0 +1,268 @@ +//===- AlphaInstrFormats.td - Alpha Instruction Formats ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//3.3: +//Memory +//Branch +//Operate +//Floating-point +//PALcode + +def u8imm : Operand<i64>; +def s14imm : Operand<i64>; +def s16imm : Operand<i64>; +def s21imm : Operand<i64>; +def s64imm : Operand<i64>; +def u64imm : Operand<i64>; + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// +// Alpha instruction baseline +class InstAlpha<bits<6> op, string asmstr, InstrItinClass itin> : Instruction { + field bits<32> Inst; + let Namespace = "Alpha"; + let AsmString = asmstr; + let Inst{31-26} = op; + let Itinerary = itin; +} + + +//3.3.1 +class MForm<bits<6> opcode, bit load, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern = pattern; + let canFoldAsLoad = load; + let Defs = [R28]; //We may use this for frame index calculations, so reserve it here + + bits<5> Ra; + bits<16> disp; + bits<5> Rb; + + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-0} = disp; +} +class MfcForm<bits<6> opcode, bits<16> fc, string asmstr, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + bits<5> Ra; + + let OutOperandList = (outs GPRC:$RA); + let InOperandList = (ins); + let Inst{25-21} = Ra; + let Inst{20-16} = 0; + let Inst{15-0} = fc; +} +class MfcPForm<bits<6> opcode, bits<16> fc, string asmstr, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let OutOperandList = (outs); + let InOperandList = (ins); + let Inst{25-21} = 0; + let Inst{20-16} = 0; + let Inst{15-0} = fc; +} + +class MbrForm<bits<6> opcode, bits<2> TB, dag OL, string asmstr, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + bits<5> Ra; + bits<5> Rb; + bits<14> disp; + + let OutOperandList = (outs); + let InOperandList = OL; + + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-14} = TB; + let Inst{13-0} = disp; +} +class MbrpForm<bits<6> opcode, bits<2> TB, dag OL, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern=pattern; + bits<5> Ra; + bits<5> Rb; + bits<14> disp; + + let OutOperandList = (outs); + let InOperandList = OL; + + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-14} = TB; + let Inst{13-0} = disp; +} + +//3.3.2 +def target : Operand<OtherVT> {} + +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { +class BFormN<bits<6> opcode, dag OL, string asmstr, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let OutOperandList = (outs); + let InOperandList = OL; + bits<64> Opc; //dummy + bits<5> Ra; + bits<21> disp; + + let Inst{25-21} = Ra; + let Inst{20-0} = disp; +} +} + +let isBranch = 1, isTerminator = 1 in +class BFormD<bits<6> opcode, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern = pattern; + let OutOperandList = (outs); + let InOperandList = (ins target:$DISP); + 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, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern = pattern; + let OutOperandList = (outs GPRC:$RC); + let InOperandList = (ins GPRC:$RA, GPRC:$RB); + + bits<5> Rc; + bits<5> Ra; + bits<5> Rb; + bits<7> Function = fun; + + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-13} = 0; + let Inst{12} = 0; + let Inst{11-5} = Function; + let Inst{4-0} = Rc; +} + +class OForm2<bits<6> opcode, bits<7> fun, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern = pattern; + let OutOperandList = (outs GPRC:$RC); + let InOperandList = (ins GPRC:$RB); + + bits<5> Rc; + bits<5> Rb; + bits<7> Function = fun; + + let Inst{25-21} = 31; + let Inst{20-16} = Rb; + let Inst{15-13} = 0; + let Inst{12} = 0; + let Inst{11-5} = Function; + let Inst{4-0} = Rc; +} + +class OForm4<bits<6> opcode, bits<7> fun, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern = pattern; + let OutOperandList = (outs GPRC:$RDEST); + let InOperandList = (ins GPRC:$RCOND, GPRC:$RTRUE, GPRC:$RFALSE); + let Constraints = "$RFALSE = $RDEST"; + let DisableEncoding = "$RFALSE"; + + bits<5> Rc; + bits<5> Ra; + bits<5> Rb; + bits<7> Function = fun; + +// let Constraints = "$RFALSE = $RDEST"; + let Inst{25-21} = Ra; + let Inst{20-16} = Rb; + let Inst{15-13} = 0; + let Inst{12} = 0; + let Inst{11-5} = Function; + let Inst{4-0} = Rc; +} + + +class OFormL<bits<6> opcode, bits<7> fun, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern = pattern; + let OutOperandList = (outs GPRC:$RC); + let InOperandList = (ins GPRC:$RA, u8imm:$L); + + bits<5> Rc; + bits<5> Ra; + bits<8> LIT; + bits<7> Function = fun; + + let Inst{25-21} = Ra; + let Inst{20-13} = LIT; + let Inst{12} = 1; + let Inst{11-5} = Function; + let Inst{4-0} = Rc; +} + +class OForm4L<bits<6> opcode, bits<7> fun, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern = pattern; + let OutOperandList = (outs GPRC:$RDEST); + let InOperandList = (ins GPRC:$RCOND, s64imm:$RTRUE, GPRC:$RFALSE); + let Constraints = "$RFALSE = $RDEST"; + let DisableEncoding = "$RFALSE"; + + bits<5> Rc; + bits<5> Ra; + bits<8> LIT; + bits<7> Function = fun; + +// let Constraints = "$RFALSE = $RDEST"; + 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, bits<11> fun, string asmstr, list<dag> pattern, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let Pattern = pattern; + + bits<5> Fc; + bits<5> Fa; + bits<5> Fb; + bits<11> Function = fun; + + 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, InstrItinClass itin> + : InstAlpha<opcode, asmstr, itin> { + let OutOperandList = (outs); + let InOperandList = OL; + bits<26> Function; + + let Inst{25-0} = Function; +} + + +// Pseudo instructions. +class PseudoInstAlpha<dag OOL, dag IOL, string nm, list<dag> pattern, InstrItinClass itin> + : InstAlpha<0, nm, itin> { + let OutOperandList = OOL; + let InOperandList = IOL; + let Pattern = pattern; + +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.cpp b/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.cpp new file mode 100644 index 0000000..8df2ed7 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.cpp @@ -0,0 +1,382 @@ +//===- AlphaInstrInfo.cpp - Alpha Instruction Information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 "AlphaMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" + +#define GET_INSTRINFO_CTOR +#include "AlphaGenInstrInfo.inc" +using namespace llvm; + +AlphaInstrInfo::AlphaInstrInfo() + : AlphaGenInstrInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP), + RI(*this) { +} + + +unsigned +AlphaInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + case Alpha::LDL: + case Alpha::LDQ: + case Alpha::LDBU: + case Alpha::LDWU: + case Alpha::LDS: + case Alpha::LDT: + if (MI->getOperand(1).isFI()) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + +unsigned +AlphaInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + case Alpha::STL: + case Alpha::STQ: + case Alpha::STB: + case Alpha::STW: + case Alpha::STS: + case Alpha::STT: + if (MI->getOperand(1).isFI()) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + +static bool isAlphaIntCondCode(unsigned Opcode) { + switch (Opcode) { + case Alpha::BEQ: + case Alpha::BNE: + case Alpha::BGE: + case Alpha::BGT: + case Alpha::BLE: + case Alpha::BLT: + case Alpha::BLBC: + case Alpha::BLBS: + return true; + default: + return false; + } +} + +unsigned AlphaInstrInfo::InsertBranch(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond, + DebugLoc DL) const { + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 2 || Cond.size() == 0) && + "Alpha branch conditions have two components!"); + + // One-way branch. + if (FBB == 0) { + if (Cond.empty()) // Unconditional branch + BuildMI(&MBB, DL, get(Alpha::BR)).addMBB(TBB); + else // Conditional branch + if (isAlphaIntCondCode(Cond[0].getImm())) + BuildMI(&MBB, DL, get(Alpha::COND_BRANCH_I)) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB); + else + BuildMI(&MBB, DL, get(Alpha::COND_BRANCH_F)) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB); + return 1; + } + + // Two-way Conditional Branch. + if (isAlphaIntCondCode(Cond[0].getImm())) + BuildMI(&MBB, DL, get(Alpha::COND_BRANCH_I)) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB); + else + BuildMI(&MBB, DL, get(Alpha::COND_BRANCH_F)) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB); + BuildMI(&MBB, DL, get(Alpha::BR)).addMBB(FBB); + return 2; +} + +void AlphaInstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const { + if (Alpha::GPRCRegClass.contains(DestReg, SrcReg)) { + BuildMI(MBB, MI, DL, get(Alpha::BISr), DestReg) + .addReg(SrcReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + } else if (Alpha::F4RCRegClass.contains(DestReg, SrcReg)) { + BuildMI(MBB, MI, DL, get(Alpha::CPYSS), DestReg) + .addReg(SrcReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + } else if (Alpha::F8RCRegClass.contains(DestReg, SrcReg)) { + BuildMI(MBB, MI, DL, get(Alpha::CPYST), DestReg) + .addReg(SrcReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + } else { + llvm_unreachable("Attempt to copy register that is not GPR or FPR"); + } +} + +void +AlphaInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + //cerr << "Trying to store " << getPrettyName(SrcReg) << " to " + // << FrameIdx << "\n"; + //BuildMI(MBB, MI, Alpha::WTF, 0).addReg(SrcReg); + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + if (RC == Alpha::F4RCRegisterClass) + BuildMI(MBB, MI, DL, get(Alpha::STS)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FrameIdx).addReg(Alpha::F31); + else if (RC == Alpha::F8RCRegisterClass) + BuildMI(MBB, MI, DL, get(Alpha::STT)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FrameIdx).addReg(Alpha::F31); + else if (RC == Alpha::GPRCRegisterClass) + BuildMI(MBB, MI, DL, get(Alpha::STQ)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FrameIdx).addReg(Alpha::F31); + else + llvm_unreachable("Unhandled register class"); +} + +void +AlphaInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + //cerr << "Trying to load " << getPrettyName(DestReg) << " to " + // << FrameIdx << "\n"; + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + if (RC == Alpha::F4RCRegisterClass) + BuildMI(MBB, MI, DL, get(Alpha::LDS), DestReg) + .addFrameIndex(FrameIdx).addReg(Alpha::F31); + else if (RC == Alpha::F8RCRegisterClass) + BuildMI(MBB, MI, DL, get(Alpha::LDT), DestReg) + .addFrameIndex(FrameIdx).addReg(Alpha::F31); + else if (RC == Alpha::GPRCRegisterClass) + BuildMI(MBB, MI, DL, get(Alpha::LDQ), DestReg) + .addFrameIndex(FrameIdx).addReg(Alpha::F31); + else + llvm_unreachable("Unhandled register class"); +} + +static unsigned AlphaRevCondCode(unsigned Opcode) { + switch (Opcode) { + case Alpha::BEQ: return Alpha::BNE; + case Alpha::BNE: return Alpha::BEQ; + case Alpha::BGE: return Alpha::BLT; + case Alpha::BGT: return Alpha::BLE; + case Alpha::BLE: return Alpha::BGT; + case Alpha::BLT: return Alpha::BGE; + case Alpha::BLBC: return Alpha::BLBS; + case Alpha::BLBS: return Alpha::BLBC; + case Alpha::FBEQ: return Alpha::FBNE; + case Alpha::FBNE: return Alpha::FBEQ; + case Alpha::FBGE: return Alpha::FBLT; + case Alpha::FBGT: return Alpha::FBLE; + case Alpha::FBLE: return Alpha::FBGT; + case Alpha::FBLT: return Alpha::FBGE; + default: + llvm_unreachable("Unknown opcode"); + } + return 0; // Not reached +} + +// Branch analysis. +bool AlphaInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const { + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) + return false; + --I; + while (I->isDebugValue()) { + if (I == MBB.begin()) + return false; + --I; + } + if (!isUnpredicatedTerminator(I)) + return false; + + // Get the last instruction in the block. + MachineInstr *LastInst = I; + + // If there is only one terminator instruction, process it. + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + if (LastInst->getOpcode() == Alpha::BR) { + TBB = LastInst->getOperand(0).getMBB(); + return false; + } else if (LastInst->getOpcode() == Alpha::COND_BRANCH_I || + LastInst->getOpcode() == Alpha::COND_BRANCH_F) { + // Block ends with fall-through condbranch. + TBB = LastInst->getOperand(2).getMBB(); + Cond.push_back(LastInst->getOperand(0)); + Cond.push_back(LastInst->getOperand(1)); + return false; + } + // Otherwise, don't know what this is. + return true; + } + + // Get the instruction before it if it's a terminator. + MachineInstr *SecondLastInst = I; + + // If there are three terminators, we don't know what sort of block this is. + if (SecondLastInst && I != MBB.begin() && + isUnpredicatedTerminator(--I)) + return true; + + // If the block ends with Alpha::BR and Alpha::COND_BRANCH_*, handle it. + if ((SecondLastInst->getOpcode() == Alpha::COND_BRANCH_I || + SecondLastInst->getOpcode() == Alpha::COND_BRANCH_F) && + LastInst->getOpcode() == Alpha::BR) { + TBB = SecondLastInst->getOperand(2).getMBB(); + Cond.push_back(SecondLastInst->getOperand(0)); + Cond.push_back(SecondLastInst->getOperand(1)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with two Alpha::BRs, handle it. The second one is not + // executed, so remove it. + if (SecondLastInst->getOpcode() == Alpha::BR && + LastInst->getOpcode() == Alpha::BR) { + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return false; + } + + // Otherwise, can't handle this. + return true; +} + +unsigned AlphaInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) return 0; + --I; + while (I->isDebugValue()) { + if (I == MBB.begin()) + return 0; + --I; + } + if (I->getOpcode() != Alpha::BR && + I->getOpcode() != Alpha::COND_BRANCH_I && + I->getOpcode() != Alpha::COND_BRANCH_F) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) return 1; + --I; + if (I->getOpcode() != Alpha::COND_BRANCH_I && + I->getOpcode() != Alpha::COND_BRANCH_F) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + +void AlphaInstrInfo::insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + DebugLoc DL; + BuildMI(MBB, MI, DL, get(Alpha::BISr), Alpha::R31) + .addReg(Alpha::R31) + .addReg(Alpha::R31); +} + +bool AlphaInstrInfo:: +ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { + assert(Cond.size() == 2 && "Invalid Alpha branch opcode!"); + Cond[0].setImm(AlphaRevCondCode(Cond[0].getImm())); + return false; +} + +/// getGlobalBaseReg - Return a virtual register initialized with the +/// the global base register value. Output instructions required to +/// initialize the register in the function entry block, if necessary. +/// +unsigned AlphaInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { + AlphaMachineFunctionInfo *AlphaFI = MF->getInfo<AlphaMachineFunctionInfo>(); + unsigned GlobalBaseReg = AlphaFI->getGlobalBaseReg(); + if (GlobalBaseReg != 0) + return GlobalBaseReg; + + // Insert the set of GlobalBaseReg into the first MBB of the function + MachineBasicBlock &FirstMBB = MF->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + GlobalBaseReg = RegInfo.createVirtualRegister(&Alpha::GPRCRegClass); + BuildMI(FirstMBB, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), + GlobalBaseReg).addReg(Alpha::R29); + RegInfo.addLiveIn(Alpha::R29); + + AlphaFI->setGlobalBaseReg(GlobalBaseReg); + return GlobalBaseReg; +} + +/// getGlobalRetAddr - Return a virtual register initialized with the +/// the global base register value. Output instructions required to +/// initialize the register in the function entry block, if necessary. +/// +unsigned AlphaInstrInfo::getGlobalRetAddr(MachineFunction *MF) const { + AlphaMachineFunctionInfo *AlphaFI = MF->getInfo<AlphaMachineFunctionInfo>(); + unsigned GlobalRetAddr = AlphaFI->getGlobalRetAddr(); + if (GlobalRetAddr != 0) + return GlobalRetAddr; + + // Insert the set of GlobalRetAddr into the first MBB of the function + MachineBasicBlock &FirstMBB = MF->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + GlobalRetAddr = RegInfo.createVirtualRegister(&Alpha::GPRCRegClass); + BuildMI(FirstMBB, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY), + GlobalRetAddr).addReg(Alpha::R26); + RegInfo.addLiveIn(Alpha::R26); + + AlphaFI->setGlobalRetAddr(GlobalRetAddr); + return GlobalRetAddr; +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.h b/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.h new file mode 100644 index 0000000..337a85c --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.h @@ -0,0 +1,85 @@ +//===- AlphaInstrInfo.h - Alpha Instruction Information ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file 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" + +#define GET_INSTRINFO_HEADER +#include "AlphaGenInstrInfo.inc" + +namespace llvm { + +class AlphaInstrInfo : public AlphaGenInstrInfo { + 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 AlphaRegisterInfo &getRegisterInfo() const { return RI; } + + virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + virtual unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond, + DebugLoc DL) const; + virtual void copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const; + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + bool AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const; + unsigned RemoveBranch(MachineBasicBlock &MBB) const; + void insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const; + bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const; + + /// getGlobalBaseReg - Return a virtual register initialized with the + /// the global base register value. Output instructions required to + /// initialize the register in the function entry block, if necessary. + /// + unsigned getGlobalBaseReg(MachineFunction *MF) const; + + /// getGlobalRetAddr - Return a virtual register initialized with the + /// the global return address register value. Output instructions required to + /// initialize the register in the function entry block, if necessary. + /// + unsigned getGlobalRetAddr(MachineFunction *MF) const; +}; + +} + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.td b/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.td new file mode 100644 index 0000000..c8c9377 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.td @@ -0,0 +1,1159 @@ +//===- AlphaInstrInfo.td - The Alpha Instruction Set -------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +include "AlphaInstrFormats.td" + +//******************** +//Custom DAG Nodes +//******************** + +def SDTFPUnaryOpUnC : SDTypeProfile<1, 1, [ + SDTCisFP<1>, SDTCisFP<0> +]>; +def Alpha_cvtqt : SDNode<"AlphaISD::CVTQT_", SDTFPUnaryOpUnC, []>; +def Alpha_cvtqs : SDNode<"AlphaISD::CVTQS_", SDTFPUnaryOpUnC, []>; +def Alpha_cvttq : SDNode<"AlphaISD::CVTTQ_" , SDTFPUnaryOp, []>; +def Alpha_gprello : SDNode<"AlphaISD::GPRelLo", SDTIntBinOp, []>; +def Alpha_gprelhi : SDNode<"AlphaISD::GPRelHi", SDTIntBinOp, []>; +def Alpha_rellit : SDNode<"AlphaISD::RelLit", SDTIntBinOp, [SDNPMayLoad]>; + +def retflag : SDNode<"AlphaISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue]>; + +// These are target-independent nodes, but have target-specific formats. +def SDT_AlphaCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i64> ]>; +def SDT_AlphaCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i64>, + SDTCisVT<1, i64> ]>; + +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_AlphaCallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_AlphaCallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +//******************** +//Paterns for matching +//******************** +def invX : SDNodeXForm<imm, [{ //invert + return getI64Imm(~N->getZExtValue()); +}]>; +def negX : SDNodeXForm<imm, [{ //negate + return getI64Imm(~N->getZExtValue() + 1); +}]>; +def SExt32 : SDNodeXForm<imm, [{ //signed extend int to long + return getI64Imm(((int64_t)N->getZExtValue() << 32) >> 32); +}]>; +def SExt16 : SDNodeXForm<imm, [{ //signed extend int to long + return getI64Imm(((int64_t)N->getZExtValue() << 48) >> 48); +}]>; +def LL16 : SDNodeXForm<imm, [{ //lda part of constant + return getI64Imm(get_lda16(N->getZExtValue())); +}]>; +def LH16 : SDNodeXForm<imm, [{ //ldah part of constant (or more if too big) + return getI64Imm(get_ldah16(N->getZExtValue())); +}]>; +def iZAPX : SDNodeXForm<and, [{ // get imm to ZAPi + ConstantSDNode *RHS = cast<ConstantSDNode>(N->getOperand(1)); + return getI64Imm(get_zapImm(SDValue(), RHS->getZExtValue())); +}]>; +def nearP2X : SDNodeXForm<imm, [{ + return getI64Imm(Log2_64(getNearPower2((uint64_t)N->getZExtValue()))); +}]>; +def nearP2RemX : SDNodeXForm<imm, [{ + uint64_t x = + abs64(N->getZExtValue() - getNearPower2((uint64_t)N->getZExtValue())); + return getI64Imm(Log2_64(x)); +}]>; + +def immUExt8 : PatLeaf<(imm), [{ //imm fits in 8 bit zero extended field + return (uint64_t)N->getZExtValue() == (uint8_t)N->getZExtValue(); +}]>; +def immUExt8inv : PatLeaf<(imm), [{ //inverted imm fits in 8 bit zero extended field + return (uint64_t)~N->getZExtValue() == (uint8_t)~N->getZExtValue(); +}], invX>; +def immUExt8neg : PatLeaf<(imm), [{ //negated imm fits in 8 bit zero extended field + return ((uint64_t)~N->getZExtValue() + 1) == + (uint8_t)((uint64_t)~N->getZExtValue() + 1); +}], negX>; +def immSExt16 : PatLeaf<(imm), [{ //imm fits in 16 bit sign extended field + return ((int64_t)N->getZExtValue() << 48) >> 48 == + (int64_t)N->getZExtValue(); +}]>; +def immSExt16int : PatLeaf<(imm), [{ //(int)imm fits in a 16 bit sign extended field + return ((int64_t)N->getZExtValue() << 48) >> 48 == + ((int64_t)N->getZExtValue() << 32) >> 32; +}], SExt16>; + +def zappat : PatFrag<(ops node:$LHS), (and node:$LHS, imm), [{ + ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1)); + if (!RHS) return 0; + uint64_t build = get_zapImm(N->getOperand(0), (uint64_t)RHS->getZExtValue()); + return build != 0; +}]>; + +def immFPZ : PatLeaf<(fpimm), [{ //the only fpconstant nodes are +/- 0.0 + (void)N; // silence warning. + return true; +}]>; + +def immRem1 :PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),1,0);}]>; +def immRem2 :PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),2,0);}]>; +def immRem3 :PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),3,0);}]>; +def immRem4 :PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),4,0);}]>; +def immRem5 :PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),5,0);}]>; +def immRem1n:PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),1,1);}]>; +def immRem2n:PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),2,1);}]>; +def immRem3n:PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),3,1);}]>; +def immRem4n:PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),4,1);}]>; +def immRem5n:PatLeaf<(imm),[{return chkRemNearPower2(N->getZExtValue(),5,1);}]>; + +def immRemP2n : PatLeaf<(imm), [{ + return isPowerOf2_64(getNearPower2((uint64_t)N->getZExtValue()) - + N->getZExtValue()); +}]>; +def immRemP2 : PatLeaf<(imm), [{ + return isPowerOf2_64(N->getZExtValue() - + getNearPower2((uint64_t)N->getZExtValue())); +}]>; +def immUExt8ME : PatLeaf<(imm), [{ //use this imm for mulqi + int64_t d = abs64((int64_t)N->getZExtValue() - + (int64_t)getNearPower2((uint64_t)N->getZExtValue())); + if (isPowerOf2_64(d)) return false; + switch (d) { + case 1: case 3: case 5: return false; + default: return (uint64_t)N->getZExtValue() == (uint8_t)N->getZExtValue(); + }; +}]>; + +def intop : PatFrag<(ops node:$op), (sext_inreg node:$op, i32)>; +def add4 : PatFrag<(ops node:$op1, node:$op2), + (add (shl node:$op1, 2), node:$op2)>; +def sub4 : PatFrag<(ops node:$op1, node:$op2), + (sub (shl node:$op1, 2), node:$op2)>; +def add8 : PatFrag<(ops node:$op1, node:$op2), + (add (shl node:$op1, 3), node:$op2)>; +def sub8 : PatFrag<(ops node:$op1, node:$op2), + (sub (shl node:$op1, 3), node:$op2)>; +class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>; +class CmpOpFrag<dag res> : PatFrag<(ops node:$R), res>; + +//Pseudo ops for selection + +def WTF : PseudoInstAlpha<(outs), (ins variable_ops), "#wtf", [], s_pseudo>; + +let hasCtrlDep = 1, Defs = [R30], Uses = [R30] in { +def ADJUSTSTACKUP : PseudoInstAlpha<(outs), (ins s64imm:$amt), + "; ADJUP $amt", + [(callseq_start timm:$amt)], s_pseudo>; +def ADJUSTSTACKDOWN : PseudoInstAlpha<(outs), (ins s64imm:$amt1, s64imm:$amt2), + "; ADJDOWN $amt1", + [(callseq_end timm:$amt1, timm:$amt2)], s_pseudo>; +} + +def ALTENT : PseudoInstAlpha<(outs), (ins s64imm:$TARGET), "$$$TARGET..ng:\n", [], s_pseudo>; +def PCLABEL : PseudoInstAlpha<(outs), (ins s64imm:$num), "PCMARKER_$num:\n",[], s_pseudo>; +def MEMLABEL : PseudoInstAlpha<(outs), (ins s64imm:$i, s64imm:$j, s64imm:$k, s64imm:$m), + "LSMARKER$$$i$$$j$$$k$$$m:", [], s_pseudo>; + + +let usesCustomInserter = 1 in { // Expanded after instruction selection. +def CAS32 : PseudoInstAlpha<(outs GPRC:$dst), (ins GPRC:$ptr, GPRC:$cmp, GPRC:$swp), "", + [(set GPRC:$dst, (atomic_cmp_swap_32 GPRC:$ptr, GPRC:$cmp, GPRC:$swp))], s_pseudo>; +def CAS64 : PseudoInstAlpha<(outs GPRC:$dst), (ins GPRC:$ptr, GPRC:$cmp, GPRC:$swp), "", + [(set GPRC:$dst, (atomic_cmp_swap_64 GPRC:$ptr, GPRC:$cmp, GPRC:$swp))], s_pseudo>; + +def LAS32 : PseudoInstAlpha<(outs GPRC:$dst), (ins GPRC:$ptr, GPRC:$swp), "", + [(set GPRC:$dst, (atomic_load_add_32 GPRC:$ptr, GPRC:$swp))], s_pseudo>; +def LAS64 :PseudoInstAlpha<(outs GPRC:$dst), (ins GPRC:$ptr, GPRC:$swp), "", + [(set GPRC:$dst, (atomic_load_add_64 GPRC:$ptr, GPRC:$swp))], s_pseudo>; + +def SWAP32 : PseudoInstAlpha<(outs GPRC:$dst), (ins GPRC:$ptr, GPRC:$swp), "", + [(set GPRC:$dst, (atomic_swap_32 GPRC:$ptr, GPRC:$swp))], s_pseudo>; +def SWAP64 :PseudoInstAlpha<(outs GPRC:$dst), (ins GPRC:$ptr, GPRC:$swp), "", + [(set GPRC:$dst, (atomic_swap_64 GPRC:$ptr, GPRC:$swp))], s_pseudo>; +} + +//*********************** +//Real instructions +//*********************** + +//Operation Form: + +//conditional moves, int + +multiclass cmov_inst<bits<7> fun, string asmstr, PatFrag OpNode> { +def r : OForm4<0x11, fun, !strconcat(asmstr, " $RCOND,$RTRUE,$RDEST"), + [(set GPRC:$RDEST, (select (OpNode GPRC:$RCOND), GPRC:$RTRUE, GPRC:$RFALSE))], s_cmov>; +def i : OForm4L<0x11, fun, !strconcat(asmstr, " $RCOND,$RTRUE,$RDEST"), + [(set GPRC:$RDEST, (select (OpNode GPRC:$RCOND), immUExt8:$RTRUE, GPRC:$RFALSE))], s_cmov>; +} + +defm CMOVEQ : cmov_inst<0x24, "cmoveq", CmpOpFrag<(seteq node:$R, 0)>>; +defm CMOVNE : cmov_inst<0x26, "cmovne", CmpOpFrag<(setne node:$R, 0)>>; +defm CMOVLT : cmov_inst<0x44, "cmovlt", CmpOpFrag<(setlt node:$R, 0)>>; +defm CMOVLE : cmov_inst<0x64, "cmovle", CmpOpFrag<(setle node:$R, 0)>>; +defm CMOVGT : cmov_inst<0x66, "cmovgt", CmpOpFrag<(setgt node:$R, 0)>>; +defm CMOVGE : cmov_inst<0x46, "cmovge", CmpOpFrag<(setge node:$R, 0)>>; +defm CMOVLBC : cmov_inst<0x16, "cmovlbc", CmpOpFrag<(xor node:$R, 1)>>; +defm CMOVLBS : cmov_inst<0x14, "cmovlbs", CmpOpFrag<(and node:$R, 1)>>; + +//General pattern for cmov +def : Pat<(select GPRC:$which, GPRC:$src1, GPRC:$src2), + (CMOVNEr GPRC:$src2, GPRC:$src1, GPRC:$which)>; +def : Pat<(select GPRC:$which, GPRC:$src1, immUExt8:$src2), + (CMOVEQi GPRC:$src1, immUExt8:$src2, GPRC:$which)>; + +//Invert sense when we can for constants: +def : Pat<(select (setne GPRC:$RCOND, 0), GPRC:$RTRUE, immUExt8:$RFALSE), + (CMOVEQi GPRC:$RCOND, immUExt8:$RFALSE, GPRC:$RTRUE)>; +def : Pat<(select (setgt GPRC:$RCOND, 0), GPRC:$RTRUE, immUExt8:$RFALSE), + (CMOVLEi GPRC:$RCOND, immUExt8:$RFALSE, GPRC:$RTRUE)>; +def : Pat<(select (setge GPRC:$RCOND, 0), GPRC:$RTRUE, immUExt8:$RFALSE), + (CMOVLTi GPRC:$RCOND, immUExt8:$RFALSE, GPRC:$RTRUE)>; +def : Pat<(select (setlt GPRC:$RCOND, 0), GPRC:$RTRUE, immUExt8:$RFALSE), + (CMOVGEi GPRC:$RCOND, immUExt8:$RFALSE, GPRC:$RTRUE)>; +def : Pat<(select (setle GPRC:$RCOND, 0), GPRC:$RTRUE, immUExt8:$RFALSE), + (CMOVGTi GPRC:$RCOND, immUExt8:$RFALSE, GPRC:$RTRUE)>; + +multiclass all_inst<bits<6> opc, bits<7> funl, bits<7> funq, + string asmstr, PatFrag OpNode, InstrItinClass itin> { + def Lr : OForm< opc, funl, !strconcat(asmstr, "l $RA,$RB,$RC"), + [(set GPRC:$RC, (intop (OpNode GPRC:$RA, GPRC:$RB)))], itin>; + def Li : OFormL<opc, funl, !strconcat(asmstr, "l $RA,$L,$RC"), + [(set GPRC:$RC, (intop (OpNode GPRC:$RA, immUExt8:$L)))], itin>; + def Qr : OForm< opc, funq, !strconcat(asmstr, "q $RA,$RB,$RC"), + [(set GPRC:$RC, (OpNode GPRC:$RA, GPRC:$RB))], itin>; + def Qi : OFormL<opc, funq, !strconcat(asmstr, "q $RA,$L,$RC"), + [(set GPRC:$RC, (OpNode GPRC:$RA, immUExt8:$L))], itin>; +} + +defm MUL : all_inst<0x13, 0x00, 0x20, "mul", BinOpFrag<(mul node:$LHS, node:$RHS)>, s_imul>; +defm ADD : all_inst<0x10, 0x00, 0x20, "add", BinOpFrag<(add node:$LHS, node:$RHS)>, s_iadd>; +defm S4ADD : all_inst<0x10, 0x02, 0x22, "s4add", add4, s_iadd>; +defm S8ADD : all_inst<0x10, 0x12, 0x32, "s8add", add8, s_iadd>; +defm S4SUB : all_inst<0x10, 0x0B, 0x2B, "s4sub", sub4, s_iadd>; +defm S8SUB : all_inst<0x10, 0x1B, 0x3B, "s8sub", sub8, s_iadd>; +defm SUB : all_inst<0x10, 0x09, 0x29, "sub", BinOpFrag<(sub node:$LHS, node:$RHS)>, s_iadd>; +//Const cases since legalize does sub x, int -> add x, inv(int) + 1 +def : Pat<(intop (add GPRC:$RA, immUExt8neg:$L)), (SUBLi GPRC:$RA, immUExt8neg:$L)>; +def : Pat<(add GPRC:$RA, immUExt8neg:$L), (SUBQi GPRC:$RA, immUExt8neg:$L)>; +def : Pat<(intop (add4 GPRC:$RA, immUExt8neg:$L)), (S4SUBLi GPRC:$RA, immUExt8neg:$L)>; +def : Pat<(add4 GPRC:$RA, immUExt8neg:$L), (S4SUBQi GPRC:$RA, immUExt8neg:$L)>; +def : Pat<(intop (add8 GPRC:$RA, immUExt8neg:$L)), (S8SUBLi GPRC:$RA, immUExt8neg:$L)>; +def : Pat<(add8 GPRC:$RA, immUExt8neg:$L), (S8SUBQi GPRC:$RA, immUExt8neg:$L)>; + +multiclass log_inst<bits<6> opc, bits<7> fun, string asmstr, SDNode OpNode, InstrItinClass itin> { +def r : OForm<opc, fun, !strconcat(asmstr, " $RA,$RB,$RC"), + [(set GPRC:$RC, (OpNode GPRC:$RA, GPRC:$RB))], itin>; +def i : OFormL<opc, fun, !strconcat(asmstr, " $RA,$L,$RC"), + [(set GPRC:$RC, (OpNode GPRC:$RA, immUExt8:$L))], itin>; +} +multiclass inv_inst<bits<6> opc, bits<7> fun, string asmstr, SDNode OpNode, InstrItinClass itin> { +def r : OForm<opc, fun, !strconcat(asmstr, " $RA,$RB,$RC"), + [(set GPRC:$RC, (OpNode GPRC:$RA, (not GPRC:$RB)))], itin>; +def i : OFormL<opc, fun, !strconcat(asmstr, " $RA,$L,$RC"), + [(set GPRC:$RC, (OpNode GPRC:$RA, immUExt8inv:$L))], itin>; +} + +defm AND : log_inst<0x11, 0x00, "and", and, s_ilog>; +defm BIC : inv_inst<0x11, 0x08, "bic", and, s_ilog>; +defm BIS : log_inst<0x11, 0x20, "bis", or, s_ilog>; +defm ORNOT : inv_inst<0x11, 0x28, "ornot", or, s_ilog>; +defm XOR : log_inst<0x11, 0x40, "xor", xor, s_ilog>; +defm EQV : inv_inst<0x11, 0x48, "eqv", xor, s_ilog>; + +defm SL : log_inst<0x12, 0x39, "sll", shl, s_ishf>; +defm SRA : log_inst<0x12, 0x3c, "sra", sra, s_ishf>; +defm SRL : log_inst<0x12, 0x34, "srl", srl, s_ishf>; +defm UMULH : log_inst<0x13, 0x30, "umulh", mulhu, s_imul>; + +def CTLZ : OForm2<0x1C, 0x32, "CTLZ $RB,$RC", + [(set GPRC:$RC, (ctlz GPRC:$RB))], s_imisc>; +def CTPOP : OForm2<0x1C, 0x30, "CTPOP $RB,$RC", + [(set GPRC:$RC, (ctpop GPRC:$RB))], s_imisc>; +def CTTZ : OForm2<0x1C, 0x33, "CTTZ $RB,$RC", + [(set GPRC:$RC, (cttz GPRC:$RB))], s_imisc>; +def EXTBL : OForm< 0x12, 0x06, "EXTBL $RA,$RB,$RC", + [(set GPRC:$RC, (and (srl GPRC:$RA, (shl GPRC:$RB, 3)), 255))], s_ishf>; +def EXTWL : OForm< 0x12, 0x16, "EXTWL $RA,$RB,$RC", + [(set GPRC:$RC, (and (srl GPRC:$RA, (shl GPRC:$RB, 3)), 65535))], s_ishf>; +def EXTLL : OForm< 0x12, 0x26, "EXTLL $RA,$RB,$RC", + [(set GPRC:$RC, (and (srl GPRC:$RA, (shl GPRC:$RB, 3)), 4294967295))], s_ishf>; +def SEXTB : OForm2<0x1C, 0x00, "sextb $RB,$RC", + [(set GPRC:$RC, (sext_inreg GPRC:$RB, i8))], s_ishf>; +def SEXTW : OForm2<0x1C, 0x01, "sextw $RB,$RC", + [(set GPRC:$RC, (sext_inreg GPRC:$RB, i16))], s_ishf>; + +//def EXTBLi : OFormL<0x12, 0x06, "EXTBL $RA,$L,$RC", []>; //Extract byte low +//def EXTLH : OForm< 0x12, 0x6A, "EXTLH $RA,$RB,$RC", []>; //Extract longword high +//def EXTLHi : OFormL<0x12, 0x6A, "EXTLH $RA,$L,$RC", []>; //Extract longword high +//def EXTLLi : OFormL<0x12, 0x26, "EXTLL $RA,$L,$RC", []>; //Extract longword low +//def EXTQH : OForm< 0x12, 0x7A, "EXTQH $RA,$RB,$RC", []>; //Extract quadword high +//def EXTQHi : OFormL<0x12, 0x7A, "EXTQH $RA,$L,$RC", []>; //Extract quadword high +//def EXTQ : OForm< 0x12, 0x36, "EXTQ $RA,$RB,$RC", []>; //Extract quadword low +//def EXTQi : OFormL<0x12, 0x36, "EXTQ $RA,$L,$RC", []>; //Extract quadword low +//def EXTWH : OForm< 0x12, 0x5A, "EXTWH $RA,$RB,$RC", []>; //Extract word high +//def EXTWHi : OFormL<0x12, 0x5A, "EXTWH $RA,$L,$RC", []>; //Extract word high +//def EXTWLi : OFormL<0x12, 0x16, "EXTWL $RA,$L,$RC", []>; //Extract word low + +//def INSBL : OForm< 0x12, 0x0B, "INSBL $RA,$RB,$RC", []>; //Insert byte low +//def INSBLi : OFormL<0x12, 0x0B, "INSBL $RA,$L,$RC", []>; //Insert byte low +//def INSLH : OForm< 0x12, 0x67, "INSLH $RA,$RB,$RC", []>; //Insert longword high +//def INSLHi : OFormL<0x12, 0x67, "INSLH $RA,$L,$RC", []>; //Insert longword high +//def INSLL : OForm< 0x12, 0x2B, "INSLL $RA,$RB,$RC", []>; //Insert longword low +//def INSLLi : OFormL<0x12, 0x2B, "INSLL $RA,$L,$RC", []>; //Insert longword low +//def INSQH : OForm< 0x12, 0x77, "INSQH $RA,$RB,$RC", []>; //Insert quadword high +//def INSQHi : OFormL<0x12, 0x77, "INSQH $RA,$L,$RC", []>; //Insert quadword high +//def INSQL : OForm< 0x12, 0x3B, "INSQL $RA,$RB,$RC", []>; //Insert quadword low +//def INSQLi : OFormL<0x12, 0x3B, "INSQL $RA,$L,$RC", []>; //Insert quadword low +//def INSWH : OForm< 0x12, 0x57, "INSWH $RA,$RB,$RC", []>; //Insert word high +//def INSWHi : OFormL<0x12, 0x57, "INSWH $RA,$L,$RC", []>; //Insert word high +//def INSWL : OForm< 0x12, 0x1B, "INSWL $RA,$RB,$RC", []>; //Insert word low +//def INSWLi : OFormL<0x12, 0x1B, "INSWL $RA,$L,$RC", []>; //Insert word low + +//def MSKBL : OForm< 0x12, 0x02, "MSKBL $RA,$RB,$RC", []>; //Mask byte low +//def MSKBLi : OFormL<0x12, 0x02, "MSKBL $RA,$L,$RC", []>; //Mask byte low +//def MSKLH : OForm< 0x12, 0x62, "MSKLH $RA,$RB,$RC", []>; //Mask longword high +//def MSKLHi : OFormL<0x12, 0x62, "MSKLH $RA,$L,$RC", []>; //Mask longword high +//def MSKLL : OForm< 0x12, 0x22, "MSKLL $RA,$RB,$RC", []>; //Mask longword low +//def MSKLLi : OFormL<0x12, 0x22, "MSKLL $RA,$L,$RC", []>; //Mask longword low +//def MSKQH : OForm< 0x12, 0x72, "MSKQH $RA,$RB,$RC", []>; //Mask quadword high +//def MSKQHi : OFormL<0x12, 0x72, "MSKQH $RA,$L,$RC", []>; //Mask quadword high +//def MSKQL : OForm< 0x12, 0x32, "MSKQL $RA,$RB,$RC", []>; //Mask quadword low +//def MSKQLi : OFormL<0x12, 0x32, "MSKQL $RA,$L,$RC", []>; //Mask quadword low +//def MSKWH : OForm< 0x12, 0x52, "MSKWH $RA,$RB,$RC", []>; //Mask word high +//def MSKWHi : OFormL<0x12, 0x52, "MSKWH $RA,$L,$RC", []>; //Mask word high +//def MSKWL : OForm< 0x12, 0x12, "MSKWL $RA,$RB,$RC", []>; //Mask word low +//def MSKWLi : OFormL<0x12, 0x12, "MSKWL $RA,$L,$RC", []>; //Mask word low + +def ZAPNOTi : OFormL<0x12, 0x31, "zapnot $RA,$L,$RC", [], s_ishf>; + +// Define the pattern that produces ZAPNOTi. +def : Pat<(zappat:$imm GPRC:$RA), + (ZAPNOTi GPRC:$RA, (iZAPX GPRC:$imm))>; + + +//Comparison, int +//So this is a waste of what this instruction can do, but it still saves something +def CMPBGE : OForm< 0x10, 0x0F, "cmpbge $RA,$RB,$RC", + [(set GPRC:$RC, (setuge (and GPRC:$RA, 255), (and GPRC:$RB, 255)))], s_ilog>; +def CMPBGEi : OFormL<0x10, 0x0F, "cmpbge $RA,$L,$RC", + [(set GPRC:$RC, (setuge (and GPRC:$RA, 255), immUExt8:$L))], s_ilog>; +def CMPEQ : OForm< 0x10, 0x2D, "cmpeq $RA,$RB,$RC", + [(set GPRC:$RC, (seteq GPRC:$RA, GPRC:$RB))], s_iadd>; +def CMPEQi : OFormL<0x10, 0x2D, "cmpeq $RA,$L,$RC", + [(set GPRC:$RC, (seteq GPRC:$RA, immUExt8:$L))], s_iadd>; +def CMPLE : OForm< 0x10, 0x6D, "cmple $RA,$RB,$RC", + [(set GPRC:$RC, (setle GPRC:$RA, GPRC:$RB))], s_iadd>; +def CMPLEi : OFormL<0x10, 0x6D, "cmple $RA,$L,$RC", + [(set GPRC:$RC, (setle GPRC:$RA, immUExt8:$L))], s_iadd>; +def CMPLT : OForm< 0x10, 0x4D, "cmplt $RA,$RB,$RC", + [(set GPRC:$RC, (setlt GPRC:$RA, GPRC:$RB))], s_iadd>; +def CMPLTi : OFormL<0x10, 0x4D, "cmplt $RA,$L,$RC", + [(set GPRC:$RC, (setlt GPRC:$RA, immUExt8:$L))], s_iadd>; +def CMPULE : OForm< 0x10, 0x3D, "cmpule $RA,$RB,$RC", + [(set GPRC:$RC, (setule GPRC:$RA, GPRC:$RB))], s_iadd>; +def CMPULEi : OFormL<0x10, 0x3D, "cmpule $RA,$L,$RC", + [(set GPRC:$RC, (setule GPRC:$RA, immUExt8:$L))], s_iadd>; +def CMPULT : OForm< 0x10, 0x1D, "cmpult $RA,$RB,$RC", + [(set GPRC:$RC, (setult GPRC:$RA, GPRC:$RB))], s_iadd>; +def CMPULTi : OFormL<0x10, 0x1D, "cmpult $RA,$L,$RC", + [(set GPRC:$RC, (setult GPRC:$RA, immUExt8:$L))], s_iadd>; + +//Patterns for unsupported int comparisons +def : Pat<(setueq GPRC:$X, GPRC:$Y), (CMPEQ GPRC:$X, GPRC:$Y)>; +def : Pat<(setueq GPRC:$X, immUExt8:$Y), (CMPEQi GPRC:$X, immUExt8:$Y)>; + +def : Pat<(setugt GPRC:$X, GPRC:$Y), (CMPULT GPRC:$Y, GPRC:$X)>; +def : Pat<(setugt immUExt8:$X, GPRC:$Y), (CMPULTi GPRC:$Y, immUExt8:$X)>; + +def : Pat<(setuge GPRC:$X, GPRC:$Y), (CMPULE GPRC:$Y, GPRC:$X)>; +def : Pat<(setuge immUExt8:$X, GPRC:$Y), (CMPULEi GPRC:$Y, immUExt8:$X)>; + +def : Pat<(setgt GPRC:$X, GPRC:$Y), (CMPLT GPRC:$Y, GPRC:$X)>; +def : Pat<(setgt immUExt8:$X, GPRC:$Y), (CMPLTi GPRC:$Y, immUExt8:$X)>; + +def : Pat<(setge GPRC:$X, GPRC:$Y), (CMPLE GPRC:$Y, GPRC:$X)>; +def : Pat<(setge immUExt8:$X, GPRC:$Y), (CMPLEi GPRC:$Y, immUExt8:$X)>; + +def : Pat<(setne GPRC:$X, GPRC:$Y), (CMPEQi (CMPEQ GPRC:$X, GPRC:$Y), 0)>; +def : Pat<(setne GPRC:$X, immUExt8:$Y), (CMPEQi (CMPEQi GPRC:$X, immUExt8:$Y), 0)>; + +def : Pat<(setune GPRC:$X, GPRC:$Y), (CMPEQi (CMPEQ GPRC:$X, GPRC:$Y), 0)>; +def : Pat<(setune GPRC:$X, immUExt8:$Y), (CMPEQi (CMPEQ GPRC:$X, immUExt8:$Y), 0)>; + + +let isReturn = 1, isTerminator = 1, isBarrier = 1, Ra = 31, Rb = 26, disp = 1, Uses = [R26] in { + def RETDAG : MbrForm< 0x1A, 0x02, (ins), "ret $$31,($$26),1", s_jsr>; //Return from subroutine + def RETDAGp : MbrpForm< 0x1A, 0x02, (ins), "ret $$31,($$26),1", [(retflag)], s_jsr>; //Return from subroutine +} + +let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1, Ra = 31, disp = 0 in +def JMP : MbrpForm< 0x1A, 0x00, (ins GPRC:$RS), "jmp $$31,($RS),0", + [(brind GPRC:$RS)], s_jsr>; //Jump + +let isCall = 1, Ra = 26, + Defs = [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, + R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, + F0, F1, + F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, + F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30], Uses = [R29] in { + def BSR : BFormD<0x34, "bsr $$26,$$$DISP..ng", [], s_jsr>; //Branch to subroutine +} +let isCall = 1, Ra = 26, Rb = 27, disp = 0, + Defs = [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, + R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, + F0, F1, + F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, + F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30], Uses = [R27, R29] in { + def JSR : MbrForm< 0x1A, 0x01, (ins), "jsr $$26,($$27),0", s_jsr>; //Jump to subroutine +} + +let isCall = 1, Ra = 23, Rb = 27, disp = 0, + Defs = [R23, R24, R25, R27, R28], Uses = [R24, R25, R27] in + def JSRs : MbrForm< 0x1A, 0x01, (ins), "jsr $$23,($$27),0", s_jsr>; //Jump to div or rem + + +def JSR_COROUTINE : MbrForm< 0x1A, 0x03, (ins GPRC:$RD, GPRC:$RS, s14imm:$DISP), "jsr_coroutine $RD,($RS),$DISP", s_jsr>; //Jump to subroutine return + + +let OutOperandList = (outs GPRC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in { +def LDQ : MForm<0x29, 1, "ldq $RA,$DISP($RB)", + [(set GPRC:$RA, (load (add GPRC:$RB, immSExt16:$DISP)))], s_ild>; +def LDQr : MForm<0x29, 1, "ldq $RA,$DISP($RB)\t\t!gprellow", + [(set GPRC:$RA, (load (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB)))], s_ild>; +def LDL : MForm<0x28, 1, "ldl $RA,$DISP($RB)", + [(set GPRC:$RA, (sextloadi32 (add GPRC:$RB, immSExt16:$DISP)))], s_ild>; +def LDLr : MForm<0x28, 1, "ldl $RA,$DISP($RB)\t\t!gprellow", + [(set GPRC:$RA, (sextloadi32 (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB)))], s_ild>; +def LDBU : MForm<0x0A, 1, "ldbu $RA,$DISP($RB)", + [(set GPRC:$RA, (zextloadi8 (add GPRC:$RB, immSExt16:$DISP)))], s_ild>; +def LDBUr : MForm<0x0A, 1, "ldbu $RA,$DISP($RB)\t\t!gprellow", + [(set GPRC:$RA, (zextloadi8 (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB)))], s_ild>; +def LDWU : MForm<0x0C, 1, "ldwu $RA,$DISP($RB)", + [(set GPRC:$RA, (zextloadi16 (add GPRC:$RB, immSExt16:$DISP)))], s_ild>; +def LDWUr : MForm<0x0C, 1, "ldwu $RA,$DISP($RB)\t\t!gprellow", + [(set GPRC:$RA, (zextloadi16 (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB)))], s_ild>; +} + + +let OutOperandList = (outs), InOperandList = (ins GPRC:$RA, s64imm:$DISP, GPRC:$RB) in { +def STB : MForm<0x0E, 0, "stb $RA,$DISP($RB)", + [(truncstorei8 GPRC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_ist>; +def STBr : MForm<0x0E, 0, "stb $RA,$DISP($RB)\t\t!gprellow", + [(truncstorei8 GPRC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_ist>; +def STW : MForm<0x0D, 0, "stw $RA,$DISP($RB)", + [(truncstorei16 GPRC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_ist>; +def STWr : MForm<0x0D, 0, "stw $RA,$DISP($RB)\t\t!gprellow", + [(truncstorei16 GPRC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_ist>; +def STL : MForm<0x2C, 0, "stl $RA,$DISP($RB)", + [(truncstorei32 GPRC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_ist>; +def STLr : MForm<0x2C, 0, "stl $RA,$DISP($RB)\t\t!gprellow", + [(truncstorei32 GPRC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_ist>; +def STQ : MForm<0x2D, 0, "stq $RA,$DISP($RB)", + [(store GPRC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_ist>; +def STQr : MForm<0x2D, 0, "stq $RA,$DISP($RB)\t\t!gprellow", + [(store GPRC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_ist>; +} + +//Load address +let OutOperandList = (outs GPRC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in { +def LDA : MForm<0x08, 0, "lda $RA,$DISP($RB)", + [(set GPRC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_lda>; +def LDAr : MForm<0x08, 0, "lda $RA,$DISP($RB)\t\t!gprellow", + [(set GPRC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_lda>; //Load address +def LDAH : MForm<0x09, 0, "ldah $RA,$DISP($RB)", + [], s_lda>; //Load address high +def LDAHr : MForm<0x09, 0, "ldah $RA,$DISP($RB)\t\t!gprelhigh", + [(set GPRC:$RA, (Alpha_gprelhi tglobaladdr:$DISP, GPRC:$RB))], s_lda>; //Load address high +} + +let OutOperandList = (outs), InOperandList = (ins F4RC:$RA, s64imm:$DISP, GPRC:$RB) in { +def STS : MForm<0x26, 0, "sts $RA,$DISP($RB)", + [(store F4RC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_fst>; +def STSr : MForm<0x26, 0, "sts $RA,$DISP($RB)\t\t!gprellow", + [(store F4RC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_fst>; +} +let OutOperandList = (outs F4RC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in { +def LDS : MForm<0x22, 1, "lds $RA,$DISP($RB)", + [(set F4RC:$RA, (load (add GPRC:$RB, immSExt16:$DISP)))], s_fld>; +def LDSr : MForm<0x22, 1, "lds $RA,$DISP($RB)\t\t!gprellow", + [(set F4RC:$RA, (load (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB)))], s_fld>; +} +let OutOperandList = (outs), InOperandList = (ins F8RC:$RA, s64imm:$DISP, GPRC:$RB) in { +def STT : MForm<0x27, 0, "stt $RA,$DISP($RB)", + [(store F8RC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_fst>; +def STTr : MForm<0x27, 0, "stt $RA,$DISP($RB)\t\t!gprellow", + [(store F8RC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_fst>; +} +let OutOperandList = (outs F8RC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in { +def LDT : MForm<0x23, 1, "ldt $RA,$DISP($RB)", + [(set F8RC:$RA, (load (add GPRC:$RB, immSExt16:$DISP)))], s_fld>; +def LDTr : MForm<0x23, 1, "ldt $RA,$DISP($RB)\t\t!gprellow", + [(set F8RC:$RA, (load (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB)))], s_fld>; +} + + +//constpool rels +def : Pat<(i64 (load (Alpha_gprello tconstpool:$DISP, GPRC:$RB))), + (LDQr tconstpool:$DISP, GPRC:$RB)>; +def : Pat<(i64 (sextloadi32 (Alpha_gprello tconstpool:$DISP, GPRC:$RB))), + (LDLr tconstpool:$DISP, GPRC:$RB)>; +def : Pat<(i64 (zextloadi8 (Alpha_gprello tconstpool:$DISP, GPRC:$RB))), + (LDBUr tconstpool:$DISP, GPRC:$RB)>; +def : Pat<(i64 (zextloadi16 (Alpha_gprello tconstpool:$DISP, GPRC:$RB))), + (LDWUr tconstpool:$DISP, GPRC:$RB)>; +def : Pat<(i64 (Alpha_gprello tconstpool:$DISP, GPRC:$RB)), + (LDAr tconstpool:$DISP, GPRC:$RB)>; +def : Pat<(i64 (Alpha_gprelhi tconstpool:$DISP, GPRC:$RB)), + (LDAHr tconstpool:$DISP, GPRC:$RB)>; +def : Pat<(f32 (load (Alpha_gprello tconstpool:$DISP, GPRC:$RB))), + (LDSr tconstpool:$DISP, GPRC:$RB)>; +def : Pat<(f64 (load (Alpha_gprello tconstpool:$DISP, GPRC:$RB))), + (LDTr tconstpool:$DISP, GPRC:$RB)>; + +//jumptable rels +def : Pat<(i64 (Alpha_gprelhi tjumptable:$DISP, GPRC:$RB)), + (LDAHr tjumptable:$DISP, GPRC:$RB)>; +def : Pat<(i64 (Alpha_gprello tjumptable:$DISP, GPRC:$RB)), + (LDAr tjumptable:$DISP, GPRC:$RB)>; + + +//misc ext patterns +def : Pat<(i64 (extloadi8 (add GPRC:$RB, immSExt16:$DISP))), + (LDBU immSExt16:$DISP, GPRC:$RB)>; +def : Pat<(i64 (extloadi16 (add GPRC:$RB, immSExt16:$DISP))), + (LDWU immSExt16:$DISP, GPRC:$RB)>; +def : Pat<(i64 (extloadi32 (add GPRC:$RB, immSExt16:$DISP))), + (LDL immSExt16:$DISP, GPRC:$RB)>; + +//0 disp patterns +def : Pat<(i64 (load GPRC:$addr)), + (LDQ 0, GPRC:$addr)>; +def : Pat<(f64 (load GPRC:$addr)), + (LDT 0, GPRC:$addr)>; +def : Pat<(f32 (load GPRC:$addr)), + (LDS 0, GPRC:$addr)>; +def : Pat<(i64 (sextloadi32 GPRC:$addr)), + (LDL 0, GPRC:$addr)>; +def : Pat<(i64 (zextloadi16 GPRC:$addr)), + (LDWU 0, GPRC:$addr)>; +def : Pat<(i64 (zextloadi8 GPRC:$addr)), + (LDBU 0, GPRC:$addr)>; +def : Pat<(i64 (extloadi8 GPRC:$addr)), + (LDBU 0, GPRC:$addr)>; +def : Pat<(i64 (extloadi16 GPRC:$addr)), + (LDWU 0, GPRC:$addr)>; +def : Pat<(i64 (extloadi32 GPRC:$addr)), + (LDL 0, GPRC:$addr)>; + +def : Pat<(store GPRC:$DATA, GPRC:$addr), + (STQ GPRC:$DATA, 0, GPRC:$addr)>; +def : Pat<(store F8RC:$DATA, GPRC:$addr), + (STT F8RC:$DATA, 0, GPRC:$addr)>; +def : Pat<(store F4RC:$DATA, GPRC:$addr), + (STS F4RC:$DATA, 0, GPRC:$addr)>; +def : Pat<(truncstorei32 GPRC:$DATA, GPRC:$addr), + (STL GPRC:$DATA, 0, GPRC:$addr)>; +def : Pat<(truncstorei16 GPRC:$DATA, GPRC:$addr), + (STW GPRC:$DATA, 0, GPRC:$addr)>; +def : Pat<(truncstorei8 GPRC:$DATA, GPRC:$addr), + (STB GPRC:$DATA, 0, GPRC:$addr)>; + + +//load address, rellocated gpdist form +let OutOperandList = (outs GPRC:$RA), + InOperandList = (ins s16imm:$DISP, GPRC:$RB, s16imm:$NUM), + mayLoad = 1 in { +def LDAg : MForm<0x08, 1, "lda $RA,0($RB)\t\t!gpdisp!$NUM", [], s_lda>; //Load address +def LDAHg : MForm<0x09, 1, "ldah $RA,0($RB)\t\t!gpdisp!$NUM", [], s_lda>; //Load address +} + +//Load quad, rellocated literal form +let OutOperandList = (outs GPRC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in +def LDQl : MForm<0x29, 1, "ldq $RA,$DISP($RB)\t\t!literal", + [(set GPRC:$RA, (Alpha_rellit tglobaladdr:$DISP, GPRC:$RB))], s_ild>; +def : Pat<(Alpha_rellit texternalsym:$ext, GPRC:$RB), + (LDQl texternalsym:$ext, GPRC:$RB)>; + +let OutOperandList = (outs GPRC:$RR), + InOperandList = (ins GPRC:$RA, s64imm:$DISP, GPRC:$RB), + Constraints = "$RA = $RR", + DisableEncoding = "$RR" in { +def STQ_C : MForm<0x2F, 0, "stq_l $RA,$DISP($RB)", [], s_ist>; +def STL_C : MForm<0x2E, 0, "stl_l $RA,$DISP($RB)", [], s_ist>; +} +let OutOperandList = (outs GPRC:$RA), + InOperandList = (ins s64imm:$DISP, GPRC:$RB), + mayLoad = 1 in { +def LDQ_L : MForm<0x2B, 1, "ldq_l $RA,$DISP($RB)", [], s_ild>; +def LDL_L : MForm<0x2A, 1, "ldl_l $RA,$DISP($RB)", [], s_ild>; +} + +def RPCC : MfcForm<0x18, 0xC000, "rpcc $RA", s_rpcc>; //Read process cycle counter +def MB : MfcPForm<0x18, 0x4000, "mb", s_imisc>; //memory barrier +def WMB : MfcPForm<0x18, 0x4400, "wmb", s_imisc>; //write memory barrier + +def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 1), (i64 imm)), + (WMB)>; +def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 imm), (i64 imm)), + (MB)>; + +def : Pat<(atomic_fence (imm), (imm)), (MB)>; + +//Basic Floating point ops + +//Floats + +let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F4RC:$RB), Fa = 31 in +def SQRTS : FPForm<0x14, 0x58B, "sqrts/su $RB,$RC", + [(set F4RC:$RC, (fsqrt F4RC:$RB))], s_fsqrts>; + +let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F4RC:$RA, F4RC:$RB) in { +def ADDS : FPForm<0x16, 0x580, "adds/su $RA,$RB,$RC", + [(set F4RC:$RC, (fadd F4RC:$RA, F4RC:$RB))], s_fadd>; +def SUBS : FPForm<0x16, 0x581, "subs/su $RA,$RB,$RC", + [(set F4RC:$RC, (fsub F4RC:$RA, F4RC:$RB))], s_fadd>; +def DIVS : FPForm<0x16, 0x583, "divs/su $RA,$RB,$RC", + [(set F4RC:$RC, (fdiv F4RC:$RA, F4RC:$RB))], s_fdivs>; +def MULS : FPForm<0x16, 0x582, "muls/su $RA,$RB,$RC", + [(set F4RC:$RC, (fmul F4RC:$RA, F4RC:$RB))], s_fmul>; + +def CPYSS : FPForm<0x17, 0x020, "cpys $RA,$RB,$RC", + [(set F4RC:$RC, (fcopysign F4RC:$RB, F4RC:$RA))], s_fadd>; +def CPYSES : FPForm<0x17, 0x022, "cpyse $RA,$RB,$RC",[], s_fadd>; //Copy sign and exponent +def CPYSNS : FPForm<0x17, 0x021, "cpysn $RA,$RB,$RC", + [(set F4RC:$RC, (fneg (fcopysign F4RC:$RB, F4RC:$RA)))], s_fadd>; +} + +//Doubles + +let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in +def SQRTT : FPForm<0x14, 0x5AB, "sqrtt/su $RB,$RC", + [(set F8RC:$RC, (fsqrt F8RC:$RB))], s_fsqrtt>; + +let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F8RC:$RA, F8RC:$RB) in { +def ADDT : FPForm<0x16, 0x5A0, "addt/su $RA,$RB,$RC", + [(set F8RC:$RC, (fadd F8RC:$RA, F8RC:$RB))], s_fadd>; +def SUBT : FPForm<0x16, 0x5A1, "subt/su $RA,$RB,$RC", + [(set F8RC:$RC, (fsub F8RC:$RA, F8RC:$RB))], s_fadd>; +def DIVT : FPForm<0x16, 0x5A3, "divt/su $RA,$RB,$RC", + [(set F8RC:$RC, (fdiv F8RC:$RA, F8RC:$RB))], s_fdivt>; +def MULT : FPForm<0x16, 0x5A2, "mult/su $RA,$RB,$RC", + [(set F8RC:$RC, (fmul F8RC:$RA, F8RC:$RB))], s_fmul>; + +def CPYST : FPForm<0x17, 0x020, "cpys $RA,$RB,$RC", + [(set F8RC:$RC, (fcopysign F8RC:$RB, F8RC:$RA))], s_fadd>; +def CPYSET : FPForm<0x17, 0x022, "cpyse $RA,$RB,$RC",[], s_fadd>; //Copy sign and exponent +def CPYSNT : FPForm<0x17, 0x021, "cpysn $RA,$RB,$RC", + [(set F8RC:$RC, (fneg (fcopysign F8RC:$RB, F8RC:$RA)))], s_fadd>; + +def CMPTEQ : FPForm<0x16, 0x5A5, "cmpteq/su $RA,$RB,$RC", [], s_fadd>; +// [(set F8RC:$RC, (seteq F8RC:$RA, F8RC:$RB))]>; +def CMPTLE : FPForm<0x16, 0x5A7, "cmptle/su $RA,$RB,$RC", [], s_fadd>; +// [(set F8RC:$RC, (setle F8RC:$RA, F8RC:$RB))]>; +def CMPTLT : FPForm<0x16, 0x5A6, "cmptlt/su $RA,$RB,$RC", [], s_fadd>; +// [(set F8RC:$RC, (setlt F8RC:$RA, F8RC:$RB))]>; +def CMPTUN : FPForm<0x16, 0x5A4, "cmptun/su $RA,$RB,$RC", [], s_fadd>; +// [(set F8RC:$RC, (setuo F8RC:$RA, F8RC:$RB))]>; +} + +//More CPYS forms: +let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F4RC:$RA, F8RC:$RB) in { +def CPYSTs : FPForm<0x17, 0x020, "cpys $RA,$RB,$RC", + [(set F8RC:$RC, (fcopysign F8RC:$RB, F4RC:$RA))], s_fadd>; +def CPYSNTs : FPForm<0x17, 0x021, "cpysn $RA,$RB,$RC", + [(set F8RC:$RC, (fneg (fcopysign F8RC:$RB, F4RC:$RA)))], s_fadd>; +} +let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F8RC:$RA, F4RC:$RB) in { +def CPYSSt : FPForm<0x17, 0x020, "cpys $RA,$RB,$RC", + [(set F4RC:$RC, (fcopysign F4RC:$RB, F8RC:$RA))], s_fadd>; +def CPYSESt : FPForm<0x17, 0x022, "cpyse $RA,$RB,$RC",[], s_fadd>; //Copy sign and exponent +def CPYSNSt : FPForm<0x17, 0x021, "cpysn $RA,$RB,$RC", + [(set F4RC:$RC, (fneg (fcopysign F4RC:$RB, F8RC:$RA)))], s_fadd>; +} + +//conditional moves, floats +let OutOperandList = (outs F4RC:$RDEST), + InOperandList = (ins F4RC:$RFALSE, F4RC:$RTRUE, F8RC:$RCOND), + Constraints = "$RTRUE = $RDEST" in { +def FCMOVEQS : FPForm<0x17, 0x02A, + "fcmoveq $RCOND,$RTRUE,$RDEST", + [], s_fcmov>; //FCMOVE if = zero +def FCMOVGES : FPForm<0x17, 0x02D, + "fcmovge $RCOND,$RTRUE,$RDEST", + [], s_fcmov>; //FCMOVE if >= zero +def FCMOVGTS : FPForm<0x17, 0x02F, + "fcmovgt $RCOND,$RTRUE,$RDEST", + [], s_fcmov>; //FCMOVE if > zero +def FCMOVLES : FPForm<0x17, 0x02E, + "fcmovle $RCOND,$RTRUE,$RDEST", + [], s_fcmov>; //FCMOVE if <= zero +def FCMOVLTS : FPForm<0x17, 0x02C, + "fcmovlt $RCOND,$RTRUE,$RDEST", + [], s_fcmov>; // FCMOVE if < zero +def FCMOVNES : FPForm<0x17, 0x02B, + "fcmovne $RCOND,$RTRUE,$RDEST", + [], s_fcmov>; //FCMOVE if != zero +} +//conditional moves, doubles +let OutOperandList = (outs F8RC:$RDEST), + InOperandList = (ins F8RC:$RFALSE, F8RC:$RTRUE, F8RC:$RCOND), + Constraints = "$RTRUE = $RDEST" in { +def FCMOVEQT : FPForm<0x17, 0x02A, "fcmoveq $RCOND,$RTRUE,$RDEST", [], s_fcmov>; +def FCMOVGET : FPForm<0x17, 0x02D, "fcmovge $RCOND,$RTRUE,$RDEST", [], s_fcmov>; +def FCMOVGTT : FPForm<0x17, 0x02F, "fcmovgt $RCOND,$RTRUE,$RDEST", [], s_fcmov>; +def FCMOVLET : FPForm<0x17, 0x02E, "fcmovle $RCOND,$RTRUE,$RDEST", [], s_fcmov>; +def FCMOVLTT : FPForm<0x17, 0x02C, "fcmovlt $RCOND,$RTRUE,$RDEST", [], s_fcmov>; +def FCMOVNET : FPForm<0x17, 0x02B, "fcmovne $RCOND,$RTRUE,$RDEST", [], s_fcmov>; +} + +//misc FP selects +//Select double + +def : Pat<(select (seteq F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setoeq F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setueq F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; + +def : Pat<(select (setne F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVEQT F8RC:$sf, F8RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setone F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVEQT F8RC:$sf, F8RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setune F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVEQT F8RC:$sf, F8RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; + +def : Pat<(select (setgt F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLT F8RC:$RB, F8RC:$RA))>; +def : Pat<(select (setogt F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLT F8RC:$RB, F8RC:$RA))>; +def : Pat<(select (setugt F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLT F8RC:$RB, F8RC:$RA))>; + +def : Pat<(select (setge F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLE F8RC:$RB, F8RC:$RA))>; +def : Pat<(select (setoge F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLE F8RC:$RB, F8RC:$RA))>; +def : Pat<(select (setuge F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLE F8RC:$RB, F8RC:$RA))>; + +def : Pat<(select (setlt F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLT F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setolt F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLT F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setult F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLT F8RC:$RA, F8RC:$RB))>; + +def : Pat<(select (setle F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLE F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setole F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLE F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setule F8RC:$RA, F8RC:$RB), F8RC:$st, F8RC:$sf), + (FCMOVNET F8RC:$sf, F8RC:$st, (CMPTLE F8RC:$RA, F8RC:$RB))>; + +//Select single +def : Pat<(select (seteq F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setoeq F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setueq F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; + +def : Pat<(select (setne F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVEQS F4RC:$sf, F4RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setone F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVEQS F4RC:$sf, F4RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setune F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVEQS F4RC:$sf, F4RC:$st, (CMPTEQ F8RC:$RA, F8RC:$RB))>; + +def : Pat<(select (setgt F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLT F8RC:$RB, F8RC:$RA))>; +def : Pat<(select (setogt F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLT F8RC:$RB, F8RC:$RA))>; +def : Pat<(select (setugt F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLT F8RC:$RB, F8RC:$RA))>; + +def : Pat<(select (setge F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLE F8RC:$RB, F8RC:$RA))>; +def : Pat<(select (setoge F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLE F8RC:$RB, F8RC:$RA))>; +def : Pat<(select (setuge F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLE F8RC:$RB, F8RC:$RA))>; + +def : Pat<(select (setlt F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLT F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setolt F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLT F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setult F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLT F8RC:$RA, F8RC:$RB))>; + +def : Pat<(select (setle F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLE F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setole F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLE F8RC:$RA, F8RC:$RB))>; +def : Pat<(select (setule F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf), + (FCMOVNES F4RC:$sf, F4RC:$st, (CMPTLE F8RC:$RA, F8RC:$RB))>; + + + +let OutOperandList = (outs GPRC:$RC), InOperandList = (ins F4RC:$RA), Fb = 31 in +def FTOIS : FPForm<0x1C, 0x078, "ftois $RA,$RC", + [(set GPRC:$RC, (bitconvert F4RC:$RA))], s_ftoi>; //Floating to integer move, S_floating +let OutOperandList = (outs GPRC:$RC), InOperandList = (ins F8RC:$RA), Fb = 31 in +def FTOIT : FPForm<0x1C, 0x070, "ftoit $RA,$RC", + [(set GPRC:$RC, (bitconvert F8RC:$RA))], s_ftoi>; //Floating to integer move +let OutOperandList = (outs F4RC:$RC), InOperandList = (ins GPRC:$RA), Fb = 31 in +def ITOFS : FPForm<0x14, 0x004, "itofs $RA,$RC", + [(set F4RC:$RC, (bitconvert GPRC:$RA))], s_itof>; //Integer to floating move, S_floating +let OutOperandList = (outs F8RC:$RC), InOperandList = (ins GPRC:$RA), Fb = 31 in +def ITOFT : FPForm<0x14, 0x024, "itoft $RA,$RC", + [(set F8RC:$RC, (bitconvert GPRC:$RA))], s_itof>; //Integer to floating move + + +let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in +def CVTQS : FPForm<0x16, 0x7BC, "cvtqs/sui $RB,$RC", + [(set F4RC:$RC, (Alpha_cvtqs F8RC:$RB))], s_fadd>; +let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in +def CVTQT : FPForm<0x16, 0x7BE, "cvtqt/sui $RB,$RC", + [(set F8RC:$RC, (Alpha_cvtqt F8RC:$RB))], s_fadd>; +let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in +def CVTTQ : FPForm<0x16, 0x52F, "cvttq/svc $RB,$RC", + [(set F8RC:$RC, (Alpha_cvttq F8RC:$RB))], s_fadd>; +let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F4RC:$RB), Fa = 31 in +def CVTST : FPForm<0x16, 0x6AC, "cvtst/s $RB,$RC", + [(set F8RC:$RC, (fextend F4RC:$RB))], s_fadd>; +let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in +def CVTTS : FPForm<0x16, 0x7AC, "cvtts/sui $RB,$RC", + [(set F4RC:$RC, (fround F8RC:$RB))], s_fadd>; + +def : Pat<(select GPRC:$RC, F8RC:$st, F8RC:$sf), + (f64 (FCMOVEQT F8RC:$st, F8RC:$sf, (ITOFT GPRC:$RC)))>; +def : Pat<(select GPRC:$RC, F4RC:$st, F4RC:$sf), + (f32 (FCMOVEQS F4RC:$st, F4RC:$sf, (ITOFT GPRC:$RC)))>; + +///////////////////////////////////////////////////////// +//Branching +///////////////////////////////////////////////////////// +class br_icc<bits<6> opc, string asmstr> + : BFormN<opc, (ins u64imm:$opc, GPRC:$R, target:$dst), + !strconcat(asmstr, " $R,$dst"), s_icbr>; +class br_fcc<bits<6> opc, string asmstr> + : BFormN<opc, (ins u64imm:$opc, F8RC:$R, target:$dst), + !strconcat(asmstr, " $R,$dst"), s_fbr>; + +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { +let Ra = 31, isBarrier = 1 in +def BR : BFormD<0x30, "br $$31,$DISP", [(br bb:$DISP)], s_ubr>; + +def COND_BRANCH_I : BFormN<0, (ins u64imm:$opc, GPRC:$R, target:$dst), + "{:comment} COND_BRANCH imm:$opc, GPRC:$R, bb:$dst", + s_icbr>; +def COND_BRANCH_F : BFormN<0, (ins u64imm:$opc, F8RC:$R, target:$dst), + "{:comment} COND_BRANCH imm:$opc, F8RC:$R, bb:$dst", + s_fbr>; +//Branches, int +def BEQ : br_icc<0x39, "beq">; +def BGE : br_icc<0x3E, "bge">; +def BGT : br_icc<0x3F, "bgt">; +def BLBC : br_icc<0x38, "blbc">; +def BLBS : br_icc<0x3C, "blbs">; +def BLE : br_icc<0x3B, "ble">; +def BLT : br_icc<0x3A, "blt">; +def BNE : br_icc<0x3D, "bne">; + +//Branches, float +def FBEQ : br_fcc<0x31, "fbeq">; +def FBGE : br_fcc<0x36, "fbge">; +def FBGT : br_fcc<0x37, "fbgt">; +def FBLE : br_fcc<0x33, "fble">; +def FBLT : br_fcc<0x32, "fblt">; +def FBNE : br_fcc<0x36, "fbne">; +} + +//An ugly trick to get the opcode as an imm I can use +def immBRCond : SDNodeXForm<imm, [{ + switch((uint64_t)N->getZExtValue()) { + default: assert(0 && "Unknown branch type"); + case 0: return getI64Imm(Alpha::BEQ); + case 1: return getI64Imm(Alpha::BNE); + case 2: return getI64Imm(Alpha::BGE); + case 3: return getI64Imm(Alpha::BGT); + case 4: return getI64Imm(Alpha::BLE); + case 5: return getI64Imm(Alpha::BLT); + case 6: return getI64Imm(Alpha::BLBS); + case 7: return getI64Imm(Alpha::BLBC); + case 20: return getI64Imm(Alpha::FBEQ); + case 21: return getI64Imm(Alpha::FBNE); + case 22: return getI64Imm(Alpha::FBGE); + case 23: return getI64Imm(Alpha::FBGT); + case 24: return getI64Imm(Alpha::FBLE); + case 25: return getI64Imm(Alpha::FBLT); + } +}]>; + +//Int cond patterns +def : Pat<(brcond (seteq GPRC:$RA, 0), bb:$DISP), + (COND_BRANCH_I (immBRCond 0), GPRC:$RA, bb:$DISP)>; +def : Pat<(brcond (setge GPRC:$RA, 0), bb:$DISP), + (COND_BRANCH_I (immBRCond 2), GPRC:$RA, bb:$DISP)>; +def : Pat<(brcond (setgt GPRC:$RA, 0), bb:$DISP), + (COND_BRANCH_I (immBRCond 3), GPRC:$RA, bb:$DISP)>; +def : Pat<(brcond (and GPRC:$RA, 1), bb:$DISP), + (COND_BRANCH_I (immBRCond 6), GPRC:$RA, bb:$DISP)>; +def : Pat<(brcond (setle GPRC:$RA, 0), bb:$DISP), + (COND_BRANCH_I (immBRCond 4), GPRC:$RA, bb:$DISP)>; +def : Pat<(brcond (setlt GPRC:$RA, 0), bb:$DISP), + (COND_BRANCH_I (immBRCond 5), GPRC:$RA, bb:$DISP)>; +def : Pat<(brcond (setne GPRC:$RA, 0), bb:$DISP), + (COND_BRANCH_I (immBRCond 1), GPRC:$RA, bb:$DISP)>; + +def : Pat<(brcond GPRC:$RA, bb:$DISP), + (COND_BRANCH_I (immBRCond 1), GPRC:$RA, bb:$DISP)>; +def : Pat<(brcond (setne GPRC:$RA, GPRC:$RB), bb:$DISP), + (COND_BRANCH_I (immBRCond 0), (CMPEQ GPRC:$RA, GPRC:$RB), bb:$DISP)>; +def : Pat<(brcond (setne GPRC:$RA, immUExt8:$L), bb:$DISP), + (COND_BRANCH_I (immBRCond 0), (CMPEQi GPRC:$RA, immUExt8:$L), bb:$DISP)>; + +//FP cond patterns +def : Pat<(brcond (seteq F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 20), F8RC:$RA, bb:$DISP)>; +def : Pat<(brcond (setne F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), F8RC:$RA, bb:$DISP)>; +def : Pat<(brcond (setge F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 22), F8RC:$RA, bb:$DISP)>; +def : Pat<(brcond (setgt F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 23), F8RC:$RA, bb:$DISP)>; +def : Pat<(brcond (setle F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 24), F8RC:$RA, bb:$DISP)>; +def : Pat<(brcond (setlt F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 25), F8RC:$RA, bb:$DISP)>; + + +def : Pat<(brcond (seteq F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTEQ F8RC:$RA, F8RC:$RB), bb:$DISP)>; +def : Pat<(brcond (setoeq F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTEQ F8RC:$RA, F8RC:$RB), bb:$DISP)>; +def : Pat<(brcond (setueq F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTEQ F8RC:$RA, F8RC:$RB), bb:$DISP)>; + +def : Pat<(brcond (setlt F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLT F8RC:$RA, F8RC:$RB), bb:$DISP)>; +def : Pat<(brcond (setolt F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLT F8RC:$RA, F8RC:$RB), bb:$DISP)>; +def : Pat<(brcond (setult F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLT F8RC:$RA, F8RC:$RB), bb:$DISP)>; + +def : Pat<(brcond (setle F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLE F8RC:$RA, F8RC:$RB), bb:$DISP)>; +def : Pat<(brcond (setole F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLE F8RC:$RA, F8RC:$RB), bb:$DISP)>; +def : Pat<(brcond (setule F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLE F8RC:$RA, F8RC:$RB), bb:$DISP)>; + +def : Pat<(brcond (setgt F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLT F8RC:$RB, F8RC:$RA), bb:$DISP)>; +def : Pat<(brcond (setogt F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLT F8RC:$RB, F8RC:$RA), bb:$DISP)>; +def : Pat<(brcond (setugt F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLT F8RC:$RB, F8RC:$RA), bb:$DISP)>; + +def : Pat<(brcond (setge F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLE F8RC:$RB, F8RC:$RA), bb:$DISP)>; +def : Pat<(brcond (setoge F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLE F8RC:$RB, F8RC:$RA), bb:$DISP)>; +def : Pat<(brcond (setuge F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), (CMPTLE F8RC:$RB, F8RC:$RA), bb:$DISP)>; + +def : Pat<(brcond (setne F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 20), (CMPTEQ F8RC:$RA, F8RC:$RB), bb:$DISP)>; +def : Pat<(brcond (setone F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 20), (CMPTEQ F8RC:$RA, F8RC:$RB), bb:$DISP)>; +def : Pat<(brcond (setune F8RC:$RA, F8RC:$RB), bb:$DISP), + (COND_BRANCH_F (immBRCond 20), (CMPTEQ F8RC:$RA, F8RC:$RB), bb:$DISP)>; + + +def : Pat<(brcond (setoeq F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 20), F8RC:$RA,bb:$DISP)>; +def : Pat<(brcond (setueq F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 20), F8RC:$RA,bb:$DISP)>; + +def : Pat<(brcond (setoge F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 22), F8RC:$RA,bb:$DISP)>; +def : Pat<(brcond (setuge F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 22), F8RC:$RA,bb:$DISP)>; + +def : Pat<(brcond (setogt F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 23), F8RC:$RA,bb:$DISP)>; +def : Pat<(brcond (setugt F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 23), F8RC:$RA,bb:$DISP)>; + +def : Pat<(brcond (setole F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 24), F8RC:$RA,bb:$DISP)>; +def : Pat<(brcond (setule F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 24), F8RC:$RA,bb:$DISP)>; + +def : Pat<(brcond (setolt F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 25), F8RC:$RA,bb:$DISP)>; +def : Pat<(brcond (setult F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 25), F8RC:$RA,bb:$DISP)>; + +def : Pat<(brcond (setone F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), F8RC:$RA,bb:$DISP)>; +def : Pat<(brcond (setune F8RC:$RA, immFPZ), bb:$DISP), + (COND_BRANCH_F (immBRCond 21), F8RC:$RA,bb:$DISP)>; + +//End Branches + +//S_floating : IEEE Single +//T_floating : IEEE Double + +//Unused instructions +//Mnemonic Format Opcode Description +//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 +//LDQ_U Mem 0B Load unaligned quadword +//MB Mfc 18.4000 Memory barrier +//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 +//MF_FPCR F-P 17.025 Move from FPCR +//MT_FPCR F-P 17.024 Move to FPCR +//There are in the Multimedia extensions, so let's not use them yet +//def MAXSB8 : OForm<0x1C, 0x3E, "MAXSB8 $RA,$RB,$RC">; //Vector signed byte maximum +//def MAXSW4 : OForm< 0x1C, 0x3F, "MAXSW4 $RA,$RB,$RC">; //Vector signed word maximum +//def MAXUB8 : OForm<0x1C, 0x3C, "MAXUB8 $RA,$RB,$RC">; //Vector unsigned byte maximum +//def MAXUW4 : OForm< 0x1C, 0x3D, "MAXUW4 $RA,$RB,$RC">; //Vector unsigned word maximum +//def MINSB8 : OForm< 0x1C, 0x38, "MINSB8 $RA,$RB,$RC">; //Vector signed byte minimum +//def MINSW4 : OForm< 0x1C, 0x39, "MINSW4 $RA,$RB,$RC">; //Vector signed word minimum +//def MINUB8 : OForm< 0x1C, 0x3A, "MINUB8 $RA,$RB,$RC">; //Vector unsigned byte minimum +//def MINUW4 : OForm< 0x1C, 0x3B, "MINUW4 $RA,$RB,$RC">; //Vector unsigned word minimum +//def PERR : OForm< 0x1C, 0x31, "PERR $RA,$RB,$RC">; //Pixel error +//def PKLB : OForm< 0x1C, 0x37, "PKLB $RA,$RB,$RC">; //Pack longwords to bytes +//def PKWB : OForm<0x1C, 0x36, "PKWB $RA,$RB,$RC">; //Pack words to bytes +//def UNPKBL : OForm< 0x1C, 0x35, "UNPKBL $RA,$RB,$RC">; //Unpack bytes to longwords +//def UNPKBW : OForm< 0x1C, 0x34, "UNPKBW $RA,$RB,$RC">; //Unpack bytes to words +//CVTLQ F-P 17.010 Convert longword to quadword +//CVTQL F-P 17.030 Convert quadword to longword + + +//Constant handling + +def immConst2Part : PatLeaf<(imm), [{ + //true if imm fits in a LDAH LDA pair + int64_t val = (int64_t)N->getZExtValue(); + return (val <= IMM_FULLHIGH && val >= IMM_FULLLOW); +}]>; +def immConst2PartInt : PatLeaf<(imm), [{ + //true if imm fits in a LDAH LDA pair with zeroext + uint64_t uval = N->getZExtValue(); + int32_t val32 = (int32_t)uval; + return ((uval >> 32) == 0 && //empty upper bits + val32 <= IMM_FULLHIGH); +// val32 >= IMM_FULLLOW + IMM_LOW * IMM_MULT); //Always True +}], SExt32>; + +def : Pat<(i64 immConst2Part:$imm), + (LDA (LL16 immConst2Part:$imm), (LDAH (LH16 immConst2Part:$imm), R31))>; + +def : Pat<(i64 immSExt16:$imm), + (LDA immSExt16:$imm, R31)>; + +def : Pat<(i64 immSExt16int:$imm), + (ZAPNOTi (LDA (SExt16 immSExt16int:$imm), R31), 15)>; +def : Pat<(i64 immConst2PartInt:$imm), + (ZAPNOTi (LDA (LL16 (i64 (SExt32 immConst2PartInt:$imm))), + (LDAH (LH16 (i64 (SExt32 immConst2PartInt:$imm))), R31)), 15)>; + + +//TODO: I want to just define these like this! +//def : Pat<(i64 0), +// (R31)>; +//def : Pat<(f64 0.0), +// (F31)>; +//def : Pat<(f64 -0.0), +// (CPYSNT F31, F31)>; +//def : Pat<(f32 0.0), +// (F31)>; +//def : Pat<(f32 -0.0), +// (CPYSNS F31, F31)>; + +//Misc Patterns: + +def : Pat<(sext_inreg GPRC:$RB, i32), + (ADDLi GPRC:$RB, 0)>; + +def : Pat<(fabs F8RC:$RB), + (CPYST F31, F8RC:$RB)>; +def : Pat<(fabs F4RC:$RB), + (CPYSS F31, F4RC:$RB)>; +def : Pat<(fneg F8RC:$RB), + (CPYSNT F8RC:$RB, F8RC:$RB)>; +def : Pat<(fneg F4RC:$RB), + (CPYSNS F4RC:$RB, F4RC:$RB)>; + +def : Pat<(fcopysign F4RC:$A, (fneg F4RC:$B)), + (CPYSNS F4RC:$B, F4RC:$A)>; +def : Pat<(fcopysign F8RC:$A, (fneg F8RC:$B)), + (CPYSNT F8RC:$B, F8RC:$A)>; +def : Pat<(fcopysign F4RC:$A, (fneg F8RC:$B)), + (CPYSNSt F8RC:$B, F4RC:$A)>; +def : Pat<(fcopysign F8RC:$A, (fneg F4RC:$B)), + (CPYSNTs F4RC:$B, F8RC:$A)>; + +//Yes, signed multiply high is ugly +def : Pat<(mulhs GPRC:$RA, GPRC:$RB), + (SUBQr (UMULHr GPRC:$RA, GPRC:$RB), (ADDQr (CMOVGEr GPRC:$RB, R31, GPRC:$RA), + (CMOVGEr GPRC:$RA, R31, GPRC:$RB)))>; + +//Stupid crazy arithmetic stuff: +let AddedComplexity = 1 in { +def : Pat<(mul GPRC:$RA, 5), (S4ADDQr GPRC:$RA, GPRC:$RA)>; +def : Pat<(mul GPRC:$RA, 9), (S8ADDQr GPRC:$RA, GPRC:$RA)>; +def : Pat<(mul GPRC:$RA, 3), (S4SUBQr GPRC:$RA, GPRC:$RA)>; +def : Pat<(mul GPRC:$RA, 7), (S8SUBQr GPRC:$RA, GPRC:$RA)>; + +//slight tree expansion if we are multiplying near to a power of 2 +//n is above a power of 2 +def : Pat<(mul GPRC:$RA, immRem1:$imm), + (ADDQr (SLr GPRC:$RA, (nearP2X immRem1:$imm)), GPRC:$RA)>; +def : Pat<(mul GPRC:$RA, immRem2:$imm), + (ADDQr (SLr GPRC:$RA, (nearP2X immRem2:$imm)), (ADDQr GPRC:$RA, GPRC:$RA))>; +def : Pat<(mul GPRC:$RA, immRem3:$imm), + (ADDQr (SLr GPRC:$RA, (nearP2X immRem3:$imm)), (S4SUBQr GPRC:$RA, GPRC:$RA))>; +def : Pat<(mul GPRC:$RA, immRem4:$imm), + (S4ADDQr GPRC:$RA, (SLr GPRC:$RA, (nearP2X immRem4:$imm)))>; +def : Pat<(mul GPRC:$RA, immRem5:$imm), + (ADDQr (SLr GPRC:$RA, (nearP2X immRem5:$imm)), (S4ADDQr GPRC:$RA, GPRC:$RA))>; +def : Pat<(mul GPRC:$RA, immRemP2:$imm), + (ADDQr (SLr GPRC:$RA, (nearP2X immRemP2:$imm)), (SLi GPRC:$RA, (nearP2RemX immRemP2:$imm)))>; + +//n is below a power of 2 +//FIXME: figure out why something is truncating the imm to 32bits +// this will fix 2007-11-27-mulneg3 +//def : Pat<(mul GPRC:$RA, immRem1n:$imm), +// (SUBQr (SLr GPRC:$RA, (nearP2X immRem1n:$imm)), GPRC:$RA)>; +//def : Pat<(mul GPRC:$RA, immRem2n:$imm), +// (SUBQr (SLr GPRC:$RA, (nearP2X immRem2n:$imm)), (ADDQr GPRC:$RA, GPRC:$RA))>; +//def : Pat<(mul GPRC:$RA, immRem3n:$imm), +// (SUBQr (SLr GPRC:$RA, (nearP2X immRem3n:$imm)), (S4SUBQr GPRC:$RA, GPRC:$RA))>; +//def : Pat<(mul GPRC:$RA, immRem4n:$imm), +// (SUBQr (SLr GPRC:$RA, (nearP2X immRem4n:$imm)), (SLi GPRC:$RA, 2))>; +//def : Pat<(mul GPRC:$RA, immRem5n:$imm), +// (SUBQr (SLr GPRC:$RA, (nearP2X immRem5n:$imm)), (S4ADDQr GPRC:$RA, GPRC:$RA))>; +//def : Pat<(mul GPRC:$RA, immRemP2n:$imm), +// (SUBQr (SLr GPRC:$RA, (nearP2X immRemP2n:$imm)), (SLi GPRC:$RA, (nearP2RemX immRemP2n:$imm)))>; +} //Added complexity diff --git a/contrib/llvm/lib/Target/Alpha/AlphaLLRP.cpp b/contrib/llvm/lib/Target/Alpha/AlphaLLRP.cpp new file mode 100644 index 0000000..85fbfd1 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaLLRP.cpp @@ -0,0 +1,158 @@ +//===-- AlphaLLRP.cpp - Alpha Load Load Replay Trap elimination pass. -- --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Here we check for potential replay traps introduced by the spiller +// We also align some branch targets if we can do so for free. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "alpha-nops" +#include "Alpha.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +STATISTIC(nopintro, "Number of nops inserted"); +STATISTIC(nopalign, "Number of nops inserted for alignment"); + +namespace { + cl::opt<bool> + AlignAll("alpha-align-all", cl::Hidden, + cl::desc("Align all blocks")); + + struct AlphaLLRPPass : public MachineFunctionPass { + /// Target machine description which we query for reg. names, data + /// layout, etc. + /// + AlphaTargetMachine &TM; + + static char ID; + AlphaLLRPPass(AlphaTargetMachine &tm) + : MachineFunctionPass(ID), TM(tm) { } + + virtual const char *getPassName() const { + return "Alpha NOP inserter"; + } + + bool runOnMachineFunction(MachineFunction &F) { + const TargetInstrInfo *TII = F.getTarget().getInstrInfo(); + bool Changed = false; + MachineInstr* prev[3] = {0,0,0}; + DebugLoc dl; + unsigned count = 0; + for (MachineFunction::iterator FI = F.begin(), FE = F.end(); + FI != FE; ++FI) { + MachineBasicBlock& MBB = *FI; + bool ub = false; + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { + if (count%4 == 0) + prev[0] = prev[1] = prev[2] = 0; //Slots cleared at fetch boundary + ++count; + MachineInstr *MI = I++; + switch (MI->getOpcode()) { + case Alpha::LDQ: case Alpha::LDL: + case Alpha::LDWU: case Alpha::LDBU: + case Alpha::LDT: case Alpha::LDS: + case Alpha::STQ: case Alpha::STL: + case Alpha::STW: case Alpha::STB: + case Alpha::STT: case Alpha::STS: + if (MI->getOperand(2).getReg() == Alpha::R30) { + if (prev[0] && + prev[0]->getOperand(2).getReg() == MI->getOperand(2).getReg()&& + prev[0]->getOperand(1).getImm() == MI->getOperand(1).getImm()){ + prev[0] = prev[1]; + prev[1] = prev[2]; + prev[2] = 0; + BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31) + .addReg(Alpha::R31) + .addReg(Alpha::R31); + Changed = true; nopintro += 1; + count += 1; + } else if (prev[1] + && prev[1]->getOperand(2).getReg() == + MI->getOperand(2).getReg() + && prev[1]->getOperand(1).getImm() == + MI->getOperand(1).getImm()) { + prev[0] = prev[2]; + prev[1] = prev[2] = 0; + BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31) + .addReg(Alpha::R31) + .addReg(Alpha::R31); + BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31) + .addReg(Alpha::R31) + .addReg(Alpha::R31); + Changed = true; nopintro += 2; + count += 2; + } else if (prev[2] + && prev[2]->getOperand(2).getReg() == + MI->getOperand(2).getReg() + && prev[2]->getOperand(1).getImm() == + MI->getOperand(1).getImm()) { + prev[0] = prev[1] = prev[2] = 0; + BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31) + .addReg(Alpha::R31).addReg(Alpha::R31); + BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31) + .addReg(Alpha::R31).addReg(Alpha::R31); + BuildMI(MBB, MI, dl, TII->get(Alpha::BISr), Alpha::R31) + .addReg(Alpha::R31).addReg(Alpha::R31); + Changed = true; nopintro += 3; + count += 3; + } + prev[0] = prev[1]; + prev[1] = prev[2]; + prev[2] = MI; + break; + } + prev[0] = prev[1]; + prev[1] = prev[2]; + prev[2] = 0; + break; + case Alpha::ALTENT: + case Alpha::MEMLABEL: + case Alpha::PCLABEL: + --count; + break; + case Alpha::BR: + case Alpha::JMP: + ub = true; + //fall through + default: + prev[0] = prev[1]; + prev[1] = prev[2]; + prev[2] = 0; + break; + } + } + if (ub || AlignAll) { + //we can align stuff for free at this point + while (count % 4) { + BuildMI(MBB, MBB.end(), dl, TII->get(Alpha::BISr), Alpha::R31) + .addReg(Alpha::R31).addReg(Alpha::R31); + ++count; + ++nopalign; + prev[0] = prev[1]; + prev[1] = prev[2]; + prev[2] = 0; + } + } + } + return Changed; + } + }; + char AlphaLLRPPass::ID = 0; +} // end of anonymous namespace + +FunctionPass *llvm::createAlphaLLRPPass(AlphaTargetMachine &tm) { + return new AlphaLLRPPass(tm); +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaMachineFunctionInfo.h b/contrib/llvm/lib/Target/Alpha/AlphaMachineFunctionInfo.h new file mode 100644 index 0000000..186738c --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaMachineFunctionInfo.h @@ -0,0 +1,62 @@ +//====- AlphaMachineFuctionInfo.h - Alpha machine function info -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares Alpha-specific per-machine-function information. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAMACHINEFUNCTIONINFO_H +#define ALPHAMACHINEFUNCTIONINFO_H + +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +/// AlphaMachineFunctionInfo - This class is derived from MachineFunction +/// private Alpha target-specific information for each MachineFunction. +class AlphaMachineFunctionInfo : public MachineFunctionInfo { + /// GlobalBaseReg - keeps track of the virtual register initialized for + /// use as the global base register. This is used for PIC in some PIC + /// relocation models. + unsigned GlobalBaseReg; + + /// GlobalRetAddr = keeps track of the virtual register initialized for + /// the return address value. + unsigned GlobalRetAddr; + + /// VarArgsOffset - What is the offset to the first vaarg + int VarArgsOffset; + /// VarArgsBase - What is the base FrameIndex + int VarArgsBase; + +public: + AlphaMachineFunctionInfo() : GlobalBaseReg(0), GlobalRetAddr(0), + VarArgsOffset(0), VarArgsBase(0) {} + + explicit AlphaMachineFunctionInfo(MachineFunction &MF) : GlobalBaseReg(0), + GlobalRetAddr(0), + VarArgsOffset(0), + VarArgsBase(0) {} + + unsigned getGlobalBaseReg() const { return GlobalBaseReg; } + void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } + + unsigned getGlobalRetAddr() const { return GlobalRetAddr; } + void setGlobalRetAddr(unsigned Reg) { GlobalRetAddr = Reg; } + + int getVarArgsOffset() const { return VarArgsOffset; } + void setVarArgsOffset(int Offset) { VarArgsOffset = Offset; } + + int getVarArgsBase() const { return VarArgsBase; } + void setVarArgsBase(int Base) { VarArgsBase = Base; } +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp b/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp new file mode 100644 index 0000000..8b6230f --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -0,0 +1,199 @@ +//===- AlphaRegisterInfo.cpp - Alpha Register Information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Alpha implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "reginfo" +#include "Alpha.h" +#include "AlphaRegisterInfo.h" +#include "llvm/Constants.h" +#include "llvm/Type.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include <cstdlib> + +#define GET_REGINFO_TARGET_DESC +#include "AlphaGenRegisterInfo.inc" + +using namespace llvm; + +AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii) + : AlphaGenRegisterInfo(Alpha::R26), TII(tii) { +} + +static long getUpper16(long l) { + long y = l / Alpha::IMM_MULT; + if (l % Alpha::IMM_MULT > Alpha::IMM_HIGH) + ++y; + return y; +} + +static long getLower16(long l) { + long h = getUpper16(l); + return l - h * Alpha::IMM_MULT; +} + +const unsigned* AlphaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) + const { + static const unsigned CalleeSavedRegs[] = { + Alpha::R9, Alpha::R10, + Alpha::R11, Alpha::R12, + Alpha::R13, Alpha::R14, + Alpha::F2, Alpha::F3, + Alpha::F4, Alpha::F5, + Alpha::F6, Alpha::F7, + Alpha::F8, Alpha::F9, 0 + }; + return CalleeSavedRegs; +} + +BitVector AlphaRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + Reserved.set(Alpha::R15); + Reserved.set(Alpha::R29); + Reserved.set(Alpha::R30); + Reserved.set(Alpha::R31); + return Reserved; +} + +//===----------------------------------------------------------------------===// +// Stack Frame Processing methods +//===----------------------------------------------------------------------===// + +void AlphaRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + if (TFI->hasFP(MF)) { + // 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; + uint64_t Amount = Old->getOperand(0).getImm(); + 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 = TFI->getStackAlignment(); + Amount = (Amount+Align-1)/Align*Align; + + MachineInstr *New; + if (Old->getOpcode() == Alpha::ADJUSTSTACKDOWN) { + New=BuildMI(MF, Old->getDebugLoc(), TII.get(Alpha::LDA), Alpha::R30) + .addImm(-Amount).addReg(Alpha::R30); + } else { + assert(Old->getOpcode() == Alpha::ADJUSTSTACKUP); + New=BuildMI(MF, Old->getDebugLoc(), TII.get(Alpha::LDA), Alpha::R30) + .addImm(Amount).addReg(Alpha::R30); + } + + // Replace the pseudo instruction with a new instruction... + MBB.insert(I, New); + } + } + + MBB.erase(I); +} + +//Alpha has a slightly funny stack: +//Args +//<- incoming SP +//fixed locals (and spills, callee saved, etc) +//<- FP +//variable locals +//<- SP + +void +AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS) const { + assert(SPAdj == 0 && "Unexpected"); + + unsigned i = 0; + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + bool FP = TFI->hasFP(MF); + + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(i).getIndex(); + + // Add the base register of R30 (SP) or R15 (FP). + MI.getOperand(i + 1).ChangeToRegister(FP ? Alpha::R15 : Alpha::R30, false); + + // Now add the frame object offset to the offset from the virtual frame index. + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + + DEBUG(errs() << "FI: " << FrameIndex << " Offset: " << Offset << "\n"); + + Offset += MF.getFrameInfo()->getStackSize(); + + DEBUG(errs() << "Corrected Offset " << Offset + << " for stack size: " << MF.getFrameInfo()->getStackSize() << "\n"); + + if (Offset > Alpha::IMM_HIGH || Offset < Alpha::IMM_LOW) { + DEBUG(errs() << "Unconditionally using R28 for evil purposes Offset: " + << Offset << "\n"); + //so in this case, we need to use a temporary register, and move the + //original inst off the SP/FP + //fix up the old: + MI.getOperand(i + 1).ChangeToRegister(Alpha::R28, false); + MI.getOperand(i).ChangeToImmediate(getLower16(Offset)); + //insert the new + MachineInstr* nMI=BuildMI(MF, MI.getDebugLoc(), + TII.get(Alpha::LDAH), Alpha::R28) + .addImm(getUpper16(Offset)).addReg(FP ? Alpha::R15 : Alpha::R30); + MBB.insert(II, nMI); + } else { + MI.getOperand(i).ChangeToImmediate(Offset); + } +} + +unsigned AlphaRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + return TFI->hasFP(MF) ? Alpha::R15 : Alpha::R30; +} + +unsigned AlphaRegisterInfo::getEHExceptionRegister() const { + llvm_unreachable("What is the exception register"); + return 0; +} + +unsigned AlphaRegisterInfo::getEHHandlerRegister() const { + llvm_unreachable("What is the exception handler register"); + return 0; +} + +std::string AlphaRegisterInfo::getPrettyName(unsigned reg) +{ + std::string s(AlphaRegDesc[reg].Name); + return s; +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.h b/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.h new file mode 100644 index 0000000..e35be27 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.h @@ -0,0 +1,56 @@ +//===- AlphaRegisterInfo.h - Alpha Register Information Impl ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Alpha implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAREGISTERINFO_H +#define ALPHAREGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "AlphaGenRegisterInfo.inc" + +namespace llvm { + +class TargetInstrInfo; +class Type; + +struct AlphaRegisterInfo : public AlphaGenRegisterInfo { + const TargetInstrInfo &TII; + + AlphaRegisterInfo(const TargetInstrInfo &tii); + + /// Code Generation virtual methods... + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + void eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS = NULL) const; + + // Debug information queries. + unsigned getFrameRegister(const MachineFunction &MF) const; + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + + static std::string getPrettyName(unsigned reg); +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.td b/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.td new file mode 100644 index 0000000..32120d7 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaRegisterInfo.td @@ -0,0 +1,133 @@ +//===- AlphaRegisterInfo.td - The Alpha Register File ------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Alpha register set. +// +//===----------------------------------------------------------------------===// + +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">, DwarfRegNum<[0]>; +def R1 : GPR< 1, "$1">, DwarfRegNum<[1]>; +def R2 : GPR< 2, "$2">, DwarfRegNum<[2]>; +def R3 : GPR< 3, "$3">, DwarfRegNum<[3]>; +def R4 : GPR< 4, "$4">, DwarfRegNum<[4]>; +def R5 : GPR< 5, "$5">, DwarfRegNum<[5]>; +def R6 : GPR< 6, "$6">, DwarfRegNum<[6]>; +def R7 : GPR< 7, "$7">, DwarfRegNum<[7]>; +def R8 : GPR< 8, "$8">, DwarfRegNum<[8]>; +def R9 : GPR< 9, "$9">, DwarfRegNum<[9]>; +def R10 : GPR<10, "$10">, DwarfRegNum<[10]>; +def R11 : GPR<11, "$11">, DwarfRegNum<[11]>; +def R12 : GPR<12, "$12">, DwarfRegNum<[12]>; +def R13 : GPR<13, "$13">, DwarfRegNum<[13]>; +def R14 : GPR<14, "$14">, DwarfRegNum<[14]>; +def R15 : GPR<15, "$15">, DwarfRegNum<[15]>; +def R16 : GPR<16, "$16">, DwarfRegNum<[16]>; +def R17 : GPR<17, "$17">, DwarfRegNum<[17]>; +def R18 : GPR<18, "$18">, DwarfRegNum<[18]>; +def R19 : GPR<19, "$19">, DwarfRegNum<[19]>; +def R20 : GPR<20, "$20">, DwarfRegNum<[20]>; +def R21 : GPR<21, "$21">, DwarfRegNum<[21]>; +def R22 : GPR<22, "$22">, DwarfRegNum<[22]>; +def R23 : GPR<23, "$23">, DwarfRegNum<[23]>; +def R24 : GPR<24, "$24">, DwarfRegNum<[24]>; +def R25 : GPR<25, "$25">, DwarfRegNum<[25]>; +def R26 : GPR<26, "$26">, DwarfRegNum<[26]>; +def R27 : GPR<27, "$27">, DwarfRegNum<[27]>; +def R28 : GPR<28, "$28">, DwarfRegNum<[28]>; +def R29 : GPR<29, "$29">, DwarfRegNum<[29]>; +def R30 : GPR<30, "$30">, DwarfRegNum<[30]>; +def R31 : GPR<31, "$31">, DwarfRegNum<[31]>; + +// Floating-point registers +def F0 : FPR< 0, "$f0">, DwarfRegNum<[33]>; +def F1 : FPR< 1, "$f1">, DwarfRegNum<[34]>; +def F2 : FPR< 2, "$f2">, DwarfRegNum<[35]>; +def F3 : FPR< 3, "$f3">, DwarfRegNum<[36]>; +def F4 : FPR< 4, "$f4">, DwarfRegNum<[37]>; +def F5 : FPR< 5, "$f5">, DwarfRegNum<[38]>; +def F6 : FPR< 6, "$f6">, DwarfRegNum<[39]>; +def F7 : FPR< 7, "$f7">, DwarfRegNum<[40]>; +def F8 : FPR< 8, "$f8">, DwarfRegNum<[41]>; +def F9 : FPR< 9, "$f9">, DwarfRegNum<[42]>; +def F10 : FPR<10, "$f10">, DwarfRegNum<[43]>; +def F11 : FPR<11, "$f11">, DwarfRegNum<[44]>; +def F12 : FPR<12, "$f12">, DwarfRegNum<[45]>; +def F13 : FPR<13, "$f13">, DwarfRegNum<[46]>; +def F14 : FPR<14, "$f14">, DwarfRegNum<[47]>; +def F15 : FPR<15, "$f15">, DwarfRegNum<[48]>; +def F16 : FPR<16, "$f16">, DwarfRegNum<[49]>; +def F17 : FPR<17, "$f17">, DwarfRegNum<[50]>; +def F18 : FPR<18, "$f18">, DwarfRegNum<[51]>; +def F19 : FPR<19, "$f19">, DwarfRegNum<[52]>; +def F20 : FPR<20, "$f20">, DwarfRegNum<[53]>; +def F21 : FPR<21, "$f21">, DwarfRegNum<[54]>; +def F22 : FPR<22, "$f22">, DwarfRegNum<[55]>; +def F23 : FPR<23, "$f23">, DwarfRegNum<[56]>; +def F24 : FPR<24, "$f24">, DwarfRegNum<[57]>; +def F25 : FPR<25, "$f25">, DwarfRegNum<[58]>; +def F26 : FPR<26, "$f26">, DwarfRegNum<[59]>; +def F27 : FPR<27, "$f27">, DwarfRegNum<[60]>; +def F28 : FPR<28, "$f28">, DwarfRegNum<[61]>; +def F29 : FPR<29, "$f29">, DwarfRegNum<[62]>; +def F30 : FPR<30, "$f30">, DwarfRegNum<[63]>; +def F31 : FPR<31, "$f31">, DwarfRegNum<[64]>; + + // //#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<"Alpha", [i64], 64, (add + // Volatile + R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, + R23, R24, R25, R28, + //Special meaning, but volatile + R27, //procedure address + R26, //return address + R29, //global offset table address + // Non-volatile + R9, R10, R11, R12, R13, R14, +// Don't allocate 15, 30, 31 + R15, R30, R31)>; //zero + +def F4RC : RegisterClass<"Alpha", [f32], 64, (add F0, F1, + F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, + F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, + // Saved: + F2, F3, F4, F5, F6, F7, F8, F9, + F31)>; //zero + +def F8RC : RegisterClass<"Alpha", [f64], 64, (add F4RC)>; diff --git a/contrib/llvm/lib/Target/Alpha/AlphaRelocations.h b/contrib/llvm/lib/Target/Alpha/AlphaRelocations.h new file mode 100644 index 0000000..4c92045 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaRelocations.h @@ -0,0 +1,31 @@ +//===- AlphaRelocations.h - Alpha 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 Alpha target-specific relocation types. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHARELOCATIONS_H +#define ALPHARELOCATIONS_H + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + namespace Alpha { + enum RelocationType { + reloc_literal, + reloc_gprellow, + reloc_gprelhigh, + reloc_gpdist, + reloc_bsr + }; + } +} + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/AlphaSchedule.td b/contrib/llvm/lib/Target/Alpha/AlphaSchedule.td new file mode 100644 index 0000000..3703dd4 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaSchedule.td @@ -0,0 +1,85 @@ +//===- AlphaSchedule.td - Alpha Scheduling Definitions -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//This is table 2-2 from the 21264 compiler writers guide +//modified some + +//Pipelines + +def L0 : FuncUnit; +def L1 : FuncUnit; +def FST0 : FuncUnit; +def FST1 : FuncUnit; +def U0 : FuncUnit; +def U1 : FuncUnit; +def FA : FuncUnit; +def FM : FuncUnit; + +def s_ild : InstrItinClass; +def s_fld : InstrItinClass; +def s_ist : InstrItinClass; +def s_fst : InstrItinClass; +def s_lda : InstrItinClass; +def s_rpcc : InstrItinClass; +def s_rx : InstrItinClass; +def s_mxpr : InstrItinClass; +def s_icbr : InstrItinClass; +def s_ubr : InstrItinClass; +def s_jsr : InstrItinClass; +def s_iadd : InstrItinClass; +def s_ilog : InstrItinClass; +def s_ishf : InstrItinClass; +def s_cmov : InstrItinClass; +def s_imul : InstrItinClass; +def s_imisc : InstrItinClass; +def s_fbr : InstrItinClass; +def s_fadd : InstrItinClass; +def s_fmul : InstrItinClass; +def s_fcmov : InstrItinClass; +def s_fdivt : InstrItinClass; +def s_fdivs : InstrItinClass; +def s_fsqrts: InstrItinClass; +def s_fsqrtt: InstrItinClass; +def s_ftoi : InstrItinClass; +def s_itof : InstrItinClass; +def s_pseudo : InstrItinClass; + +//Table 2-4 Instruction Class Latency in Cycles +//modified some + +def Alpha21264Itineraries : ProcessorItineraries< + [L0, L1, FST0, FST1, U0, U1, FA, FM], [], [ + InstrItinData<s_ild , [InstrStage<3, [L0, L1]>]>, + InstrItinData<s_fld , [InstrStage<4, [L0, L1]>]>, + InstrItinData<s_ist , [InstrStage<0, [L0, L1]>]>, + InstrItinData<s_fst , [InstrStage<0, [FST0, FST1, L0, L1]>]>, + InstrItinData<s_lda , [InstrStage<1, [L0, L1, U0, U1]>]>, + InstrItinData<s_rpcc , [InstrStage<1, [L1]>]>, + InstrItinData<s_rx , [InstrStage<1, [L1]>]>, + InstrItinData<s_mxpr , [InstrStage<1, [L0, L1]>]>, + InstrItinData<s_icbr , [InstrStage<0, [U0, U1]>]>, + InstrItinData<s_ubr , [InstrStage<3, [U0, U1]>]>, + InstrItinData<s_jsr , [InstrStage<3, [L0]>]>, + InstrItinData<s_iadd , [InstrStage<1, [L0, U0, L1, U1]>]>, + InstrItinData<s_ilog , [InstrStage<1, [L0, U0, L1, U1]>]>, + InstrItinData<s_ishf , [InstrStage<1, [U0, U1]>]>, + InstrItinData<s_cmov , [InstrStage<1, [L0, U0, L1, U1]>]>, + InstrItinData<s_imul , [InstrStage<7, [U1]>]>, + InstrItinData<s_imisc , [InstrStage<3, [U0]>]>, + InstrItinData<s_fbr , [InstrStage<0, [FA]>]>, + InstrItinData<s_fadd , [InstrStage<6, [FA]>]>, + InstrItinData<s_fmul , [InstrStage<6, [FM]>]>, + InstrItinData<s_fcmov , [InstrStage<6, [FA]>]>, + InstrItinData<s_fdivs , [InstrStage<12, [FA]>]>, + InstrItinData<s_fdivt , [InstrStage<15, [FA]>]>, + InstrItinData<s_fsqrts , [InstrStage<18, [FA]>]>, + InstrItinData<s_fsqrtt , [InstrStage<33, [FA]>]>, + InstrItinData<s_ftoi , [InstrStage<3, [FST0, FST1, L0, L1]>]>, + InstrItinData<s_itof , [InstrStage<4, [L0, L1]>]> +]>; diff --git a/contrib/llvm/lib/Target/Alpha/AlphaSelectionDAGInfo.cpp b/contrib/llvm/lib/Target/Alpha/AlphaSelectionDAGInfo.cpp new file mode 100644 index 0000000..f1958fe --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaSelectionDAGInfo.cpp @@ -0,0 +1,23 @@ +//===-- AlphaSelectionDAGInfo.cpp - Alpha SelectionDAG Info ---------------===// +// +// 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 AlphaSelectionDAGInfo class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "alpha-selectiondag-info" +#include "AlphaTargetMachine.h" +using namespace llvm; + +AlphaSelectionDAGInfo::AlphaSelectionDAGInfo(const AlphaTargetMachine &TM) + : TargetSelectionDAGInfo(TM) { +} + +AlphaSelectionDAGInfo::~AlphaSelectionDAGInfo() { +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaSelectionDAGInfo.h b/contrib/llvm/lib/Target/Alpha/AlphaSelectionDAGInfo.h new file mode 100644 index 0000000..3405cc0 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaSelectionDAGInfo.h @@ -0,0 +1,31 @@ +//===-- AlphaSelectionDAGInfo.h - Alpha SelectionDAG Info -------*- 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 Alpha subclass for TargetSelectionDAGInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHASELECTIONDAGINFO_H +#define ALPHASELECTIONDAGINFO_H + +#include "llvm/Target/TargetSelectionDAGInfo.h" + +namespace llvm { + +class AlphaTargetMachine; + +class AlphaSelectionDAGInfo : public TargetSelectionDAGInfo { +public: + explicit AlphaSelectionDAGInfo(const AlphaTargetMachine &TM); + ~AlphaSelectionDAGInfo(); +}; + +} + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/AlphaSubtarget.cpp b/contrib/llvm/lib/Target/Alpha/AlphaSubtarget.cpp new file mode 100644 index 0000000..bd55ce9 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaSubtarget.cpp @@ -0,0 +1,35 @@ +//===- AlphaSubtarget.cpp - Alpha Subtarget Information ---------*- 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 the Alpha specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#include "AlphaSubtarget.h" +#include "Alpha.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "AlphaGenSubtargetInfo.inc" + +using namespace llvm; + +AlphaSubtarget::AlphaSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS) + : AlphaGenSubtargetInfo(TT, CPU, FS), HasCT(false) { + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic"; + + // Parse features string. + ParseSubtargetFeatures(CPUName, FS); + + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(CPUName); +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaSubtarget.h b/contrib/llvm/lib/Target/Alpha/AlphaSubtarget.h new file mode 100644 index 0000000..70b3116 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaSubtarget.h @@ -0,0 +1,49 @@ +//=====-- AlphaSubtarget.h - Define Subtarget for the Alpha --*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Alpha specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHASUBTARGET_H +#define ALPHASUBTARGET_H + +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/MC/MCInstrItineraries.h" +#include <string> + +#define GET_SUBTARGETINFO_HEADER +#include "AlphaGenSubtargetInfo.inc" + +namespace llvm { +class StringRe; + +class AlphaSubtarget : public AlphaGenSubtargetInfo { +protected: + + bool HasCT; + + InstrItineraryData InstrItins; + +public: + /// This constructor initializes the data members to match that + /// of the specified triple. + /// + AlphaSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS); + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + + bool hasCT() const { return HasCT; } +}; +} // End llvm namespace + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/AlphaTargetMachine.cpp b/contrib/llvm/lib/Target/Alpha/AlphaTargetMachine.cpp new file mode 100644 index 0000000..fc9a677 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaTargetMachine.cpp @@ -0,0 +1,51 @@ +//===-- AlphaTargetMachine.cpp - Define TargetMachine for Alpha -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +#include "AlphaTargetMachine.h" +#include "llvm/PassManager.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +extern "C" void LLVMInitializeAlphaTarget() { + // Register the target. + RegisterTargetMachine<AlphaTargetMachine> X(TheAlphaTarget); +} + +AlphaTargetMachine::AlphaTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM) + : LLVMTargetMachine(T, TT, CPU, FS, RM, CM), + DataLayout("e-f128:128:128-n64"), + FrameLowering(Subtarget), + Subtarget(TT, CPU, FS), + TLInfo(*this), + TSInfo(*this) { +} + +//===----------------------------------------------------------------------===// +// Pass Pipeline Configuration +//===----------------------------------------------------------------------===// + +bool AlphaTargetMachine::addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + PM.add(createAlphaISelDag(*this)); + return false; +} +bool AlphaTargetMachine::addPreEmitPass(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // Must run branch selection immediately preceding the asm printer + PM.add(createAlphaBranchSelectionPass()); + PM.add(createAlphaLLRPPass(*this)); + return false; +} diff --git a/contrib/llvm/lib/Target/Alpha/AlphaTargetMachine.h b/contrib/llvm/lib/Target/Alpha/AlphaTargetMachine.h new file mode 100644 index 0000000..48bb948 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/AlphaTargetMachine.h @@ -0,0 +1,66 @@ +//===-- AlphaTargetMachine.h - Define TargetMachine for Alpha ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 "AlphaInstrInfo.h" +#include "AlphaISelLowering.h" +#include "AlphaFrameLowering.h" +#include "AlphaSelectionDAGInfo.h" +#include "AlphaSubtarget.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { + +class GlobalValue; + +class AlphaTargetMachine : public LLVMTargetMachine { + const TargetData DataLayout; // Calculates type size & alignment + AlphaInstrInfo InstrInfo; + AlphaFrameLowering FrameLowering; + AlphaSubtarget Subtarget; + AlphaTargetLowering TLInfo; + AlphaSelectionDAGInfo TSInfo; + +public: + AlphaTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM); + + virtual const AlphaInstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const TargetFrameLowering *getFrameLowering() const { + return &FrameLowering; + } + virtual const AlphaSubtarget *getSubtargetImpl() const{ return &Subtarget; } + virtual const AlphaRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + virtual const AlphaTargetLowering* getTargetLowering() const { + return &TLInfo; + } + virtual const AlphaSelectionDAGInfo* getSelectionDAGInfo() const { + return &TSInfo; + } + virtual const TargetData *getTargetData() const { return &DataLayout; } + + // Pass Pipeline Configuration + virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.cpp b/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.cpp new file mode 100644 index 0000000..a35e884 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.cpp @@ -0,0 +1,23 @@ +//===-- AlphaMCAsmInfo.cpp - Alpha asm properties ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the AlphaMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "AlphaMCAsmInfo.h" +using namespace llvm; + +AlphaMCAsmInfo::AlphaMCAsmInfo(const Target &T, StringRef TT) { + AlignmentIsInBytes = false; + PrivateGlobalPrefix = "$"; + GPRel32Directive = ".gprel32"; + WeakRefDirective = "\t.weak\t"; + HasSetDirective = false; +} diff --git a/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.h b/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.h new file mode 100644 index 0000000..837844b --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCAsmInfo.h @@ -0,0 +1,29 @@ +//=====-- AlphaMCAsmInfo.h - Alpha asm properties -------------*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the AlphaMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHATARGETASMINFO_H +#define ALPHATARGETASMINFO_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class Target; + + struct AlphaMCAsmInfo : public MCAsmInfo { + explicit AlphaMCAsmInfo(const Target &T, StringRef TT); + }; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp b/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp new file mode 100644 index 0000000..4ad021c --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp @@ -0,0 +1,78 @@ +//===-- AlphaMCTargetDesc.cpp - Alpha Target Descriptions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Alpha specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "AlphaMCTargetDesc.h" +#include "AlphaMCAsmInfo.h" +#include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "AlphaGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "AlphaGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "AlphaGenRegisterInfo.inc" + +using namespace llvm; + + +static MCInstrInfo *createAlphaMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitAlphaMCInstrInfo(X); + return X; +} + +static MCRegisterInfo *createAlphaMCRegisterInfo(StringRef TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitAlphaMCRegisterInfo(X, Alpha::R26); + return X; +} + +static MCSubtargetInfo *createAlphaMCSubtargetInfo(StringRef TT, StringRef CPU, + StringRef FS) { + MCSubtargetInfo *X = new MCSubtargetInfo(); + InitAlphaMCSubtargetInfo(X, TT, CPU, FS); + return X; +} + +static MCCodeGenInfo *createAlphaMCCodeGenInfo(StringRef TT, Reloc::Model RM, + CodeModel::Model CM) { + MCCodeGenInfo *X = new MCCodeGenInfo(); + X->InitMCCodeGenInfo(Reloc::PIC_, CM); + return X; +} + +// Force static initialization. +extern "C" void LLVMInitializeAlphaTargetMC() { + // Register the MC asm info. + RegisterMCAsmInfo<AlphaMCAsmInfo> X(TheAlphaTarget); + + // Register the MC codegen info. + TargetRegistry::RegisterMCCodeGenInfo(TheAlphaTarget, + createAlphaMCCodeGenInfo); + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(TheAlphaTarget, createAlphaMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(TheAlphaTarget, createAlphaMCRegisterInfo); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(TheAlphaTarget, + createAlphaMCSubtargetInfo); +} diff --git a/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.h b/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.h new file mode 100644 index 0000000..b0619e6 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/MCTargetDesc/AlphaMCTargetDesc.h @@ -0,0 +1,40 @@ +//===-- AlphaMCTargetDesc.h - Alpha Target Descriptions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Alpha specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef ALPHAMCTARGETDESC_H +#define ALPHAMCTARGETDESC_H + +namespace llvm { +class MCSubtargetInfo; +class Target; +class StringRef; + +extern Target TheAlphaTarget; + +} // End llvm namespace + +// Defines symbolic names for Alpha registers. This defines a mapping from +// register name to register number. +// +#define GET_REGINFO_ENUM +#include "AlphaGenRegisterInfo.inc" + +// Defines symbolic names for the Alpha instructions. +// +#define GET_INSTRINFO_ENUM +#include "AlphaGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "AlphaGenSubtargetInfo.inc" + +#endif diff --git a/contrib/llvm/lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp b/contrib/llvm/lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp new file mode 100644 index 0000000..bdc69e7 --- /dev/null +++ b/contrib/llvm/lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp @@ -0,0 +1,20 @@ +//===-- AlphaTargetInfo.cpp - Alpha Target Implementation -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Alpha.h" +#include "llvm/Module.h" +#include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +llvm::Target llvm::TheAlphaTarget; + +extern "C" void LLVMInitializeAlphaTargetInfo() { + RegisterTarget<Triple::alpha, /*HasJIT=*/true> + X(TheAlphaTarget, "alpha", "Alpha [experimental]"); +} |