From c6aaf5acf9f9638f2dce6c21bfc3f4889048caa3 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 5 Feb 2006 06:33:29 +0000 Subject: [PATCH] Remove the SparcV8 backend. It has been renamed to be the Sparc backend. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25992 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SparcV8/DelaySlotFiller.cpp | 73 -- lib/Target/SparcV8/FPMover.cpp | 132 --- lib/Target/SparcV8/Makefile | 20 - lib/Target/SparcV8/README.txt | 58 - lib/Target/SparcV8/SparcV8.h | 119 -- lib/Target/SparcV8/SparcV8.td | 86 -- lib/Target/SparcV8/SparcV8AsmPrinter.cpp | 295 ----- lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp | 1147 ------------------- lib/Target/SparcV8/SparcV8InstrFormats.td | 111 -- lib/Target/SparcV8/SparcV8InstrInfo.cpp | 98 -- lib/Target/SparcV8/SparcV8InstrInfo.h | 68 -- lib/Target/SparcV8/SparcV8InstrInfo.td | 845 -------------- lib/Target/SparcV8/SparcV8RegisterInfo.cpp | 203 ---- lib/Target/SparcV8/SparcV8RegisterInfo.h | 63 - lib/Target/SparcV8/SparcV8RegisterInfo.td | 118 -- lib/Target/SparcV8/SparcV8Subtarget.cpp | 43 - lib/Target/SparcV8/SparcV8Subtarget.h | 42 - lib/Target/SparcV8/SparcV8TargetMachine.cpp | 115 -- lib/Target/SparcV8/SparcV8TargetMachine.h | 51 - 19 files changed, 3687 deletions(-) delete mode 100644 lib/Target/SparcV8/DelaySlotFiller.cpp delete mode 100644 lib/Target/SparcV8/FPMover.cpp delete mode 100644 lib/Target/SparcV8/Makefile delete mode 100644 lib/Target/SparcV8/README.txt delete mode 100644 lib/Target/SparcV8/SparcV8.h delete mode 100644 lib/Target/SparcV8/SparcV8.td delete mode 100644 lib/Target/SparcV8/SparcV8AsmPrinter.cpp delete mode 100644 lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp delete mode 100644 lib/Target/SparcV8/SparcV8InstrFormats.td delete mode 100644 lib/Target/SparcV8/SparcV8InstrInfo.cpp delete mode 100644 lib/Target/SparcV8/SparcV8InstrInfo.h delete mode 100644 lib/Target/SparcV8/SparcV8InstrInfo.td delete mode 100644 lib/Target/SparcV8/SparcV8RegisterInfo.cpp delete mode 100644 lib/Target/SparcV8/SparcV8RegisterInfo.h delete mode 100644 lib/Target/SparcV8/SparcV8RegisterInfo.td delete mode 100644 lib/Target/SparcV8/SparcV8Subtarget.cpp delete mode 100644 lib/Target/SparcV8/SparcV8Subtarget.h delete mode 100644 lib/Target/SparcV8/SparcV8TargetMachine.cpp delete mode 100644 lib/Target/SparcV8/SparcV8TargetMachine.h diff --git a/lib/Target/SparcV8/DelaySlotFiller.cpp b/lib/Target/SparcV8/DelaySlotFiller.cpp deleted file mode 100644 index 71dc022b9fd..00000000000 --- a/lib/Target/SparcV8/DelaySlotFiller.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//===-- DelaySlotFiller.cpp - SparcV8 delay slot filler -------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a simple local pass that fills delay slots with NOPs. -// -//===----------------------------------------------------------------------===// - -#include "SparcV8.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/ADT/Statistic.h" - -using namespace llvm; - -namespace { - Statistic<> FilledSlots ("delayslotfiller", "Num. of delay slots filled"); - - struct Filler : public MachineFunctionPass { - /// Target machine description which we query for reg. names, data - /// layout, etc. - /// - TargetMachine &TM; - const TargetInstrInfo *TII; - - Filler (TargetMachine &tm) : TM (tm), TII (tm.getInstrInfo ()) { } - - virtual const char *getPassName () const { - return "SparcV8 Delay Slot Filler"; - } - - bool runOnMachineBasicBlock (MachineBasicBlock &MBB); - bool runOnMachineFunction (MachineFunction &F) { - bool Changed = false; - for (MachineFunction::iterator FI = F.begin (), FE = F.end (); - FI != FE; ++FI) - Changed |= runOnMachineBasicBlock (*FI); - return Changed; - } - - }; -} // end of anonymous namespace - -/// createSparcV8DelaySlotFillerPass - Returns a pass that fills in delay -/// slots in SparcV8 MachineFunctions -/// -FunctionPass *llvm::createSparcV8DelaySlotFillerPass (TargetMachine &tm) { - return new Filler (tm); -} - -/// runOnMachineBasicBlock - Fill in delay slots for the given basic block. -/// Currently, we fill delay slots with NOPs. We assume there is only one -/// delay slot per delayed instruction. -/// -bool Filler::runOnMachineBasicBlock (MachineBasicBlock &MBB) { - bool Changed = false; - for (MachineBasicBlock::iterator I = MBB.begin (); I != MBB.end (); ++I) - if (TII->hasDelaySlot (I->getOpcode ())) { - MachineBasicBlock::iterator J = I; - ++J; - BuildMI (MBB, J, V8::NOP, 0); - ++FilledSlots; - Changed = true; - } - return Changed; -} diff --git a/lib/Target/SparcV8/FPMover.cpp b/lib/Target/SparcV8/FPMover.cpp deleted file mode 100644 index 8bc1009d37b..00000000000 --- a/lib/Target/SparcV8/FPMover.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//===-- FPMover.cpp - SparcV8 double-precision floating point move fixer --===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Expand FpMOVD/FpABSD/FpNEGD instructions into their single-precision pieces. -// -//===----------------------------------------------------------------------===// - -#include "SparcV8.h" -#include "SparcV8Subtarget.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Support/Debug.h" -#include -using namespace llvm; - -namespace { - Statistic<> NumFpDs("fpmover", "Number of instructions translated"); - Statistic<> NoopFpDs("fpmover", "Number of noop instructions removed"); - - struct FPMover : public MachineFunctionPass { - /// Target machine description which we query for reg. names, data - /// layout, etc. - /// - TargetMachine &TM; - - FPMover(TargetMachine &tm) : TM(tm) { } - - virtual const char *getPassName() const { - return "SparcV8 Double-FP Move Fixer"; - } - - bool runOnMachineBasicBlock(MachineBasicBlock &MBB); - bool runOnMachineFunction(MachineFunction &F); - }; -} // end of anonymous namespace - -/// createSparcV8FPMoverPass - Returns a pass that turns FpMOVD -/// instructions into FMOVS instructions -/// -FunctionPass *llvm::createSparcV8FPMoverPass(TargetMachine &tm) { - return new FPMover(tm); -} - -/// getDoubleRegPair - Given a DFP register, return the even and odd FP -/// registers that correspond to it. -static void getDoubleRegPair(unsigned DoubleReg, unsigned &EvenReg, - unsigned &OddReg) { - static const unsigned EvenHalvesOfPairs[] = { - V8::F0, V8::F2, V8::F4, V8::F6, V8::F8, V8::F10, V8::F12, V8::F14, - V8::F16, V8::F18, V8::F20, V8::F22, V8::F24, V8::F26, V8::F28, V8::F30 - }; - static const unsigned OddHalvesOfPairs[] = { - V8::F1, V8::F3, V8::F5, V8::F7, V8::F9, V8::F11, V8::F13, V8::F15, - V8::F17, V8::F19, V8::F21, V8::F23, V8::F25, V8::F27, V8::F29, V8::F31 - }; - static const unsigned DoubleRegsInOrder[] = { - V8::D0, V8::D1, V8::D2, V8::D3, V8::D4, V8::D5, V8::D6, V8::D7, V8::D8, - V8::D9, V8::D10, V8::D11, V8::D12, V8::D13, V8::D14, V8::D15 - }; - for (unsigned i = 0; i < sizeof(DoubleRegsInOrder)/sizeof(unsigned); ++i) - if (DoubleRegsInOrder[i] == DoubleReg) { - EvenReg = EvenHalvesOfPairs[i]; - OddReg = OddHalvesOfPairs[i]; - return; - } - assert(0 && "Can't find reg"); -} - -/// runOnMachineBasicBlock - Fixup FpMOVD instructions in this MBB. -/// -bool FPMover::runOnMachineBasicBlock(MachineBasicBlock &MBB) { - bool Changed = false; - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { - MachineInstr *MI = I++; - if (MI->getOpcode() == V8::FpMOVD || MI->getOpcode() == V8::FpABSD || - MI->getOpcode() == V8::FpNEGD) { - Changed = true; - unsigned DestDReg = MI->getOperand(0).getReg(); - unsigned SrcDReg = MI->getOperand(1).getReg(); - if (DestDReg == SrcDReg && MI->getOpcode() == V8::FpMOVD) { - MBB.erase(MI); // Eliminate the noop copy. - ++NoopFpDs; - continue; - } - - unsigned EvenSrcReg = 0, OddSrcReg = 0, EvenDestReg = 0, OddDestReg = 0; - getDoubleRegPair(DestDReg, EvenDestReg, OddDestReg); - getDoubleRegPair(SrcDReg, EvenSrcReg, OddSrcReg); - - if (MI->getOpcode() == V8::FpMOVD) - MI->setOpcode(V8::FMOVS); - else if (MI->getOpcode() == V8::FpNEGD) - MI->setOpcode(V8::FNEGS); - else if (MI->getOpcode() == V8::FpABSD) - MI->setOpcode(V8::FABSS); - else - assert(0 && "Unknown opcode!"); - - MI->SetMachineOperandReg(0, EvenDestReg); - MI->SetMachineOperandReg(1, EvenSrcReg); - DEBUG(std::cerr << "FPMover: the modified instr is: " << *MI); - // Insert copy for the other half of the double. - if (DestDReg != SrcDReg) { - MI = BuildMI(MBB, I, V8::FMOVS, 1, OddDestReg).addReg(OddSrcReg); - DEBUG(std::cerr << "FPMover: the inserted instr is: " << *MI); - } - ++NumFpDs; - } - } - return Changed; -} - -bool FPMover::runOnMachineFunction(MachineFunction &F) { - // If the target has V9 instructions, the fp-mover pseudos will never be - // emitted. Avoid a scan of the instructions to improve compile time. - if (TM.getSubtarget().isV9()) - return false; - - bool Changed = false; - for (MachineFunction::iterator FI = F.begin(), FE = F.end(); - FI != FE; ++FI) - Changed |= runOnMachineBasicBlock(*FI); - return Changed; -} diff --git a/lib/Target/SparcV8/Makefile b/lib/Target/SparcV8/Makefile deleted file mode 100644 index 7d61984048e..00000000000 --- a/lib/Target/SparcV8/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -##===- lib/Target/SparcV8/Makefile -------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file was developed by the LLVM research group and is distributed under -# the University of Illinois Open Source License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../.. -LIBRARYNAME = LLVMSparcV8 -TARGET = SparcV8 - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = SparcV8GenRegisterInfo.h.inc SparcV8GenRegisterNames.inc \ - SparcV8GenRegisterInfo.inc SparcV8GenInstrNames.inc \ - SparcV8GenInstrInfo.inc SparcV8GenAsmWriter.inc \ - SparcV8GenDAGISel.inc SparcV8GenSubtarget.inc - -include $(LEVEL)/Makefile.common - diff --git a/lib/Target/SparcV8/README.txt b/lib/Target/SparcV8/README.txt deleted file mode 100644 index 352f842c21f..00000000000 --- a/lib/Target/SparcV8/README.txt +++ /dev/null @@ -1,58 +0,0 @@ - -To-do ------ - -* Enable LSR for V8. -* Keep the address of the constant pool in a register instead of forming its - address all of the time. -* We can fold small constant offsets into the %hi/%lo references to constant - pool addresses as well. -* When in V9 mode, register allocate %icc[0-3]. -* Emit the 'Branch on Integer Register with Prediction' instructions. It's - not clear how to write a pattern for this though: - -float %t1(int %a, int* %p) { - %C = seteq int %a, 0 - br bool %C, label %T, label %F -T: - store int 123, int* %p - br label %F -F: - ret float undef -} - -codegens to this: - -t1: - save -96, %o6, %o6 -1) subcc %i0, 0, %l0 -1) bne .LBBt1_2 ! F - nop -.LBBt1_1: ! T - or %g0, 123, %l0 - st %l0, [%i1] -.LBBt1_2: ! F - restore %g0, %g0, %g0 - retl - nop - -1) should be replaced with a brz in V9 mode. - -* Same as above, but emit conditional move on register zero (p192) in V9 - mode. Testcase: - -int %t1(int %a, int %b) { - %C = seteq int %a, 0 - %D = select bool %C, int %a, int %b - ret int %D -} - -* Emit MULX/[SU]DIVX instructions in V9 mode instead of fiddling - with the Y register, if they are faster. - -* Codegen bswap(load)/store(bswap) -> load/store ASI - -* Implement frame pointer elimination, e.g. eliminate save/restore for - leaf fns. -* Fill delay slots - diff --git a/lib/Target/SparcV8/SparcV8.h b/lib/Target/SparcV8/SparcV8.h deleted file mode 100644 index faf160b16cd..00000000000 --- a/lib/Target/SparcV8/SparcV8.h +++ /dev/null @@ -1,119 +0,0 @@ -//===-- SparcV8.h - Top-level interface for SparcV8 representation -*- C++ -*-// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the entry points for global functions defined in the LLVM -// SparcV8 back-end. -// -//===----------------------------------------------------------------------===// - -#ifndef TARGET_SPARCV8_H -#define TARGET_SPARCV8_H - -#include -#include - -namespace llvm { - - class FunctionPass; - class TargetMachine; - - FunctionPass *createSparcV8ISelDag(TargetMachine &TM); - - FunctionPass *createSparcV8CodePrinterPass(std::ostream &OS, - TargetMachine &TM); - FunctionPass *createSparcV8DelaySlotFillerPass(TargetMachine &TM); - FunctionPass *createSparcV8FPMoverPass(TargetMachine &TM); -} // end namespace llvm; - -// Defines symbolic names for SparcV8 registers. This defines a mapping from -// register name to register number. -// -#include "SparcV8GenRegisterNames.inc" - -// Defines symbolic names for the SparcV8 instructions. -// -#include "SparcV8GenInstrNames.inc" - - -namespace llvm { - // Enums corresponding to SparcV8 condition codes, both icc's and fcc's. These - // values must be kept in sync with the ones in the .td file. - namespace V8CC { - enum CondCodes { - //ICC_A = 8 , // Always - //ICC_N = 0 , // Never - ICC_NE = 9 , // Not Equal - ICC_E = 1 , // Equal - ICC_G = 10 , // Greater - ICC_LE = 2 , // Less or Equal - ICC_GE = 11 , // Greater or Equal - ICC_L = 3 , // Less - ICC_GU = 12 , // Greater Unsigned - ICC_LEU = 4 , // Less or Equal Unsigned - ICC_CC = 13 , // Carry Clear/Great or Equal Unsigned - ICC_CS = 5 , // Carry Set/Less Unsigned - ICC_POS = 14 , // Positive - ICC_NEG = 6 , // Negative - ICC_VC = 15 , // Overflow Clear - ICC_VS = 7 , // Overflow Set - - //FCC_A = 8+16, // Always - //FCC_N = 0+16, // Never - FCC_U = 7+16, // Unordered - FCC_G = 6+16, // Greater - FCC_UG = 5+16, // Unordered or Greater - FCC_L = 4+16, // Less - FCC_UL = 3+16, // Unordered or Less - FCC_LG = 2+16, // Less or Greater - FCC_NE = 1+16, // Not Equal - FCC_E = 9+16, // Equal - FCC_UE = 10+16, // Unordered or Equal - FCC_GE = 11+16, // Greater or Equal - FCC_UGE = 12+16, // Unordered or Greater or Equal - FCC_LE = 13+16, // Less or Equal - FCC_ULE = 14+16, // Unordered or Less or Equal - FCC_O = 15+16, // Ordered - }; - } - - static const char *SPARCCondCodeToString(V8CC::CondCodes CC) { - switch (CC) { - default: assert(0 && "Unknown condition code"); - case V8CC::ICC_NE: return "ne"; - case V8CC::ICC_E: return "e"; - case V8CC::ICC_G: return "g"; - case V8CC::ICC_LE: return "le"; - case V8CC::ICC_GE: return "ge"; - case V8CC::ICC_L: return "l"; - case V8CC::ICC_GU: return "gu"; - case V8CC::ICC_LEU: return "leu"; - case V8CC::ICC_CC: return "cc"; - case V8CC::ICC_CS: return "cs"; - case V8CC::ICC_POS: return "pos"; - case V8CC::ICC_NEG: return "neg"; - case V8CC::ICC_VC: return "vc"; - case V8CC::ICC_VS: return "vs"; - case V8CC::FCC_U: return "u"; - case V8CC::FCC_G: return "g"; - case V8CC::FCC_UG: return "ug"; - case V8CC::FCC_L: return "l"; - case V8CC::FCC_UL: return "ul"; - case V8CC::FCC_LG: return "lg"; - case V8CC::FCC_NE: return "ne"; - case V8CC::FCC_E: return "e"; - case V8CC::FCC_UE: return "ue"; - case V8CC::FCC_GE: return "ge"; - case V8CC::FCC_UGE: return "uge"; - case V8CC::FCC_LE: return "le"; - case V8CC::FCC_ULE: return "ule"; - case V8CC::FCC_O: return "o"; - } - } -} // end namespace llvm -#endif diff --git a/lib/Target/SparcV8/SparcV8.td b/lib/Target/SparcV8/SparcV8.td deleted file mode 100644 index b123930157d..00000000000 --- a/lib/Target/SparcV8/SparcV8.td +++ /dev/null @@ -1,86 +0,0 @@ -//===- SparcV8.td - Describe the SparcV8 Target Machine ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Target-independent interfaces which we are implementing -//===----------------------------------------------------------------------===// - -include "../Target.td" - -//===----------------------------------------------------------------------===// -// SPARC Subtarget features. -// - -def FeatureV9 - : SubtargetFeature<"v9", "IsV9", "true", - "Enable SPARC-V9 instructions">; -def FeatureV8Deprecated - : SubtargetFeature<"deprecated-v8", "V8DeprecatedInsts", "true", - "Enable deprecated V8 instructions in V9 mode">; -def FeatureVIS - : SubtargetFeature<"vis", "IsVIS", "true", - "Enable UltraSPARC Visual Instruction Set extensions">; - -//===----------------------------------------------------------------------===// -// Register File Description -//===----------------------------------------------------------------------===// - -include "SparcV8RegisterInfo.td" - -//===----------------------------------------------------------------------===// -// Instruction Descriptions -//===----------------------------------------------------------------------===// - -include "SparcV8InstrInfo.td" - -def SparcV8InstrInfo : InstrInfo { - // Define how we want to layout our target-specific information field. - let TSFlagsFields = []; - let TSFlagsShifts = []; -} - -//===----------------------------------------------------------------------===// -// SPARC processors supported. -//===----------------------------------------------------------------------===// - -class Proc Features> - : Processor; - -def : Proc<"generic", []>; -def : Proc<"v8", []>; -def : Proc<"supersparc", []>; -def : Proc<"sparclite", []>; -def : Proc<"f934", []>; -def : Proc<"hypersparc", []>; -def : Proc<"sparclite86x", []>; -def : Proc<"sparclet", []>; -def : Proc<"tsc701", []>; -def : Proc<"v9", [FeatureV9]>; -def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated]>; -def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>; -def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>; - - -//===----------------------------------------------------------------------===// -// Declare the target which we are implementing -//===----------------------------------------------------------------------===// - -def SparcV8 : Target { - // Pointers are 32-bits in size. - let PointerType = i32; - - // FIXME: Specify callee-saved registers - let CalleeSavedRegisters = []; - - // Pull in Instruction Info: - let InstructionSet = SparcV8InstrInfo; -} diff --git a/lib/Target/SparcV8/SparcV8AsmPrinter.cpp b/lib/Target/SparcV8/SparcV8AsmPrinter.cpp deleted file mode 100644 index dd1b46904d8..00000000000 --- a/lib/Target/SparcV8/SparcV8AsmPrinter.cpp +++ /dev/null @@ -1,295 +0,0 @@ -//===-- SparcV8AsmPrinter.cpp - SparcV8 LLVM assembly writer --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a printer that converts from our internal representation -// of machine-dependent LLVM code to GAS-format Sparc V8 assembly language. -// -//===----------------------------------------------------------------------===// - -#include "SparcV8.h" -#include "SparcV8InstrInfo.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Support/Mangler.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/MathExtras.h" -#include -#include -using namespace llvm; - -namespace { - Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); - - struct SparcV8AsmPrinter : public AsmPrinter { - SparcV8AsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) { - Data16bitsDirective = "\t.half\t"; - Data32bitsDirective = "\t.word\t"; - Data64bitsDirective = 0; // .xword is only supported by V9. - ZeroDirective = 0; // no .zero or .space! - CommentString = "!"; - ConstantPoolSection = "\t.section \".rodata\",#alloc\n"; - } - - /// We name each basic block in a Function with a unique number, so - /// that we can consistently refer to them later. This is cleared - /// at the beginning of each call to runOnMachineFunction(). - /// - typedef std::map ValueMapTy; - ValueMapTy NumberForBB; - - virtual const char *getPassName() const { - return "SparcV8 Assembly Printer"; - } - - void printOperand(const MachineInstr *MI, int opNum); - void printMemOperand(const MachineInstr *MI, int opNum); - void printV8CCOperand(const MachineInstr *MI, int opNum); - - bool printInstruction(const MachineInstr *MI); // autogenerated. - bool runOnMachineFunction(MachineFunction &F); - bool doInitialization(Module &M); - bool doFinalization(Module &M); - }; -} // end of anonymous namespace - -#include "SparcV8GenAsmWriter.inc" - -/// createSparcV8CodePrinterPass - Returns a pass that prints the SparcV8 -/// assembly code for a MachineFunction to the given output stream, -/// using the given target machine description. This should work -/// regardless of whether the function is in SSA form. -/// -FunctionPass *llvm::createSparcV8CodePrinterPass (std::ostream &o, - TargetMachine &tm) { - return new SparcV8AsmPrinter(o, tm); -} - -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool SparcV8AsmPrinter::runOnMachineFunction(MachineFunction &MF) { - SetupMachineFunction(MF); - - // Print out constants referenced by the function - EmitConstantPool(MF.getConstantPool()); - - // BBNumber is used here so that a given Printer will never give two - // BBs the same name. (If you have a better way, please let me know!) - static unsigned BBNumber = 0; - - O << "\n\n"; - // What's my mangled name? - CurrentFnName = Mang->getValueName(MF.getFunction()); - - // Print out labels for the function. - O << "\t.text\n"; - O << "\t.align 16\n"; - O << "\t.globl\t" << CurrentFnName << "\n"; - O << "\t.type\t" << CurrentFnName << ", #function\n"; - O << CurrentFnName << ":\n"; - - // Number each basic block so that we can consistently refer to them - // in PC-relative references. - NumberForBB.clear(); - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - NumberForBB[I->getBasicBlock()] = BBNumber++; - } - - // Print out code for the function. - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - // Print a label for the basic block. - if (I != MF.begin()) - O << ".LBB" << Mang->getValueName(MF.getFunction ()) - << "_" << I->getNumber () << ":\t! " - << I->getBasicBlock ()->getName () << "\n"; - for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); - II != E; ++II) { - // Print the assembly for the instruction. - O << "\t"; - printInstruction(II); - ++EmittedInsts; - } - } - - // We didn't modify anything. - return false; -} - -void SparcV8AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { - const MachineOperand &MO = MI->getOperand (opNum); - const MRegisterInfo &RI = *TM.getRegisterInfo(); - bool CloseParen = false; - if (MI->getOpcode() == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) { - O << "%hi("; - CloseParen = true; - } else if ((MI->getOpcode() == V8::ORri || MI->getOpcode() == V8::ADDri) - && !MO.isRegister() && !MO.isImmediate()) { - O << "%lo("; - CloseParen = true; - } - switch (MO.getType()) { - case MachineOperand::MO_VirtualRegister: - if (Value *V = MO.getVRegValueOrNull()) { - O << "<" << V->getName() << ">"; - break; - } - // FALLTHROUGH - case MachineOperand::MO_MachineRegister: - if (MRegisterInfo::isPhysicalRegister(MO.getReg())) - O << "%" << LowercaseString (RI.get(MO.getReg()).Name); - else - O << "%reg" << MO.getReg(); - break; - - case MachineOperand::MO_SignExtendedImmed: - case MachineOperand::MO_UnextendedImmed: - O << (int)MO.getImmedValue(); - break; - case MachineOperand::MO_MachineBasicBlock: { - MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); - O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) - << "_" << MBBOp->getNumber () << "\t! " - << MBBOp->getBasicBlock ()->getName (); - return; - } - case MachineOperand::MO_PCRelativeDisp: - std::cerr << "Shouldn't use addPCDisp() when building SparcV8 MachineInstrs"; - abort (); - return; - case MachineOperand::MO_GlobalAddress: - O << Mang->getValueName(MO.getGlobal()); - break; - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); - break; - case MachineOperand::MO_ConstantPoolIndex: - O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_" - << MO.getConstantPoolIndex(); - break; - default: - O << ""; abort (); break; - } - if (CloseParen) O << ")"; -} - -void SparcV8AsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) { - printOperand(MI, opNum); - MachineOperand::MachineOperandType OpTy = MI->getOperand(opNum+1).getType(); - - if ((OpTy == MachineOperand::MO_VirtualRegister || - OpTy == MachineOperand::MO_MachineRegister) && - MI->getOperand(opNum+1).getReg() == V8::G0) - return; // don't print "+%g0" - if ((OpTy == MachineOperand::MO_SignExtendedImmed || - OpTy == MachineOperand::MO_UnextendedImmed) && - MI->getOperand(opNum+1).getImmedValue() == 0) - return; // don't print "+0" - - O << "+"; - if (OpTy == MachineOperand::MO_GlobalAddress || - OpTy == MachineOperand::MO_ConstantPoolIndex) { - O << "%lo("; - printOperand(MI, opNum+1); - O << ")"; - } else { - printOperand(MI, opNum+1); - } -} - -void SparcV8AsmPrinter::printV8CCOperand(const MachineInstr *MI, int opNum) { - int CC = (int)MI->getOperand(opNum).getImmedValue(); - O << SPARCCondCodeToString((V8CC::CondCodes)CC); -} - - - -bool SparcV8AsmPrinter::doInitialization(Module &M) { - Mang = new Mangler(M); - return false; // success -} - -bool SparcV8AsmPrinter::doFinalization(Module &M) { - const TargetData &TD = TM.getTargetData(); - - // Print out module-level global variables here. - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (I->hasInitializer()) { // External global require no code - O << "\n\n"; - std::string name = Mang->getValueName(I); - Constant *C = I->getInitializer(); - unsigned Size = TD.getTypeSize(C->getType()); - unsigned Align = TD.getTypeAlignment(C->getType()); - - if (C->isNullValue() && - (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || - I->hasWeakLinkage() /* FIXME: Verify correct */)) { - SwitchSection(".data", I); - if (I->hasInternalLinkage()) - O << "\t.local " << name << "\n"; - - O << "\t.comm " << name << "," << TD.getTypeSize(C->getType()) - << "," << (unsigned)TD.getTypeAlignment(C->getType()); - O << "\t\t! "; - WriteAsOperand(O, I, true, true, &M); - O << "\n"; - } else { - switch (I->getLinkage()) { - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. - // Nonnull linkonce -> weak - O << "\t.weak " << name << "\n"; - SwitchSection("", I); - O << "\t.section\t\".llvm.linkonce.d." << name - << "\",\"aw\",@progbits\n"; - break; - - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.globl " << name << "\n"; - // FALL THROUGH - case GlobalValue::InternalLinkage: - if (C->isNullValue()) - SwitchSection(".bss", I); - else - SwitchSection(".data", I); - break; - case GlobalValue::GhostLinkage: - std::cerr << "Should not have any unmaterialized functions!\n"; - abort(); - } - - O << "\t.align " << Align << "\n"; - O << "\t.type " << name << ",#object\n"; - O << "\t.size " << name << "," << Size << "\n"; - O << name << ":\t\t\t\t! "; - WriteAsOperand(O, I, true, true, &M); - O << " = "; - WriteAsOperand(O, C, false, false, &M); - O << "\n"; - EmitGlobalConstant(C); - } - } - - AsmPrinter::doFinalization(M); - return false; // success -} diff --git a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp deleted file mode 100644 index bd5073d8972..00000000000 --- a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp +++ /dev/null @@ -1,1147 +0,0 @@ -//===-- SparcV8ISelDAGToDAG.cpp - A dag to dag inst selector for SparcV8 --===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an instruction selector for the V8 target -// -//===----------------------------------------------------------------------===// - -#include "SparcV8.h" -#include "SparcV8TargetMachine.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Function.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGISel.h" -#include "llvm/CodeGen/SSARegMap.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Support/Debug.h" -#include -using namespace llvm; - -//===----------------------------------------------------------------------===// -// TargetLowering Implementation -//===----------------------------------------------------------------------===// - -namespace V8ISD { - enum { - FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END, - CMPICC, // Compare two GPR operands, set icc. - CMPFCC, // Compare two FP operands, set fcc. - BRICC, // Branch to dest on icc condition - BRFCC, // Branch to dest on fcc condition - SELECT_ICC, // Select between two values using the current ICC flags. - SELECT_FCC, // Select between two values using the current FCC flags. - - Hi, Lo, // Hi/Lo operations, typically on a global address. - - FTOI, // FP to Int within a FP register. - ITOF, // Int to FP within a FP register. - - CALL, // A V8 call instruction. - RET_FLAG, // Return with a flag operand. - }; -} - -/// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC -/// condition. -static V8CC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) { - switch (CC) { - default: assert(0 && "Unknown integer condition code!"); - case ISD::SETEQ: return V8CC::ICC_E; - case ISD::SETNE: return V8CC::ICC_NE; - case ISD::SETLT: return V8CC::ICC_L; - case ISD::SETGT: return V8CC::ICC_G; - case ISD::SETLE: return V8CC::ICC_LE; - case ISD::SETGE: return V8CC::ICC_GE; - case ISD::SETULT: return V8CC::ICC_CS; - case ISD::SETULE: return V8CC::ICC_LEU; - case ISD::SETUGT: return V8CC::ICC_GU; - case ISD::SETUGE: return V8CC::ICC_CC; - } -} - -/// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC -/// FCC condition. -static V8CC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { - switch (CC) { - default: assert(0 && "Unknown fp condition code!"); - case ISD::SETEQ: return V8CC::FCC_E; - case ISD::SETNE: return V8CC::FCC_NE; - case ISD::SETLT: return V8CC::FCC_L; - case ISD::SETGT: return V8CC::FCC_G; - case ISD::SETLE: return V8CC::FCC_LE; - case ISD::SETGE: return V8CC::FCC_GE; - case ISD::SETULT: return V8CC::FCC_UL; - case ISD::SETULE: return V8CC::FCC_ULE; - case ISD::SETUGT: return V8CC::FCC_UG; - case ISD::SETUGE: return V8CC::FCC_UGE; - case ISD::SETUO: return V8CC::FCC_U; - case ISD::SETO: return V8CC::FCC_O; - case ISD::SETONE: return V8CC::FCC_LG; - case ISD::SETUEQ: return V8CC::FCC_UE; - } -} - -namespace { - class SparcV8TargetLowering : public TargetLowering { - int VarArgsFrameOffset; // Frame offset to start of varargs area. - public: - SparcV8TargetLowering(TargetMachine &TM); - virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); - - /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to - /// be zero. Op is expected to be a target specific node. Used by DAG - /// combiner. - virtual bool isMaskedValueZeroForTargetNode(const SDOperand &Op, - uint64_t Mask) const; - - virtual std::vector - LowerArguments(Function &F, SelectionDAG &DAG); - virtual std::pair - LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, - unsigned CC, - bool isTailCall, SDOperand Callee, ArgListTy &Args, - SelectionDAG &DAG); - virtual std::pair - LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, - SelectionDAG &DAG); - virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI, - MachineBasicBlock *MBB); - - virtual const char *getTargetNodeName(unsigned Opcode) const; - }; -} - -SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) - : TargetLowering(TM) { - - // Set up the register classes. - addRegisterClass(MVT::i32, V8::IntRegsRegisterClass); - addRegisterClass(MVT::f32, V8::FPRegsRegisterClass); - addRegisterClass(MVT::f64, V8::DFPRegsRegisterClass); - - // Custom legalize GlobalAddress nodes into LO/HI parts. - setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); - setOperationAction(ISD::ConstantPool , MVT::i32, Custom); - - // Sparc doesn't have sext_inreg, replace them with shl/sra - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); - - // Sparc has no REM operation. - setOperationAction(ISD::UREM, MVT::i32, Expand); - setOperationAction(ISD::SREM, MVT::i32, Expand); - - // Custom expand fp<->sint - setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); - setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); - - // Expand fp<->uint - setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); - setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); - - setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); - setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); - - // Turn FP extload into load/fextend - setOperationAction(ISD::EXTLOAD, MVT::f32, Expand); - - // Sparc has no select or setcc: expand to SELECT_CC. - setOperationAction(ISD::SELECT, MVT::i32, Expand); - setOperationAction(ISD::SELECT, MVT::f32, Expand); - setOperationAction(ISD::SELECT, MVT::f64, Expand); - setOperationAction(ISD::SETCC, MVT::i32, Expand); - setOperationAction(ISD::SETCC, MVT::f32, Expand); - setOperationAction(ISD::SETCC, MVT::f64, Expand); - - // Sparc doesn't have BRCOND either, it has BR_CC. - setOperationAction(ISD::BRCOND, MVT::Other, Expand); - setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); - setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); - setOperationAction(ISD::BR_CC, MVT::i32, Custom); - setOperationAction(ISD::BR_CC, MVT::f32, Custom); - setOperationAction(ISD::BR_CC, MVT::f64, Custom); - - setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); - setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); - - // V8 has no intrinsics for these particular operations. - setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); - setOperationAction(ISD::MEMSET, MVT::Other, Expand); - setOperationAction(ISD::MEMCPY, MVT::Other, Expand); - - 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::CTPOP, MVT::i32, Expand); - setOperationAction(ISD::CTTZ , MVT::i32, Expand); - setOperationAction(ISD::CTLZ , MVT::i32, Expand); - setOperationAction(ISD::ROTL , MVT::i32, Expand); - setOperationAction(ISD::ROTR , MVT::i32, Expand); - setOperationAction(ISD::BSWAP, MVT::i32, Expand); - - setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); - - // We don't have line number support yet. - setOperationAction(ISD::LOCATION, MVT::Other, Expand); - setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); - setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand); - - // RET must be custom lowered, to meet ABI requirements - setOperationAction(ISD::RET , MVT::Other, Custom); - - // VASTART needs to be custom lowered to use the VarArgsFrameIndex. - setOperationAction(ISD::VASTART , MVT::Other, Custom); - // VAARG needs to be lowered to not do unaligned accesses for doubles. - setOperationAction(ISD::VAARG , MVT::Other, Custom); - - // Use the default implementation. - setOperationAction(ISD::VACOPY , MVT::Other, Expand); - setOperationAction(ISD::VAEND , MVT::Other, Expand); - setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); - setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); - setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand); - - setOperationAction(ISD::ConstantFP, MVT::f64, Expand); - setOperationAction(ISD::ConstantFP, MVT::f32, Expand); - - setStackPointerRegisterToSaveRestore(V8::O6); - - if (TM.getSubtarget().isV9()) { - setOperationAction(ISD::CTPOP, MVT::i32, Legal); - } - - computeRegisterProperties(); -} - -const char *SparcV8TargetLowering::getTargetNodeName(unsigned Opcode) const { - switch (Opcode) { - default: return 0; - case V8ISD::CMPICC: return "V8ISD::CMPICC"; - case V8ISD::CMPFCC: return "V8ISD::CMPFCC"; - case V8ISD::BRICC: return "V8ISD::BRICC"; - case V8ISD::BRFCC: return "V8ISD::BRFCC"; - case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC"; - case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC"; - case V8ISD::Hi: return "V8ISD::Hi"; - case V8ISD::Lo: return "V8ISD::Lo"; - case V8ISD::FTOI: return "V8ISD::FTOI"; - case V8ISD::ITOF: return "V8ISD::ITOF"; - case V8ISD::CALL: return "V8ISD::CALL"; - case V8ISD::RET_FLAG: return "V8ISD::RET_FLAG"; - } -} - -/// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to -/// be zero. Op is expected to be a target specific node. Used by DAG -/// combiner. -bool SparcV8TargetLowering:: -isMaskedValueZeroForTargetNode(const SDOperand &Op, uint64_t Mask) const { - switch (Op.getOpcode()) { - default: return false; - case V8ISD::SELECT_ICC: - case V8ISD::SELECT_FCC: - assert(MVT::isInteger(Op.getValueType()) && "Not an integer select!"); - // These operations are masked zero if both the left and the right are zero. - return MaskedValueIsZero(Op.getOperand(0), Mask) && - MaskedValueIsZero(Op.getOperand(1), Mask); - } -} - - -/// LowerArguments - V8 uses a very simple ABI, where all values are passed in -/// either one or two GPRs, including FP values. TODO: we should pass FP values -/// in FP registers for fastcc functions. -std::vector -SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { - MachineFunction &MF = DAG.getMachineFunction(); - SSARegMap *RegMap = MF.getSSARegMap(); - std::vector ArgValues; - - static const unsigned ArgRegs[] = { - V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5 - }; - - const unsigned *CurArgReg = ArgRegs, *ArgRegEnd = ArgRegs+6; - unsigned ArgOffset = 68; - - SDOperand Root = DAG.getRoot(); - std::vector OutChains; - - for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { - MVT::ValueType ObjectVT = getValueType(I->getType()); - - switch (ObjectVT) { - default: assert(0 && "Unhandled argument type!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - if (I->use_empty()) { // Argument is dead. - if (CurArgReg < ArgRegEnd) ++CurArgReg; - ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT)); - } else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR - unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass); - MF.addLiveIn(*CurArgReg++, VReg); - SDOperand Arg = DAG.getCopyFromReg(Root, VReg, MVT::i32); - if (ObjectVT != MVT::i32) { - unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext - : ISD::AssertZext; - Arg = DAG.getNode(AssertOp, MVT::i32, Arg, - DAG.getValueType(ObjectVT)); - Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg); - } - ArgValues.push_back(Arg); - } else { - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); - SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - SDOperand Load; - if (ObjectVT == MVT::i32) { - Load = DAG.getLoad(MVT::i32, Root, FIPtr, DAG.getSrcValue(0)); - } else { - unsigned LoadOp = - I->getType()->isSigned() ? ISD::SEXTLOAD : ISD::ZEXTLOAD; - - // Sparc is big endian, so add an offset based on the ObjectVT. - unsigned Offset = 4-std::max(1U, MVT::getSizeInBits(ObjectVT)/8); - FIPtr = DAG.getNode(ISD::ADD, MVT::i32, FIPtr, - DAG.getConstant(Offset, MVT::i32)); - Load = DAG.getExtLoad(LoadOp, MVT::i32, Root, FIPtr, - DAG.getSrcValue(0), ObjectVT); - Load = DAG.getNode(ISD::TRUNCATE, ObjectVT, Load); - } - ArgValues.push_back(Load); - } - - ArgOffset += 4; - break; - case MVT::f32: - if (I->use_empty()) { // Argument is dead. - if (CurArgReg < ArgRegEnd) ++CurArgReg; - ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT)); - } else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR - // FP value is passed in an integer register. - unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass); - MF.addLiveIn(*CurArgReg++, VReg); - SDOperand Arg = DAG.getCopyFromReg(Root, VReg, MVT::i32); - - Arg = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Arg); - ArgValues.push_back(Arg); - } else { - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); - SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - SDOperand Load = DAG.getLoad(MVT::f32, Root, FIPtr, DAG.getSrcValue(0)); - ArgValues.push_back(Load); - } - ArgOffset += 4; - break; - - case MVT::i64: - case MVT::f64: - if (I->use_empty()) { // Argument is dead. - if (CurArgReg < ArgRegEnd) ++CurArgReg; - if (CurArgReg < ArgRegEnd) ++CurArgReg; - ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT)); - } else if (/* FIXME: Apparently this isn't safe?? */ - 0 && CurArgReg == ArgRegEnd && ObjectVT == MVT::f64 && - ((CurArgReg-ArgRegs) & 1) == 0) { - // If this is a double argument and the whole thing lives on the stack, - // and the argument is aligned, load the double straight from the stack. - // We can't do a load in cases like void foo([6ints], int,double), - // because the double wouldn't be aligned! - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(8, ArgOffset); - SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - ArgValues.push_back(DAG.getLoad(MVT::f64, Root, FIPtr, - DAG.getSrcValue(0))); - } else { - SDOperand HiVal; - if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR - unsigned VRegHi = RegMap->createVirtualRegister(&V8::IntRegsRegClass); - MF.addLiveIn(*CurArgReg++, VRegHi); - HiVal = DAG.getCopyFromReg(Root, VRegHi, MVT::i32); - } else { - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); - SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - HiVal = DAG.getLoad(MVT::i32, Root, FIPtr, DAG.getSrcValue(0)); - } - - SDOperand LoVal; - if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR - unsigned VRegLo = RegMap->createVirtualRegister(&V8::IntRegsRegClass); - MF.addLiveIn(*CurArgReg++, VRegLo); - LoVal = DAG.getCopyFromReg(Root, VRegLo, MVT::i32); - } else { - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4); - SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - LoVal = DAG.getLoad(MVT::i32, Root, FIPtr, DAG.getSrcValue(0)); - } - - // Compose the two halves together into an i64 unit. - SDOperand WholeValue = - DAG.getNode(ISD::BUILD_PAIR, MVT::i64, LoVal, HiVal); - - // If we want a double, do a bit convert. - if (ObjectVT == MVT::f64) - WholeValue = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, WholeValue); - - ArgValues.push_back(WholeValue); - } - ArgOffset += 8; - break; - } - } - - // Store remaining ArgRegs to the stack if this is a varargs function. - if (F.getFunctionType()->isVarArg()) { - // Remember the vararg offset for the va_start implementation. - VarArgsFrameOffset = ArgOffset; - - for (; CurArgReg != ArgRegEnd; ++CurArgReg) { - unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass); - MF.addLiveIn(*CurArgReg, VReg); - SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); - - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); - SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - - OutChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), - Arg, FIPtr, DAG.getSrcValue(0))); - ArgOffset += 4; - } - } - - if (!OutChains.empty()) - DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains)); - - // Finally, inform the code generator which regs we return values in. - switch (getValueType(F.getReturnType())) { - default: assert(0 && "Unknown type!"); - case MVT::isVoid: break; - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - MF.addLiveOut(V8::I0); - break; - case MVT::i64: - MF.addLiveOut(V8::I0); - MF.addLiveOut(V8::I1); - break; - case MVT::f32: - MF.addLiveOut(V8::F0); - break; - case MVT::f64: - MF.addLiveOut(V8::D0); - break; - } - - return ArgValues; -} - -std::pair -SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, - bool isVarArg, unsigned CC, - bool isTailCall, SDOperand Callee, - ArgListTy &Args, SelectionDAG &DAG) { - MachineFunction &MF = DAG.getMachineFunction(); - // Count the size of the outgoing arguments. - unsigned ArgsSize = 0; - for (unsigned i = 0, e = Args.size(); i != e; ++i) { - switch (getValueType(Args[i].second)) { - default: assert(0 && "Unknown value type!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - case MVT::f32: - ArgsSize += 4; - break; - case MVT::i64: - case MVT::f64: - ArgsSize += 8; - break; - } - } - if (ArgsSize > 4*6) - ArgsSize -= 4*6; // Space for first 6 arguments is prereserved. - else - ArgsSize = 0; - - // Keep stack frames 8-byte aligned. - ArgsSize = (ArgsSize+7) & ~7; - - Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain, - DAG.getConstant(ArgsSize, getPointerTy())); - - SDOperand StackPtr, NullSV; - std::vector Stores; - std::vector RegValuesToPass; - unsigned ArgOffset = 68; - for (unsigned i = 0, e = Args.size(); i != e; ++i) { - SDOperand Val = Args[i].first; - MVT::ValueType ObjectVT = Val.getValueType(); - SDOperand ValToStore(0, 0); - unsigned ObjSize; - switch (ObjectVT) { - default: assert(0 && "Unhandled argument type!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - // Promote the integer to 32-bits. If the input type is signed, use a - // sign extend, otherwise use a zero extend. - if (Args[i].second->isSigned()) - Val = DAG.getNode(ISD::SIGN_EXTEND, MVT::i32, Val); - else - Val = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Val); - // FALL THROUGH - case MVT::i32: - ObjSize = 4; - - if (RegValuesToPass.size() >= 6) { - ValToStore = Val; - } else { - RegValuesToPass.push_back(Val); - } - break; - case MVT::f32: - ObjSize = 4; - if (RegValuesToPass.size() >= 6) { - ValToStore = Val; - } else { - // Convert this to a FP value in an int reg. - Val = DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Val); - RegValuesToPass.push_back(Val); - } - break; - case MVT::f64: - ObjSize = 8; - // If we can store this directly into the outgoing slot, do so. We can - // do this when all ArgRegs are used and if the outgoing slot is aligned. - // FIXME: McGill/misr fails with this. - if (0 && RegValuesToPass.size() >= 6 && ((ArgOffset-68) & 7) == 0) { - ValToStore = Val; - break; - } - - // Otherwise, convert this to a FP value in int regs. - Val = DAG.getNode(ISD::BIT_CONVERT, MVT::i64, Val); - // FALL THROUGH - case MVT::i64: - ObjSize = 8; - if (RegValuesToPass.size() >= 6) { - ValToStore = Val; // Whole thing is passed in memory. - break; - } - - // Split the value into top and bottom part. Top part goes in a reg. - SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Val, - DAG.getConstant(1, MVT::i32)); - SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Val, - DAG.getConstant(0, MVT::i32)); - RegValuesToPass.push_back(Hi); - - if (RegValuesToPass.size() >= 6) { - ValToStore = Lo; - ArgOffset += 4; - ObjSize = 4; - } else { - RegValuesToPass.push_back(Lo); - } - break; - } - - if (ValToStore.Val) { - if (!StackPtr.Val) { - StackPtr = DAG.getRegister(V8::O6, MVT::i32); - NullSV = DAG.getSrcValue(NULL); - } - SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy()); - PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff); - Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - ValToStore, PtrOff, NullSV)); - } - ArgOffset += ObjSize; - } - - // Emit all stores, make sure the occur before any copies into physregs. - if (!Stores.empty()) - Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores); - - static const unsigned ArgRegs[] = { - V8::O0, V8::O1, V8::O2, V8::O3, V8::O4, V8::O5 - }; - - // Build a sequence of copy-to-reg nodes chained together with token chain - // and flag operands which copy the outgoing args into O[0-5]. - SDOperand InFlag; - for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) { - Chain = DAG.getCopyToReg(Chain, ArgRegs[i], RegValuesToPass[i], InFlag); - InFlag = Chain.getValue(1); - } - - // If the callee is a GlobalAddress node (quite common, every direct call is) - // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. - if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32); - - std::vector NodeTys; - NodeTys.push_back(MVT::Other); // Returns a chain - NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. - std::vector Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - if (InFlag.Val) - Ops.push_back(InFlag); - Chain = DAG.getNode(V8ISD::CALL, NodeTys, Ops); - InFlag = Chain.getValue(1); - - MVT::ValueType RetTyVT = getValueType(RetTy); - SDOperand RetVal; - if (RetTyVT != MVT::isVoid) { - switch (RetTyVT) { - default: assert(0 && "Unknown value type to return!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - RetVal = DAG.getCopyFromReg(Chain, V8::O0, MVT::i32, InFlag); - Chain = RetVal.getValue(1); - - // Add a note to keep track of whether it is sign or zero extended. - RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext :ISD::AssertZext, - MVT::i32, RetVal, DAG.getValueType(RetTyVT)); - RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal); - break; - case MVT::i32: - RetVal = DAG.getCopyFromReg(Chain, V8::O0, MVT::i32, InFlag); - Chain = RetVal.getValue(1); - break; - case MVT::f32: - RetVal = DAG.getCopyFromReg(Chain, V8::F0, MVT::f32, InFlag); - Chain = RetVal.getValue(1); - break; - case MVT::f64: - RetVal = DAG.getCopyFromReg(Chain, V8::D0, MVT::f64, InFlag); - Chain = RetVal.getValue(1); - break; - case MVT::i64: - SDOperand Lo = DAG.getCopyFromReg(Chain, V8::O1, MVT::i32, InFlag); - SDOperand Hi = DAG.getCopyFromReg(Lo.getValue(1), V8::O0, MVT::i32, - Lo.getValue(2)); - RetVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi); - Chain = Hi.getValue(1); - break; - } - } - - Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain, - DAG.getConstant(ArgsSize, getPointerTy())); - - return std::make_pair(RetVal, Chain); -} - -std::pair SparcV8TargetLowering:: -LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, - SelectionDAG &DAG) { - assert(0 && "Unimp"); - abort(); -} - -// Look at LHS/RHS/CC and see if they are a lowered V8 setcc instruction. If so -// set LHS/RHS and V8CC to the LHS/RHS of the setcc and V8CC to the condition. -static void LookThroughSetCC(SDOperand &LHS, SDOperand &RHS, - ISD::CondCode CC, unsigned &V8CC) { - if (isa(RHS) && cast(RHS)->getValue() == 0 && - CC == ISD::SETNE && - ((LHS.getOpcode() == V8ISD::SELECT_ICC && - LHS.getOperand(3).getOpcode() == V8ISD::CMPICC) || - (LHS.getOpcode() == V8ISD::SELECT_FCC && - LHS.getOperand(3).getOpcode() == V8ISD::CMPFCC)) && - isa(LHS.getOperand(0)) && - isa(LHS.getOperand(1)) && - cast(LHS.getOperand(0))->getValue() == 1 && - cast(LHS.getOperand(1))->getValue() == 0) { - SDOperand CMPCC = LHS.getOperand(3); - V8CC = cast(LHS.getOperand(2))->getValue(); - LHS = CMPCC.getOperand(0); - RHS = CMPCC.getOperand(1); - } -} - - -SDOperand SparcV8TargetLowering:: -LowerOperation(SDOperand Op, SelectionDAG &DAG) { - switch (Op.getOpcode()) { - default: assert(0 && "Should not custom lower this!"); - case ISD::GlobalAddress: { - GlobalValue *GV = cast(Op)->getGlobal(); - SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); - SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, GA); - SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, GA); - return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi); - } - case ISD::ConstantPool: { - Constant *C = cast(Op)->get(); - SDOperand CP = DAG.getTargetConstantPool(C, MVT::i32, - cast(Op)->getAlignment()); - SDOperand Hi = DAG.getNode(V8ISD::Hi, MVT::i32, CP); - SDOperand Lo = DAG.getNode(V8ISD::Lo, MVT::i32, CP); - return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi); - } - case ISD::FP_TO_SINT: - // Convert the fp value to integer in an FP register. - assert(Op.getValueType() == MVT::i32); - Op = DAG.getNode(V8ISD::FTOI, MVT::f32, Op.getOperand(0)); - return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Op); - case ISD::SINT_TO_FP: { - assert(Op.getOperand(0).getValueType() == MVT::i32); - SDOperand Tmp = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Op.getOperand(0)); - // Convert the int value to FP in an FP register. - return DAG.getNode(V8ISD::ITOF, Op.getValueType(), Tmp); - } - case ISD::BR_CC: { - SDOperand Chain = Op.getOperand(0); - ISD::CondCode CC = cast(Op.getOperand(1))->get(); - SDOperand LHS = Op.getOperand(2); - SDOperand RHS = Op.getOperand(3); - SDOperand Dest = Op.getOperand(4); - unsigned Opc, V8CC = ~0U; - - // If this is a br_cc of a "setcc", and if the setcc got lowered into - // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. - LookThroughSetCC(LHS, RHS, CC, V8CC); - - // Get the condition flag. - SDOperand CompareFlag; - if (LHS.getValueType() == MVT::i32) { - std::vector VTs; - VTs.push_back(MVT::i32); - VTs.push_back(MVT::Flag); - std::vector Ops; - Ops.push_back(LHS); - Ops.push_back(RHS); - CompareFlag = DAG.getNode(V8ISD::CMPICC, VTs, Ops).getValue(1); - if (V8CC == ~0U) V8CC = IntCondCCodeToICC(CC); - Opc = V8ISD::BRICC; - } else { - CompareFlag = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS); - if (V8CC == ~0U) V8CC = FPCondCCodeToFCC(CC); - Opc = V8ISD::BRFCC; - } - return DAG.getNode(Opc, MVT::Other, Chain, Dest, - DAG.getConstant(V8CC, MVT::i32), CompareFlag); - } - case ISD::SELECT_CC: { - SDOperand LHS = Op.getOperand(0); - SDOperand RHS = Op.getOperand(1); - ISD::CondCode CC = cast(Op.getOperand(4))->get(); - SDOperand TrueVal = Op.getOperand(2); - SDOperand FalseVal = Op.getOperand(3); - unsigned Opc, V8CC = ~0U; - - // If this is a select_cc of a "setcc", and if the setcc got lowered into - // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values. - LookThroughSetCC(LHS, RHS, CC, V8CC); - - SDOperand CompareFlag; - if (LHS.getValueType() == MVT::i32) { - std::vector VTs; - VTs.push_back(LHS.getValueType()); // subcc returns a value - VTs.push_back(MVT::Flag); - std::vector Ops; - Ops.push_back(LHS); - Ops.push_back(RHS); - CompareFlag = DAG.getNode(V8ISD::CMPICC, VTs, Ops).getValue(1); - Opc = V8ISD::SELECT_ICC; - if (V8CC == ~0U) V8CC = IntCondCCodeToICC(CC); - } else { - CompareFlag = DAG.getNode(V8ISD::CMPFCC, MVT::Flag, LHS, RHS); - Opc = V8ISD::SELECT_FCC; - if (V8CC == ~0U) V8CC = FPCondCCodeToFCC(CC); - } - return DAG.getNode(Opc, TrueVal.getValueType(), TrueVal, FalseVal, - DAG.getConstant(V8CC, MVT::i32), CompareFlag); - } - case ISD::VASTART: { - // vastart just stores the address of the VarArgsFrameIndex slot into the - // memory location argument. - SDOperand Offset = DAG.getNode(ISD::ADD, MVT::i32, - DAG.getRegister(V8::I6, MVT::i32), - DAG.getConstant(VarArgsFrameOffset, MVT::i32)); - return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), Offset, - Op.getOperand(1), Op.getOperand(2)); - } - case ISD::VAARG: { - SDNode *Node = Op.Val; - MVT::ValueType VT = Node->getValueType(0); - SDOperand InChain = Node->getOperand(0); - SDOperand VAListPtr = Node->getOperand(1); - SDOperand VAList = DAG.getLoad(getPointerTy(), InChain, VAListPtr, - Node->getOperand(2)); - // Increment the pointer, VAList, to the next vaarg - SDOperand NextPtr = DAG.getNode(ISD::ADD, getPointerTy(), VAList, - DAG.getConstant(MVT::getSizeInBits(VT)/8, - getPointerTy())); - // Store the incremented VAList to the legalized pointer - InChain = DAG.getNode(ISD::STORE, MVT::Other, VAList.getValue(1), NextPtr, - VAListPtr, Node->getOperand(2)); - // Load the actual argument out of the pointer VAList, unless this is an - // f64 load. - if (VT != MVT::f64) { - return DAG.getLoad(VT, InChain, VAList, DAG.getSrcValue(0)); - } else { - // Otherwise, load it as i64, then do a bitconvert. - SDOperand V = DAG.getLoad(MVT::i64, InChain, VAList, DAG.getSrcValue(0)); - std::vector Tys; - Tys.push_back(MVT::f64); - Tys.push_back(MVT::Other); - std::vector Ops; - // Bit-Convert the value to f64. - Ops.push_back(DAG.getNode(ISD::BIT_CONVERT, MVT::f64, V)); - Ops.push_back(V.getValue(1)); - return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops); - } - } - case ISD::RET: { - SDOperand Copy; - - switch(Op.getNumOperands()) { - default: - assert(0 && "Do not know how to return this many arguments!"); - abort(); - case 1: - return SDOperand(); // ret void is legal - case 2: { - unsigned ArgReg; - switch(Op.getOperand(1).getValueType()) { - default: assert(0 && "Unknown type to return!"); - case MVT::i32: ArgReg = V8::I0; break; - case MVT::f32: ArgReg = V8::F0; break; - case MVT::f64: ArgReg = V8::D0; break; - } - Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1), - SDOperand()); - break; - } - case 3: - Copy = DAG.getCopyToReg(Op.getOperand(0), V8::I0, Op.getOperand(2), - SDOperand()); - Copy = DAG.getCopyToReg(Copy, V8::I1, Op.getOperand(1), Copy.getValue(1)); - break; - } - return DAG.getNode(V8ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); - } - } -} - -MachineBasicBlock * -SparcV8TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, - MachineBasicBlock *BB) { - unsigned BROpcode; - unsigned CC; - // Figure out the conditional branch opcode to use for this select_cc. - switch (MI->getOpcode()) { - default: assert(0 && "Unknown SELECT_CC!"); - case V8::SELECT_CC_Int_ICC: - case V8::SELECT_CC_FP_ICC: - case V8::SELECT_CC_DFP_ICC: - BROpcode = V8::BCOND; - break; - case V8::SELECT_CC_Int_FCC: - case V8::SELECT_CC_FP_FCC: - case V8::SELECT_CC_DFP_FCC: - BROpcode = V8::FBCOND; - break; - } - - CC = (V8CC::CondCodes)MI->getOperand(3).getImmedValue(); - - // To "insert" a SELECT_CC instruction, we actually have to insert the diamond - // control-flow pattern. The incoming instruction knows the destination vreg - // to set, the condition code register to branch on, the true/false values to - // select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - ilist::iterator It = BB; - ++It; - - // thisMBB: - // ... - // TrueVal = ... - // [f]bCC copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *thisMBB = BB; - MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); - BuildMI(BB, BROpcode, 2).addMBB(sinkMBB).addImm(CC); - MachineFunction *F = BB->getParent(); - F->getBasicBlockList().insert(It, copy0MBB); - F->getBasicBlockList().insert(It, sinkMBB); - // Update machine-CFG edges - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] - // ... - BB = sinkMBB; - BuildMI(BB, V8::PHI, 4, MI->getOperand(0).getReg()) - .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) - .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); - - delete MI; // The pseudo instruction is gone now. - return BB; -} - -//===----------------------------------------------------------------------===// -// Instruction Selector Implementation -//===----------------------------------------------------------------------===// - -//===--------------------------------------------------------------------===// -/// SparcV8DAGToDAGISel - SPARC specific code to select Sparc V8 machine -/// instructions for SelectionDAG operations. -/// -namespace { -class SparcV8DAGToDAGISel : public SelectionDAGISel { - SparcV8TargetLowering V8Lowering; - - /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can - /// make the right decision when generating code for different targets. - const SparcV8Subtarget &Subtarget; -public: - SparcV8DAGToDAGISel(TargetMachine &TM) - : SelectionDAGISel(V8Lowering), V8Lowering(TM), - Subtarget(TM.getSubtarget()) { - } - - SDOperand Select(SDOperand Op); - - // Complex Pattern Selectors. - bool SelectADDRrr(SDOperand N, SDOperand &R1, SDOperand &R2); - bool SelectADDRri(SDOperand N, SDOperand &Base, SDOperand &Offset); - - /// InstructionSelectBasicBlock - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); - - virtual const char *getPassName() const { - return "SparcV8 DAG->DAG Pattern Instruction Selection"; - } - - // Include the pieces autogenerated from the target description. -#include "SparcV8GenDAGISel.inc" -}; -} // end anonymous namespace - -/// InstructionSelectBasicBlock - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void SparcV8DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { - DEBUG(BB->dump()); - - // Select target instructions for the DAG. - DAG.setRoot(Select(DAG.getRoot())); - CodeGenMap.clear(); - DAG.RemoveDeadNodes(); - - // Emit machine code to BB. - ScheduleAndEmitDAG(DAG); -} - -bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base, - SDOperand &Offset) { - if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); - Offset = CurDAG->getTargetConstant(0, MVT::i32); - return true; - } - - if (Addr.getOpcode() == ISD::ADD) { - if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) { - if (Predicate_simm13(CN)) { - if (FrameIndexSDNode *FIN = - dyn_cast(Addr.getOperand(0))) { - // Constant offset from frame ref. - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); - } else { - Base = Select(Addr.getOperand(0)); - } - Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32); - return true; - } - } - if (Addr.getOperand(0).getOpcode() == V8ISD::Lo) { - Base = Select(Addr.getOperand(1)); - Offset = Addr.getOperand(0).getOperand(0); - return true; - } - if (Addr.getOperand(1).getOpcode() == V8ISD::Lo) { - Base = Select(Addr.getOperand(0)); - Offset = Addr.getOperand(1).getOperand(0); - return true; - } - } - Base = Select(Addr); - Offset = CurDAG->getTargetConstant(0, MVT::i32); - return true; -} - -bool SparcV8DAGToDAGISel::SelectADDRrr(SDOperand Addr, SDOperand &R1, - SDOperand &R2) { - if (Addr.getOpcode() == ISD::FrameIndex) return false; - if (Addr.getOpcode() == ISD::ADD) { - if (isa(Addr.getOperand(1)) && - Predicate_simm13(Addr.getOperand(1).Val)) - return false; // Let the reg+imm pattern catch this! - if (Addr.getOperand(0).getOpcode() == V8ISD::Lo || - Addr.getOperand(1).getOpcode() == V8ISD::Lo) - return false; // Let the reg+imm pattern catch this! - R1 = Select(Addr.getOperand(0)); - R2 = Select(Addr.getOperand(1)); - return true; - } - - R1 = Select(Addr); - R2 = CurDAG->getRegister(V8::G0, MVT::i32); - return true; -} - -SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) { - SDNode *N = Op.Val; - if (N->getOpcode() >= ISD::BUILTIN_OP_END && - N->getOpcode() < V8ISD::FIRST_NUMBER) - return Op; // Already selected. - // If this has already been converted, use it. - std::map::iterator CGMI = CodeGenMap.find(Op); - if (CGMI != CodeGenMap.end()) return CGMI->second; - - switch (N->getOpcode()) { - default: break; - case ISD::FrameIndex: { - int FI = cast(N)->getIndex(); - if (N->hasOneUse()) - return CurDAG->SelectNodeTo(N, V8::ADDri, MVT::i32, - CurDAG->getTargetFrameIndex(FI, MVT::i32), - CurDAG->getTargetConstant(0, MVT::i32)); - return CodeGenMap[Op] = - CurDAG->getTargetNode(V8::ADDri, MVT::i32, - CurDAG->getTargetFrameIndex(FI, MVT::i32), - CurDAG->getTargetConstant(0, MVT::i32)); - } - case ISD::ADD_PARTS: { - SDOperand LHSL = Select(N->getOperand(0)); - SDOperand LHSH = Select(N->getOperand(1)); - SDOperand RHSL = Select(N->getOperand(2)); - SDOperand RHSH = Select(N->getOperand(3)); - // FIXME, handle immediate RHS. - SDOperand Low = CurDAG->getTargetNode(V8::ADDCCrr, MVT::i32, MVT::Flag, - LHSL, RHSL); - SDOperand Hi = CurDAG->getTargetNode(V8::ADDXrr, MVT::i32, LHSH, RHSH, - Low.getValue(1)); - CodeGenMap[SDOperand(N, 0)] = Low; - CodeGenMap[SDOperand(N, 1)] = Hi; - return Op.ResNo ? Hi : Low; - } - case ISD::SUB_PARTS: { - SDOperand LHSL = Select(N->getOperand(0)); - SDOperand LHSH = Select(N->getOperand(1)); - SDOperand RHSL = Select(N->getOperand(2)); - SDOperand RHSH = Select(N->getOperand(3)); - // FIXME, handle immediate RHS. - SDOperand Low = CurDAG->getTargetNode(V8::SUBCCrr, MVT::i32, MVT::Flag, - LHSL, RHSL); - SDOperand Hi = CurDAG->getTargetNode(V8::SUBXrr, MVT::i32, LHSH, RHSH, - Low.getValue(1)); - CodeGenMap[SDOperand(N, 0)] = Low; - CodeGenMap[SDOperand(N, 1)] = Hi; - return Op.ResNo ? Hi : Low; - } - case ISD::SDIV: - case ISD::UDIV: { - // FIXME: should use a custom expander to expose the SRA to the dag. - SDOperand DivLHS = Select(N->getOperand(0)); - SDOperand DivRHS = Select(N->getOperand(1)); - - // Set the Y register to the high-part. - SDOperand TopPart; - if (N->getOpcode() == ISD::SDIV) { - TopPart = CurDAG->getTargetNode(V8::SRAri, MVT::i32, DivLHS, - CurDAG->getTargetConstant(31, MVT::i32)); - } else { - TopPart = CurDAG->getRegister(V8::G0, MVT::i32); - } - TopPart = CurDAG->getTargetNode(V8::WRYrr, MVT::Flag, TopPart, - CurDAG->getRegister(V8::G0, MVT::i32)); - - // FIXME: Handle div by immediate. - unsigned Opcode = N->getOpcode() == ISD::SDIV ? V8::SDIVrr : V8::UDIVrr; - return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart); - } - case ISD::MULHU: - case ISD::MULHS: { - // FIXME: Handle mul by immediate. - SDOperand MulLHS = Select(N->getOperand(0)); - SDOperand MulRHS = Select(N->getOperand(1)); - unsigned Opcode = N->getOpcode() == ISD::MULHU ? V8::UMULrr : V8::SMULrr; - SDOperand Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag, - MulLHS, MulRHS); - // The high part is in the Y register. - return CurDAG->SelectNodeTo(N, V8::RDY, MVT::i32, Mul.getValue(1)); - } - case V8ISD::CALL: - // FIXME: This is a workaround for a bug in tblgen. - { // Pattern #47: (call:Flag (tglobaladdr:i32):$dst, ICC:Flag) - // Emits: (CALL:void (tglobaladdr:i32):$dst) - // Pattern complexity = 2 cost = 1 - SDOperand N1 = N->getOperand(1); - if (N1.getOpcode() != ISD::TargetGlobalAddress && - N1.getOpcode() != ISD::ExternalSymbol) goto P47Fail; - SDOperand InFlag = SDOperand(0, 0); - SDOperand Chain = N->getOperand(0); - SDOperand Tmp0 = N1; - Chain = Select(Chain); - SDOperand Result; - if (N->getNumOperands() == 3) { - InFlag = Select(N->getOperand(2)); - Result = CurDAG->getTargetNode(V8::CALL, MVT::Other, MVT::Flag, Tmp0, - Chain, InFlag); - } else { - Result = CurDAG->getTargetNode(V8::CALL, MVT::Other, MVT::Flag, Tmp0, - Chain); - } - Chain = CodeGenMap[SDOperand(N, 0)] = Result.getValue(0); - CodeGenMap[SDOperand(N, 1)] = Result.getValue(1); - return Result.getValue(Op.ResNo); - } - P47Fail:; - - } - - return SelectCode(Op); -} - - -/// createSparcV8ISelDag - This pass converts a legalized DAG into a -/// SPARC-specific DAG, ready for instruction scheduling. -/// -FunctionPass *llvm::createSparcV8ISelDag(TargetMachine &TM) { - return new SparcV8DAGToDAGISel(TM); -} diff --git a/lib/Target/SparcV8/SparcV8InstrFormats.td b/lib/Target/SparcV8/SparcV8InstrFormats.td deleted file mode 100644 index 9b15aeed50c..00000000000 --- a/lib/Target/SparcV8/SparcV8InstrFormats.td +++ /dev/null @@ -1,111 +0,0 @@ -//===- SparcV8InstrFormats.td - SparcV8 Instr Formats ------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -class InstV8 pattern> : Instruction { - field bits<32> Inst; - - let Namespace = "V8"; - - bits<2> op; - let Inst{31-30} = op; // Top two bits are the 'op' field - - dag OperandList = ops; - let AsmString = asmstr; - let Pattern = pattern; -} - -//===----------------------------------------------------------------------===// -// Format #2 instruction classes in the SparcV8 -//===----------------------------------------------------------------------===// - -// Format 2 instructions -class F2 pattern> - : InstV8 { - bits<3> op2; - bits<22> imm22; - let op = 0; // op = 0 - let Inst{24-22} = op2; - let Inst{21-0} = imm22; -} - -// Specific F2 classes: SparcV8 manual, page 44 -// -class F2_1 op2Val, dag ops, string asmstr, list pattern> - : F2 { - bits<5> rd; - - let op2 = op2Val; - - let Inst{29-25} = rd; -} - -class F2_2 condVal, bits<3> op2Val, dag ops, string asmstr, - list pattern> : F2 { - bits<4> cond; - bit annul = 0; // currently unused - - let cond = condVal; - let op2 = op2Val; - - let Inst{29} = annul; - let Inst{28-25} = cond; -} - -//===----------------------------------------------------------------------===// -// Format #3 instruction classes in the SparcV8 -//===----------------------------------------------------------------------===// - -class F3 pattern> - : InstV8 { - bits<5> rd; - bits<6> op3; - bits<5> rs1; - let op{1} = 1; // Op = 2 or 3 - let Inst{29-25} = rd; - let Inst{24-19} = op3; - let Inst{18-14} = rs1; -} - -// Specific F3 classes: SparcV8 manual, page 44 -// -class F3_1 opVal, bits<6> op3val, dag ops, - string asmstr, list pattern> : F3 { - bits<8> asi = 0; // asi not currently used in SparcV8 - bits<5> rs2; - - let op = opVal; - let op3 = op3val; - - let Inst{13} = 0; // i field = 0 - let Inst{12-5} = asi; // address space identifier - let Inst{4-0} = rs2; -} - -class F3_2 opVal, bits<6> op3val, dag ops, - string asmstr, list pattern> : F3 { - bits<13> simm13; - - let op = opVal; - let op3 = op3val; - - let Inst{13} = 1; // i field = 1 - let Inst{12-0} = simm13; -} - -// floating-point -class F3_3 opVal, bits<6> op3val, bits<9> opfval, dag ops, - string asmstr, list pattern> : F3 { - bits<5> rs2; - - let op = opVal; - let op3 = op3val; - - let Inst{13-5} = opfval; // fp opcode - let Inst{4-0} = rs2; -} diff --git a/lib/Target/SparcV8/SparcV8InstrInfo.cpp b/lib/Target/SparcV8/SparcV8InstrInfo.cpp deleted file mode 100644 index 8f0dc01cd14..00000000000 --- a/lib/Target/SparcV8/SparcV8InstrInfo.cpp +++ /dev/null @@ -1,98 +0,0 @@ -//===- SparcV8InstrInfo.cpp - SparcV8 Instruction Information ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the SparcV8 implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#include "SparcV8InstrInfo.h" -#include "SparcV8.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "SparcV8GenInstrInfo.inc" -using namespace llvm; - -SparcV8InstrInfo::SparcV8InstrInfo(SparcV8Subtarget &ST) - : TargetInstrInfo(SparcV8Insts, sizeof(SparcV8Insts)/sizeof(SparcV8Insts[0])), - RI(ST) { -} - -static bool isZeroImm(const MachineOperand &op) { - return op.isImmediate() && op.getImmedValue() == 0; -} - -/// Return true if the instruction is a register to register move and -/// leave the source and dest operands in the passed parameters. -/// -bool SparcV8InstrInfo::isMoveInstr(const MachineInstr &MI, - unsigned &SrcReg, unsigned &DstReg) const { - // We look for 3 kinds of patterns here: - // or with G0 or 0 - // add with G0 or 0 - // fmovs or FpMOVD (pseudo double move). - if (MI.getOpcode() == V8::ORrr || MI.getOpcode() == V8::ADDrr) { - if (MI.getOperand(1).getReg() == V8::G0) { - DstReg = MI.getOperand(0).getReg(); - SrcReg = MI.getOperand(2).getReg(); - return true; - } else if (MI.getOperand(2).getReg() == V8::G0) { - DstReg = MI.getOperand(0).getReg(); - SrcReg = MI.getOperand(1).getReg(); - return true; - } - } else if ((MI.getOpcode() == V8::ORri || MI.getOpcode() == V8::ADDri) && - isZeroImm(MI.getOperand(2)) && MI.getOperand(1).isRegister()) { - DstReg = MI.getOperand(0).getReg(); - SrcReg = MI.getOperand(1).getReg(); - return true; - } else if (MI.getOpcode() == V8::FMOVS || MI.getOpcode() == V8::FpMOVD || - MI.getOpcode() == V8::FMOVD) { - SrcReg = MI.getOperand(1).getReg(); - DstReg = MI.getOperand(0).getReg(); - return true; - } - return false; -} - -/// isLoadFromStackSlot - If the specified machine instruction is a direct -/// load from a stack slot, return the virtual or physical register number of -/// the destination along with the FrameIndex of the loaded stack slot. If -/// not, return 0. This predicate must return 0 if the instruction has -/// any side effects other than loading from the stack slot. -unsigned SparcV8InstrInfo::isLoadFromStackSlot(MachineInstr *MI, - int &FrameIndex) const { - if (MI->getOpcode() == V8::LDri || - MI->getOpcode() == V8::LDFri || - MI->getOpcode() == V8::LDDFri) { - if (MI->getOperand(1).isFrameIndex() && MI->getOperand(2).isImmediate() && - MI->getOperand(2).getImmedValue() == 0) { - FrameIndex = MI->getOperand(1).getFrameIndex(); - return MI->getOperand(0).getReg(); - } - } - return 0; -} - -/// isStoreToStackSlot - If the specified machine instruction is a direct -/// store to a stack slot, return the virtual or physical register number of -/// the source reg along with the FrameIndex of the loaded stack slot. If -/// not, return 0. This predicate must return 0 if the instruction has -/// any side effects other than storing to the stack slot. -unsigned SparcV8InstrInfo::isStoreToStackSlot(MachineInstr *MI, - int &FrameIndex) const { - if (MI->getOpcode() == V8::STri || - MI->getOpcode() == V8::STFri || - MI->getOpcode() == V8::STDFri) { - if (MI->getOperand(0).isFrameIndex() && MI->getOperand(1).isImmediate() && - MI->getOperand(1).getImmedValue() == 0) { - FrameIndex = MI->getOperand(0).getFrameIndex(); - return MI->getOperand(2).getReg(); - } - } - return 0; -} diff --git a/lib/Target/SparcV8/SparcV8InstrInfo.h b/lib/Target/SparcV8/SparcV8InstrInfo.h deleted file mode 100644 index 0b2ee905e36..00000000000 --- a/lib/Target/SparcV8/SparcV8InstrInfo.h +++ /dev/null @@ -1,68 +0,0 @@ -//===- SparcV8InstrInfo.h - SparcV8 Instruction Information -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the SparcV8 implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef SPARCV8INSTRUCTIONINFO_H -#define SPARCV8INSTRUCTIONINFO_H - -#include "llvm/Target/TargetInstrInfo.h" -#include "SparcV8RegisterInfo.h" - -namespace llvm { - -/// V8II - This namespace holds all of the target specific flags that -/// instruction info tracks. -/// -namespace V8II { - enum { - Pseudo = (1<<0), - Load = (1<<1), - Store = (1<<2), - DelaySlot = (1<<3) - }; -}; - -class SparcV8InstrInfo : public TargetInstrInfo { - const SparcV8RegisterInfo RI; -public: - SparcV8InstrInfo(SparcV8Subtarget &ST); - - /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As - /// such, whenever a client has an instance of instruction info, it should - /// always be able to get register info as well (through this method). - /// - virtual const MRegisterInfo &getRegisterInfo() const { return RI; } - - /// Return true if the instruction is a register to register move and - /// leave the source and dest operands in the passed parameters. - /// - virtual bool isMoveInstr(const MachineInstr &MI, - unsigned &SrcReg, unsigned &DstReg) const; - - /// isLoadFromStackSlot - If the specified machine instruction is a direct - /// load from a stack slot, return the virtual or physical register number of - /// the destination along with the FrameIndex of the loaded stack slot. If - /// not, return 0. This predicate must return 0 if the instruction has - /// any side effects other than loading from the stack slot. - virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; - - /// isStoreToStackSlot - If the specified machine instruction is a direct - /// store to a stack slot, return the virtual or physical register number of - /// the source reg along with the FrameIndex of the loaded stack slot. If - /// not, return 0. This predicate must return 0 if the instruction has - /// any side effects other than storing to the stack slot. - virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const; -}; - -} - -#endif diff --git a/lib/Target/SparcV8/SparcV8InstrInfo.td b/lib/Target/SparcV8/SparcV8InstrInfo.td deleted file mode 100644 index f6d35adfd2b..00000000000 --- a/lib/Target/SparcV8/SparcV8InstrInfo.td +++ /dev/null @@ -1,845 +0,0 @@ -//===- SparcV8Instrs.td - Target Description for SparcV8 Target -----------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file describes the SparcV8 instructions in TableGen format. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Instruction format superclass -//===----------------------------------------------------------------------===// - -include "SparcV8InstrFormats.td" - -//===----------------------------------------------------------------------===// -// Feature predicates. -//===----------------------------------------------------------------------===// - -// HasV9 - This predicate is true when the target processor supports V9 -// instructions. Note that the machine may be running in 32-bit mode. -def HasV9 : Predicate<"Subtarget.isV9()">; - -// HasNoV9 - This predicate is true when the target doesn't have V9 -// instructions. Use of this is just a hack for the isel not having proper -// costs for V8 instructions that are more expensive than their V9 ones. -def HasNoV9 : Predicate<"!Subtarget.isV9()">; - -// HasVIS - This is true when the target processor has VIS extensions. -def HasVIS : Predicate<"Subtarget.isVIS()">; - -// UseDeprecatedInsts - This predicate is true when the target processor is a -// V8, or when it is V9 but the V8 deprecated instructions are efficient enough -// to use when appropriate. In either of these cases, the instruction selector -// will pick deprecated instructions. -def UseDeprecatedInsts : Predicate<"Subtarget.useDeprecatedV8Instructions()">; - -//===----------------------------------------------------------------------===// -// Instruction Pattern Stuff -//===----------------------------------------------------------------------===// - -def simm11 : PatLeaf<(imm), [{ - // simm11 predicate - True if the imm fits in a 11-bit sign extended field. - return (((int)N->getValue() << (32-11)) >> (32-11)) == (int)N->getValue(); -}]>; - -def simm13 : PatLeaf<(imm), [{ - // simm13 predicate - True if the imm fits in a 13-bit sign extended field. - return (((int)N->getValue() << (32-13)) >> (32-13)) == (int)N->getValue(); -}]>; - -def LO10 : SDNodeXFormgetTargetConstant((unsigned)N->getValue() & 1023, MVT::i32); -}]>; - -def HI22 : SDNodeXFormgetTargetConstant((unsigned)N->getValue() >> 10, MVT::i32); -}]>; - -def SETHIimm : PatLeaf<(imm), [{ - return (((unsigned)N->getValue() >> 10) << 10) == (unsigned)N->getValue(); -}], HI22>; - -// Addressing modes. -def ADDRrr : ComplexPattern; -def ADDRri : ComplexPattern; - -// Address operands -def MEMrr : Operand { - let PrintMethod = "printMemOperand"; - let NumMIOperands = 2; - let MIOperandInfo = (ops IntRegs, IntRegs); -} -def MEMri : Operand { - let PrintMethod = "printMemOperand"; - let NumMIOperands = 2; - let MIOperandInfo = (ops IntRegs, i32imm); -} - -// Branch targets have OtherVT type. -def brtarget : Operand; -def calltarget : Operand; - -// Operand for printing out a condition code. -let PrintMethod = "printV8CCOperand" in - def V8CC : Operand; - -def SDTV8cmpfcc : -SDTypeProfile<1, 2, [SDTCisVT<0, FlagVT>, SDTCisFP<1>, SDTCisSameAs<1, 2>]>; -def SDTV8brcc : -SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>, - SDTCisVT<2, FlagVT>]>; -def SDTV8selectcc : -SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, - SDTCisVT<3, i32>, SDTCisVT<4, FlagVT>]>; -def SDTV8FTOI : -SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisFP<1>]>; -def SDTV8ITOF : -SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, f32>]>; - -def V8cmpicc : SDNode<"V8ISD::CMPICC", SDTIntBinOp, [SDNPOutFlag]>; -def V8cmpfcc : SDNode<"V8ISD::CMPFCC", SDTV8cmpfcc, [SDNPOutFlag]>; -def V8bricc : SDNode<"V8ISD::BRICC", SDTV8brcc, [SDNPHasChain]>; -def V8brfcc : SDNode<"V8ISD::BRFCC", SDTV8brcc, [SDNPHasChain]>; - -def V8hi : SDNode<"V8ISD::Hi", SDTIntUnaryOp>; -def V8lo : SDNode<"V8ISD::Lo", SDTIntUnaryOp>; - -def V8ftoi : SDNode<"V8ISD::FTOI", SDTV8FTOI>; -def V8itof : SDNode<"V8ISD::ITOF", SDTV8ITOF>; - -def V8selecticc : SDNode<"V8ISD::SELECT_ICC", SDTV8selectcc>; -def V8selectfcc : SDNode<"V8ISD::SELECT_FCC", SDTV8selectcc>; - -// These are target-independent nodes, but have target-specific formats. -def SDT_V8CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i32> ]>; -def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_V8CallSeq, [SDNPHasChain]>; -def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_V8CallSeq, [SDNPHasChain]>; - -def SDT_V8Call : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; -def call : SDNode<"V8ISD::CALL", SDT_V8Call, - [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; - -def SDT_V8RetFlag : SDTypeProfile<0, 0, []>; -def retflag : SDNode<"V8ISD::RET_FLAG", SDT_V8RetFlag, - [SDNPHasChain, SDNPOptInFlag]>; - -//===----------------------------------------------------------------------===// -// SPARC Flag Conditions -//===----------------------------------------------------------------------===// - -// Note that these values must be kept in sync with the V8CC::CondCode enum -// values. -class ICC_VAL : PatLeaf<(i32 N)>; -def ICC_NE : ICC_VAL< 9>; // Not Equal -def ICC_E : ICC_VAL< 1>; // Equal -def ICC_G : ICC_VAL<10>; // Greater -def ICC_LE : ICC_VAL< 2>; // Less or Equal -def ICC_GE : ICC_VAL<11>; // Greater or Equal -def ICC_L : ICC_VAL< 3>; // Less -def ICC_GU : ICC_VAL<12>; // Greater Unsigned -def ICC_LEU : ICC_VAL< 4>; // Less or Equal Unsigned -def ICC_CC : ICC_VAL<13>; // Carry Clear/Great or Equal Unsigned -def ICC_CS : ICC_VAL< 5>; // Carry Set/Less Unsigned -def ICC_POS : ICC_VAL<14>; // Positive -def ICC_NEG : ICC_VAL< 6>; // Negative -def ICC_VC : ICC_VAL<15>; // Overflow Clear -def ICC_VS : ICC_VAL< 7>; // Overflow Set - -class FCC_VAL : PatLeaf<(i32 N)>; -def FCC_U : FCC_VAL<23>; // Unordered -def FCC_G : FCC_VAL<22>; // Greater -def FCC_UG : FCC_VAL<21>; // Unordered or Greater -def FCC_L : FCC_VAL<20>; // Less -def FCC_UL : FCC_VAL<19>; // Unordered or Less -def FCC_LG : FCC_VAL<18>; // Less or Greater -def FCC_NE : FCC_VAL<17>; // Not Equal -def FCC_E : FCC_VAL<25>; // Equal -def FCC_UE : FCC_VAL<24>; // Unordered or Equal -def FCC_GE : FCC_VAL<25>; // Greater or Equal -def FCC_UGE : FCC_VAL<26>; // Unordered or Greater or Equal -def FCC_LE : FCC_VAL<27>; // Less or Equal -def FCC_ULE : FCC_VAL<28>; // Unordered or Less or Equal -def FCC_O : FCC_VAL<29>; // Ordered - - -//===----------------------------------------------------------------------===// -// Instructions -//===----------------------------------------------------------------------===// - -// Pseudo instructions. -class Pseudo pattern> - : InstV8; - -def ADJCALLSTACKDOWN : Pseudo<(ops i32imm:$amt), - "!ADJCALLSTACKDOWN $amt", - [(callseq_start imm:$amt)]>; -def ADJCALLSTACKUP : Pseudo<(ops i32imm:$amt), - "!ADJCALLSTACKUP $amt", - [(callseq_end imm:$amt)]>; -def IMPLICIT_DEF_Int : Pseudo<(ops IntRegs:$dst), - "!IMPLICIT_DEF $dst", - [(set IntRegs:$dst, (undef))]>; -def IMPLICIT_DEF_FP : Pseudo<(ops FPRegs:$dst), "!IMPLICIT_DEF $dst", - [(set FPRegs:$dst, (undef))]>; -def IMPLICIT_DEF_DFP : Pseudo<(ops DFPRegs:$dst), "!IMPLICIT_DEF $dst", - [(set DFPRegs:$dst, (undef))]>; - -// FpMOVD/FpNEGD/FpABSD - These are lowered to single-precision ops by the -// fpmover pass. -let Predicates = [HasNoV9] in { // Only emit these in V8 mode. - def FpMOVD : Pseudo<(ops DFPRegs:$dst, DFPRegs:$src), - "!FpMOVD $src, $dst", []>; - def FpNEGD : Pseudo<(ops DFPRegs:$dst, DFPRegs:$src), - "!FpNEGD $src, $dst", - [(set DFPRegs:$dst, (fneg DFPRegs:$src))]>; - def FpABSD : Pseudo<(ops DFPRegs:$dst, DFPRegs:$src), - "!FpABSD $src, $dst", - [(set DFPRegs:$dst, (fabs DFPRegs:$src))]>; -} - -// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded by the -// scheduler into a branch sequence. This has to handle all permutations of -// selection between i32/f32/f64 on ICC and FCC. -let usesCustomDAGSchedInserter = 1, // Expanded by the scheduler. - Predicates = [HasNoV9] in { // V9 has conditional moves - def SELECT_CC_Int_ICC - : Pseudo<(ops IntRegs:$dst, IntRegs:$T, IntRegs:$F, i32imm:$Cond), - "; SELECT_CC_Int_ICC PSEUDO!", - [(set IntRegs:$dst, (V8selecticc IntRegs:$T, IntRegs:$F, - imm:$Cond, ICC))]>; - def SELECT_CC_Int_FCC - : Pseudo<(ops IntRegs:$dst, IntRegs:$T, IntRegs:$F, i32imm:$Cond), - "; SELECT_CC_Int_FCC PSEUDO!", - [(set IntRegs:$dst, (V8selectfcc IntRegs:$T, IntRegs:$F, - imm:$Cond, FCC))]>; - def SELECT_CC_FP_ICC - : Pseudo<(ops FPRegs:$dst, FPRegs:$T, FPRegs:$F, i32imm:$Cond), - "; SELECT_CC_FP_ICC PSEUDO!", - [(set FPRegs:$dst, (V8selecticc FPRegs:$T, FPRegs:$F, - imm:$Cond, ICC))]>; - def SELECT_CC_FP_FCC - : Pseudo<(ops FPRegs:$dst, FPRegs:$T, FPRegs:$F, i32imm:$Cond), - "; SELECT_CC_FP_FCC PSEUDO!", - [(set FPRegs:$dst, (V8selectfcc FPRegs:$T, FPRegs:$F, - imm:$Cond, FCC))]>; - def SELECT_CC_DFP_ICC - : Pseudo<(ops DFPRegs:$dst, DFPRegs:$T, DFPRegs:$F, i32imm:$Cond), - "; SELECT_CC_DFP_ICC PSEUDO!", - [(set DFPRegs:$dst, (V8selecticc DFPRegs:$T, DFPRegs:$F, - imm:$Cond, ICC))]>; - def SELECT_CC_DFP_FCC - : Pseudo<(ops DFPRegs:$dst, DFPRegs:$T, DFPRegs:$F, i32imm:$Cond), - "; SELECT_CC_DFP_FCC PSEUDO!", - [(set DFPRegs:$dst, (V8selectfcc DFPRegs:$T, DFPRegs:$F, - imm:$Cond, FCC))]>; -} - - -// Section A.3 - Synthetic Instructions, p. 85 -// special cases of JMPL: -let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, noResults = 1 in { - let rd = O7.Num, rs1 = G0.Num, simm13 = 8 in - def RETL: F3_2<2, 0b111000, (ops), "retl", [(retflag)]>; -} - -// Section B.1 - Load Integer Instructions, p. 90 -def LDSBrr : F3_1<3, 0b001001, - (ops IntRegs:$dst, MEMrr:$addr), - "ldsb [$addr], $dst", - [(set IntRegs:$dst, (sextload ADDRrr:$addr, i8))]>; -def LDSBri : F3_2<3, 0b001001, - (ops IntRegs:$dst, MEMri:$addr), - "ldsb [$addr], $dst", - [(set IntRegs:$dst, (sextload ADDRri:$addr, i8))]>; -def LDSHrr : F3_1<3, 0b001010, - (ops IntRegs:$dst, MEMrr:$addr), - "ldsh [$addr], $dst", - [(set IntRegs:$dst, (sextload ADDRrr:$addr, i16))]>; -def LDSHri : F3_2<3, 0b001010, - (ops IntRegs:$dst, MEMri:$addr), - "ldsh [$addr], $dst", - [(set IntRegs:$dst, (sextload ADDRri:$addr, i16))]>; -def LDUBrr : F3_1<3, 0b000001, - (ops IntRegs:$dst, MEMrr:$addr), - "ldub [$addr], $dst", - [(set IntRegs:$dst, (zextload ADDRrr:$addr, i8))]>; -def LDUBri : F3_2<3, 0b000001, - (ops IntRegs:$dst, MEMri:$addr), - "ldub [$addr], $dst", - [(set IntRegs:$dst, (zextload ADDRri:$addr, i8))]>; -def LDUHrr : F3_1<3, 0b000010, - (ops IntRegs:$dst, MEMrr:$addr), - "lduh [$addr], $dst", - [(set IntRegs:$dst, (zextload ADDRrr:$addr, i16))]>; -def LDUHri : F3_2<3, 0b000010, - (ops IntRegs:$dst, MEMri:$addr), - "lduh [$addr], $dst", - [(set IntRegs:$dst, (zextload ADDRri:$addr, i16))]>; -def LDrr : F3_1<3, 0b000000, - (ops IntRegs:$dst, MEMrr:$addr), - "ld [$addr], $dst", - [(set IntRegs:$dst, (load ADDRrr:$addr))]>; -def LDri : F3_2<3, 0b000000, - (ops IntRegs:$dst, MEMri:$addr), - "ld [$addr], $dst", - [(set IntRegs:$dst, (load ADDRri:$addr))]>; - -// Section B.2 - Load Floating-point Instructions, p. 92 -def LDFrr : F3_1<3, 0b100000, - (ops FPRegs:$dst, MEMrr:$addr), - "ld [$addr], $dst", - [(set FPRegs:$dst, (load ADDRrr:$addr))]>; -def LDFri : F3_2<3, 0b100000, - (ops FPRegs:$dst, MEMri:$addr), - "ld [$addr], $dst", - [(set FPRegs:$dst, (load ADDRri:$addr))]>; -def LDDFrr : F3_1<3, 0b100011, - (ops DFPRegs:$dst, MEMrr:$addr), - "ldd [$addr], $dst", - [(set DFPRegs:$dst, (load ADDRrr:$addr))]>; -def LDDFri : F3_2<3, 0b100011, - (ops DFPRegs:$dst, MEMri:$addr), - "ldd [$addr], $dst", - [(set DFPRegs:$dst, (load ADDRri:$addr))]>; - -// Section B.4 - Store Integer Instructions, p. 95 -def STBrr : F3_1<3, 0b000101, - (ops MEMrr:$addr, IntRegs:$src), - "stb $src, [$addr]", - [(truncstore IntRegs:$src, ADDRrr:$addr, i8)]>; -def STBri : F3_2<3, 0b000101, - (ops MEMri:$addr, IntRegs:$src), - "stb $src, [$addr]", - [(truncstore IntRegs:$src, ADDRri:$addr, i8)]>; -def STHrr : F3_1<3, 0b000110, - (ops MEMrr:$addr, IntRegs:$src), - "sth $src, [$addr]", - [(truncstore IntRegs:$src, ADDRrr:$addr, i16)]>; -def STHri : F3_2<3, 0b000110, - (ops MEMri:$addr, IntRegs:$src), - "sth $src, [$addr]", - [(truncstore IntRegs:$src, ADDRri:$addr, i16)]>; -def STrr : F3_1<3, 0b000100, - (ops MEMrr:$addr, IntRegs:$src), - "st $src, [$addr]", - [(store IntRegs:$src, ADDRrr:$addr)]>; -def STri : F3_2<3, 0b000100, - (ops MEMri:$addr, IntRegs:$src), - "st $src, [$addr]", - [(store IntRegs:$src, ADDRri:$addr)]>; - -// Section B.5 - Store Floating-point Instructions, p. 97 -def STFrr : F3_1<3, 0b100100, - (ops MEMrr:$addr, FPRegs:$src), - "st $src, [$addr]", - [(store FPRegs:$src, ADDRrr:$addr)]>; -def STFri : F3_2<3, 0b100100, - (ops MEMri:$addr, FPRegs:$src), - "st $src, [$addr]", - [(store FPRegs:$src, ADDRri:$addr)]>; -def STDFrr : F3_1<3, 0b100111, - (ops MEMrr:$addr, DFPRegs:$src), - "std $src, [$addr]", - [(store DFPRegs:$src, ADDRrr:$addr)]>; -def STDFri : F3_2<3, 0b100111, - (ops MEMri:$addr, DFPRegs:$src), - "std $src, [$addr]", - [(store DFPRegs:$src, ADDRri:$addr)]>; - -// Section B.9 - SETHI Instruction, p. 104 -def SETHIi: F2_1<0b100, - (ops IntRegs:$dst, i32imm:$src), - "sethi $src, $dst", - [(set IntRegs:$dst, SETHIimm:$src)]>; - -// Section B.10 - NOP Instruction, p. 105 -// (It's a special case of SETHI) -let rd = 0, imm22 = 0 in - def NOP : F2_1<0b100, (ops), "nop", []>; - -// Section B.11 - Logical Instructions, p. 106 -def ANDrr : F3_1<2, 0b000001, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "and $b, $c, $dst", - [(set IntRegs:$dst, (and IntRegs:$b, IntRegs:$c))]>; -def ANDri : F3_2<2, 0b000001, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "and $b, $c, $dst", - [(set IntRegs:$dst, (and IntRegs:$b, simm13:$c))]>; -def ANDNrr : F3_1<2, 0b000101, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "andn $b, $c, $dst", - [(set IntRegs:$dst, (and IntRegs:$b, (not IntRegs:$c)))]>; -def ANDNri : F3_2<2, 0b000101, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "andn $b, $c, $dst", []>; -def ORrr : F3_1<2, 0b000010, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "or $b, $c, $dst", - [(set IntRegs:$dst, (or IntRegs:$b, IntRegs:$c))]>; -def ORri : F3_2<2, 0b000010, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "or $b, $c, $dst", - [(set IntRegs:$dst, (or IntRegs:$b, simm13:$c))]>; -def ORNrr : F3_1<2, 0b000110, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "orn $b, $c, $dst", - [(set IntRegs:$dst, (or IntRegs:$b, (not IntRegs:$c)))]>; -def ORNri : F3_2<2, 0b000110, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "orn $b, $c, $dst", []>; -def XORrr : F3_1<2, 0b000011, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "xor $b, $c, $dst", - [(set IntRegs:$dst, (xor IntRegs:$b, IntRegs:$c))]>; -def XORri : F3_2<2, 0b000011, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "xor $b, $c, $dst", - [(set IntRegs:$dst, (xor IntRegs:$b, simm13:$c))]>; -def XNORrr : F3_1<2, 0b000111, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "xnor $b, $c, $dst", - [(set IntRegs:$dst, (not (xor IntRegs:$b, IntRegs:$c)))]>; -def XNORri : F3_2<2, 0b000111, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "xnor $b, $c, $dst", []>; - -// Section B.12 - Shift Instructions, p. 107 -def SLLrr : F3_1<2, 0b100101, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "sll $b, $c, $dst", - [(set IntRegs:$dst, (shl IntRegs:$b, IntRegs:$c))]>; -def SLLri : F3_2<2, 0b100101, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "sll $b, $c, $dst", - [(set IntRegs:$dst, (shl IntRegs:$b, simm13:$c))]>; -def SRLrr : F3_1<2, 0b100110, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "srl $b, $c, $dst", - [(set IntRegs:$dst, (srl IntRegs:$b, IntRegs:$c))]>; -def SRLri : F3_2<2, 0b100110, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "srl $b, $c, $dst", - [(set IntRegs:$dst, (srl IntRegs:$b, simm13:$c))]>; -def SRArr : F3_1<2, 0b100111, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "sra $b, $c, $dst", - [(set IntRegs:$dst, (sra IntRegs:$b, IntRegs:$c))]>; -def SRAri : F3_2<2, 0b100111, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "sra $b, $c, $dst", - [(set IntRegs:$dst, (sra IntRegs:$b, simm13:$c))]>; - -// Section B.13 - Add Instructions, p. 108 -def ADDrr : F3_1<2, 0b000000, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "add $b, $c, $dst", - [(set IntRegs:$dst, (add IntRegs:$b, IntRegs:$c))]>; -def ADDri : F3_2<2, 0b000000, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "add $b, $c, $dst", - [(set IntRegs:$dst, (add IntRegs:$b, simm13:$c))]>; -def ADDCCrr : F3_1<2, 0b010000, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "addcc $b, $c, $dst", []>; -def ADDCCri : F3_2<2, 0b010000, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "addcc $b, $c, $dst", []>; -def ADDXrr : F3_1<2, 0b001000, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "addx $b, $c, $dst", []>; -def ADDXri : F3_2<2, 0b001000, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "addx $b, $c, $dst", []>; - -// Section B.15 - Subtract Instructions, p. 110 -def SUBrr : F3_1<2, 0b000100, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "sub $b, $c, $dst", - [(set IntRegs:$dst, (sub IntRegs:$b, IntRegs:$c))]>; -def SUBri : F3_2<2, 0b000100, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "sub $b, $c, $dst", - [(set IntRegs:$dst, (sub IntRegs:$b, simm13:$c))]>; -def SUBXrr : F3_1<2, 0b001100, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "subx $b, $c, $dst", []>; -def SUBXri : F3_2<2, 0b001100, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "subx $b, $c, $dst", []>; -def SUBCCrr : F3_1<2, 0b010100, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "subcc $b, $c, $dst", - [(set IntRegs:$dst, (V8cmpicc IntRegs:$b, IntRegs:$c))]>; -def SUBCCri : F3_2<2, 0b010100, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "subcc $b, $c, $dst", - [(set IntRegs:$dst, (V8cmpicc IntRegs:$b, simm13:$c))]>; -def SUBXCCrr: F3_1<2, 0b011100, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "subxcc $b, $c, $dst", []>; - -// Section B.18 - Multiply Instructions, p. 113 -def UMULrr : F3_1<2, 0b001010, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "umul $b, $c, $dst", []>; -def UMULri : F3_2<2, 0b001010, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "umul $b, $c, $dst", []>; -def SMULrr : F3_1<2, 0b001011, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "smul $b, $c, $dst", - [(set IntRegs:$dst, (mul IntRegs:$b, IntRegs:$c))]>; -def SMULri : F3_2<2, 0b001011, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "smul $b, $c, $dst", - [(set IntRegs:$dst, (mul IntRegs:$b, simm13:$c))]>; - -// Section B.19 - Divide Instructions, p. 115 -def UDIVrr : F3_1<2, 0b001110, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "udiv $b, $c, $dst", []>; -def UDIVri : F3_2<2, 0b001110, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "udiv $b, $c, $dst", []>; -def SDIVrr : F3_1<2, 0b001111, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "sdiv $b, $c, $dst", []>; -def SDIVri : F3_2<2, 0b001111, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "sdiv $b, $c, $dst", []>; - -// Section B.20 - SAVE and RESTORE, p. 117 -def SAVErr : F3_1<2, 0b111100, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "save $b, $c, $dst", []>; -def SAVEri : F3_2<2, 0b111100, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "save $b, $c, $dst", []>; -def RESTORErr : F3_1<2, 0b111101, - (ops IntRegs:$dst, IntRegs:$b, IntRegs:$c), - "restore $b, $c, $dst", []>; -def RESTOREri : F3_2<2, 0b111101, - (ops IntRegs:$dst, IntRegs:$b, i32imm:$c), - "restore $b, $c, $dst", []>; - -// Section B.21 - Branch on Integer Condition Codes Instructions, p. 119 - -// conditional branch class: -class BranchV8 cc, dag ops, string asmstr, list pattern> - : F2_2 { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let noResults = 1; -} - -let isBarrier = 1 in - def BA : BranchV8<0b1000, (ops brtarget:$dst), - "ba $dst", - [(br bb:$dst)]>; - -// FIXME: the encoding for the JIT should look at the condition field. -def BCOND : BranchV8<0, (ops brtarget:$dst, V8CC:$cc), - "b$cc $dst", - [(V8bricc bb:$dst, imm:$cc, ICC)]>; - - -// Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121 - -// floating-point conditional branch class: -class FPBranchV8 cc, dag ops, string asmstr, list pattern> - : F2_2 { - let isBranch = 1; - let isTerminator = 1; - let hasDelaySlot = 1; - let noResults = 1; -} - -// FIXME: the encoding for the JIT should look at the condition field. -def FBCOND : FPBranchV8<0, (ops brtarget:$dst, V8CC:$cc), - "fb$cc $dst", - [(V8brfcc bb:$dst, imm:$cc, FCC)]>; - - -// Section B.24 - Call and Link Instruction, p. 125 -// This is the only Format 1 instruction -let Uses = [O0, O1, O2, O3, O4, O5], - hasDelaySlot = 1, isCall = 1, noResults = 1, - Defs = [O0, O1, O2, O3, O4, O5, O7, G1, G2, G3, G4, G5, G6, G7, - D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15] in { - def CALL : InstV8<(ops calltarget:$dst), - "call $dst", []> { - bits<30> disp; - let op = 1; - let Inst{29-0} = disp; - } - - // indirect calls - def JMPLrr : F3_1<2, 0b111000, - (ops MEMrr:$ptr), - "call $ptr", - [(call ADDRrr:$ptr)]>; - def JMPLri : F3_2<2, 0b111000, - (ops MEMri:$ptr), - "call $ptr", - [(call ADDRri:$ptr)]>; -} - -// Section B.28 - Read State Register Instructions -def RDY : F3_1<2, 0b101000, - (ops IntRegs:$dst), - "rd %y, $dst", []>; - -// Section B.29 - Write State Register Instructions -def WRYrr : F3_1<2, 0b110000, - (ops IntRegs:$b, IntRegs:$c), - "wr $b, $c, %y", []>; -def WRYri : F3_2<2, 0b110000, - (ops IntRegs:$b, i32imm:$c), - "wr $b, $c, %y", []>; - -// Convert Integer to Floating-point Instructions, p. 141 -def FITOS : F3_3<2, 0b110100, 0b011000100, - (ops FPRegs:$dst, FPRegs:$src), - "fitos $src, $dst", - [(set FPRegs:$dst, (V8itof FPRegs:$src))]>; -def FITOD : F3_3<2, 0b110100, 0b011001000, - (ops DFPRegs:$dst, FPRegs:$src), - "fitod $src, $dst", - [(set DFPRegs:$dst, (V8itof FPRegs:$src))]>; - -// Convert Floating-point to Integer Instructions, p. 142 -def FSTOI : F3_3<2, 0b110100, 0b011010001, - (ops FPRegs:$dst, FPRegs:$src), - "fstoi $src, $dst", - [(set FPRegs:$dst, (V8ftoi FPRegs:$src))]>; -def FDTOI : F3_3<2, 0b110100, 0b011010010, - (ops FPRegs:$dst, DFPRegs:$src), - "fdtoi $src, $dst", - [(set FPRegs:$dst, (V8ftoi DFPRegs:$src))]>; - -// Convert between Floating-point Formats Instructions, p. 143 -def FSTOD : F3_3<2, 0b110100, 0b011001001, - (ops DFPRegs:$dst, FPRegs:$src), - "fstod $src, $dst", - [(set DFPRegs:$dst, (fextend FPRegs:$src))]>; -def FDTOS : F3_3<2, 0b110100, 0b011000110, - (ops FPRegs:$dst, DFPRegs:$src), - "fdtos $src, $dst", - [(set FPRegs:$dst, (fround DFPRegs:$src))]>; - -// Floating-point Move Instructions, p. 144 -def FMOVS : F3_3<2, 0b110100, 0b000000001, - (ops FPRegs:$dst, FPRegs:$src), - "fmovs $src, $dst", []>; -def FNEGS : F3_3<2, 0b110100, 0b000000101, - (ops FPRegs:$dst, FPRegs:$src), - "fnegs $src, $dst", - [(set FPRegs:$dst, (fneg FPRegs:$src))]>; -def FABSS : F3_3<2, 0b110100, 0b000001001, - (ops FPRegs:$dst, FPRegs:$src), - "fabss $src, $dst", - [(set FPRegs:$dst, (fabs FPRegs:$src))]>; - - -// Floating-point Square Root Instructions, p.145 -def FSQRTS : F3_3<2, 0b110100, 0b000101001, - (ops FPRegs:$dst, FPRegs:$src), - "fsqrts $src, $dst", - [(set FPRegs:$dst, (fsqrt FPRegs:$src))]>; -def FSQRTD : F3_3<2, 0b110100, 0b000101010, - (ops DFPRegs:$dst, DFPRegs:$src), - "fsqrtd $src, $dst", - [(set DFPRegs:$dst, (fsqrt DFPRegs:$src))]>; - - - -// Floating-point Add and Subtract Instructions, p. 146 -def FADDS : F3_3<2, 0b110100, 0b001000001, - (ops FPRegs:$dst, FPRegs:$src1, FPRegs:$src2), - "fadds $src1, $src2, $dst", - [(set FPRegs:$dst, (fadd FPRegs:$src1, FPRegs:$src2))]>; -def FADDD : F3_3<2, 0b110100, 0b001000010, - (ops DFPRegs:$dst, DFPRegs:$src1, DFPRegs:$src2), - "faddd $src1, $src2, $dst", - [(set DFPRegs:$dst, (fadd DFPRegs:$src1, DFPRegs:$src2))]>; -def FSUBS : F3_3<2, 0b110100, 0b001000101, - (ops FPRegs:$dst, FPRegs:$src1, FPRegs:$src2), - "fsubs $src1, $src2, $dst", - [(set FPRegs:$dst, (fsub FPRegs:$src1, FPRegs:$src2))]>; -def FSUBD : F3_3<2, 0b110100, 0b001000110, - (ops DFPRegs:$dst, DFPRegs:$src1, DFPRegs:$src2), - "fsubd $src1, $src2, $dst", - [(set DFPRegs:$dst, (fsub DFPRegs:$src1, DFPRegs:$src2))]>; - -// Floating-point Multiply and Divide Instructions, p. 147 -def FMULS : F3_3<2, 0b110100, 0b001001001, - (ops FPRegs:$dst, FPRegs:$src1, FPRegs:$src2), - "fmuls $src1, $src2, $dst", - [(set FPRegs:$dst, (fmul FPRegs:$src1, FPRegs:$src2))]>; -def FMULD : F3_3<2, 0b110100, 0b001001010, - (ops DFPRegs:$dst, DFPRegs:$src1, DFPRegs:$src2), - "fmuld $src1, $src2, $dst", - [(set DFPRegs:$dst, (fmul DFPRegs:$src1, DFPRegs:$src2))]>; -def FSMULD : F3_3<2, 0b110100, 0b001101001, - (ops DFPRegs:$dst, FPRegs:$src1, FPRegs:$src2), - "fsmuld $src1, $src2, $dst", - [(set DFPRegs:$dst, (fmul (fextend FPRegs:$src1), - (fextend FPRegs:$src2)))]>; -def FDIVS : F3_3<2, 0b110100, 0b001001101, - (ops FPRegs:$dst, FPRegs:$src1, FPRegs:$src2), - "fdivs $src1, $src2, $dst", - [(set FPRegs:$dst, (fdiv FPRegs:$src1, FPRegs:$src2))]>; -def FDIVD : F3_3<2, 0b110100, 0b001001110, - (ops DFPRegs:$dst, DFPRegs:$src1, DFPRegs:$src2), - "fdivd $src1, $src2, $dst", - [(set DFPRegs:$dst, (fdiv DFPRegs:$src1, DFPRegs:$src2))]>; - -// Floating-point Compare Instructions, p. 148 -// Note: the 2nd template arg is different for these guys. -// Note 2: the result of a FCMP is not available until the 2nd cycle -// after the instr is retired, but there is no interlock. This behavior -// is modelled with a forced noop after the instruction. -def FCMPS : F3_3<2, 0b110101, 0b001010001, - (ops FPRegs:$src1, FPRegs:$src2), - "fcmps $src1, $src2\n\tnop", - [(set FCC, (V8cmpfcc FPRegs:$src1, FPRegs:$src2))]>; -def FCMPD : F3_3<2, 0b110101, 0b001010010, - (ops DFPRegs:$src1, DFPRegs:$src2), - "fcmpd $src1, $src2\n\tnop", - [(set FCC, (V8cmpfcc DFPRegs:$src1, DFPRegs:$src2))]>; - - -//===----------------------------------------------------------------------===// -// V9 Instructions -//===----------------------------------------------------------------------===// - -// V9 Conditional Moves. -let Predicates = [HasV9], isTwoAddress = 1 in { - // Move Integer Register on Condition (MOVcc) p. 194 of the V9 manual. - // FIXME: Add instruction encodings for the JIT some day. - def MOVICCrr - : Pseudo<(ops IntRegs:$dst, IntRegs:$T, IntRegs:$F, V8CC:$cc), - "mov$cc %icc, $F, $dst", - [(set IntRegs:$dst, - (V8selecticc IntRegs:$F, IntRegs:$T, imm:$cc, ICC))]>; - def MOVICCri - : Pseudo<(ops IntRegs:$dst, IntRegs:$T, i32imm:$F, V8CC:$cc), - "mov$cc %icc, $F, $dst", - [(set IntRegs:$dst, - (V8selecticc simm11:$F, IntRegs:$T, imm:$cc, ICC))]>; - - def MOVFCCrr - : Pseudo<(ops IntRegs:$dst, IntRegs:$T, IntRegs:$F, V8CC:$cc), - "mov$cc %fcc0, $F, $dst", - [(set IntRegs:$dst, - (V8selectfcc IntRegs:$F, IntRegs:$T, imm:$cc, FCC))]>; - def MOVFCCri - : Pseudo<(ops IntRegs:$dst, IntRegs:$T, i32imm:$F, V8CC:$cc), - "mov$cc %fcc0, $F, $dst", - [(set IntRegs:$dst, - (V8selectfcc simm11:$F, IntRegs:$T, imm:$cc, FCC))]>; - - def FMOVS_ICC - : Pseudo<(ops FPRegs:$dst, FPRegs:$T, FPRegs:$F, V8CC:$cc), - "fmovs$cc %icc, $F, $dst", - [(set FPRegs:$dst, - (V8selecticc FPRegs:$F, FPRegs:$T, imm:$cc, ICC))]>; - def FMOVD_ICC - : Pseudo<(ops DFPRegs:$dst, DFPRegs:$T, DFPRegs:$F, V8CC:$cc), - "fmovd$cc %icc, $F, $dst", - [(set DFPRegs:$dst, - (V8selecticc DFPRegs:$F, DFPRegs:$T, imm:$cc, ICC))]>; - def FMOVS_FCC - : Pseudo<(ops FPRegs:$dst, FPRegs:$T, FPRegs:$F, V8CC:$cc), - "fmovs$cc %fcc0, $F, $dst", - [(set FPRegs:$dst, - (V8selectfcc FPRegs:$F, FPRegs:$T, imm:$cc, FCC))]>; - def FMOVD_FCC - : Pseudo<(ops DFPRegs:$dst, DFPRegs:$T, DFPRegs:$F, V8CC:$cc), - "fmovd$cc %fcc0, $F, $dst", - [(set DFPRegs:$dst, - (V8selectfcc DFPRegs:$F, DFPRegs:$T, imm:$cc, FCC))]>; - -} - -// Floating-Point Move Instructions, p. 164 of the V9 manual. -let Predicates = [HasV9] in { - def FMOVD : F3_3<2, 0b110100, 0b000000010, - (ops DFPRegs:$dst, DFPRegs:$src), - "fmovd $src, $dst", []>; - def FNEGD : F3_3<2, 0b110100, 0b000000110, - (ops DFPRegs:$dst, DFPRegs:$src), - "fnegd $src, $dst", - [(set DFPRegs:$dst, (fneg DFPRegs:$src))]>; - def FABSD : F3_3<2, 0b110100, 0b000001010, - (ops DFPRegs:$dst, DFPRegs:$src), - "fabsd $src, $dst", - [(set DFPRegs:$dst, (fabs DFPRegs:$src))]>; -} - -// POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear -// the top 32-bits before using it. To do this clearing, we use a SLLri X,0. -def POPCrr : F3_1<2, 0b101110, - (ops IntRegs:$dst, IntRegs:$src), - "popc $src, $dst", []>, Requires<[HasV9]>; -def : Pat<(ctpop IntRegs:$src), - (POPCrr (SLLri IntRegs:$src, 0))>; - -//===----------------------------------------------------------------------===// -// Non-Instruction Patterns -//===----------------------------------------------------------------------===// - -// Small immediates. -def : Pat<(i32 simm13:$val), - (ORri G0, imm:$val)>; -// Arbitrary immediates. -def : Pat<(i32 imm:$val), - (ORri (SETHIi (HI22 imm:$val)), (LO10 imm:$val))>; - -// Global addresses, constant pool entries -def : Pat<(V8hi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>; -def : Pat<(V8lo tglobaladdr:$in), (ORri G0, tglobaladdr:$in)>; -def : Pat<(V8hi tconstpool:$in), (SETHIi tconstpool:$in)>; -def : Pat<(V8lo tconstpool:$in), (ORri G0, tconstpool:$in)>; - -// Add reg, lo. This is used when taking the addr of a global/constpool entry. -def : Pat<(add IntRegs:$r, (V8lo tglobaladdr:$in)), - (ADDri IntRegs:$r, tglobaladdr:$in)>; -def : Pat<(add IntRegs:$r, (V8lo tconstpool:$in)), - (ADDri IntRegs:$r, tconstpool:$in)>; - - -// Calls: -def : Pat<(call tglobaladdr:$dst), - (CALL tglobaladdr:$dst)>; -def : Pat<(call externalsym:$dst), - (CALL externalsym:$dst)>; - -def : Pat<(ret), (RETL)>; - -// Map integer extload's to zextloads. -def : Pat<(i32 (extload ADDRrr:$src, i1)), (LDUBrr ADDRrr:$src)>; -def : Pat<(i32 (extload ADDRri:$src, i1)), (LDUBri ADDRri:$src)>; -def : Pat<(i32 (extload ADDRrr:$src, i8)), (LDUBrr ADDRrr:$src)>; -def : Pat<(i32 (extload ADDRri:$src, i8)), (LDUBri ADDRri:$src)>; -def : Pat<(i32 (extload ADDRrr:$src, i16)), (LDUHrr ADDRrr:$src)>; -def : Pat<(i32 (extload ADDRri:$src, i16)), (LDUHri ADDRri:$src)>; - -// zextload bool -> zextload byte -def : Pat<(i32 (zextload ADDRrr:$src, i1)), (LDUBrr ADDRrr:$src)>; -def : Pat<(i32 (zextload ADDRri:$src, i1)), (LDUBri ADDRri:$src)>; - -// truncstore bool -> truncstore byte. -def : Pat<(truncstore IntRegs:$src, ADDRrr:$addr, i1), - (STBrr ADDRrr:$addr, IntRegs:$src)>; -def : Pat<(truncstore IntRegs:$src, ADDRri:$addr, i1), - (STBri ADDRri:$addr, IntRegs:$src)>; diff --git a/lib/Target/SparcV8/SparcV8RegisterInfo.cpp b/lib/Target/SparcV8/SparcV8RegisterInfo.cpp deleted file mode 100644 index a76111ab254..00000000000 --- a/lib/Target/SparcV8/SparcV8RegisterInfo.cpp +++ /dev/null @@ -1,203 +0,0 @@ -//===- SparcV8RegisterInfo.cpp - SparcV8 Register Information ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the SparcV8 implementation of the MRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#include "SparcV8.h" -#include "SparcV8RegisterInfo.h" -#include "SparcV8Subtarget.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/Type.h" -#include "llvm/ADT/STLExtras.h" -#include -using namespace llvm; - -SparcV8RegisterInfo::SparcV8RegisterInfo(SparcV8Subtarget &st) - : SparcV8GenRegisterInfo(V8::ADJCALLSTACKDOWN, - V8::ADJCALLSTACKUP), Subtarget(st) { -} - -void SparcV8RegisterInfo:: -storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned SrcReg, int FI, - const TargetRegisterClass *RC) const { - // On the order of operands here: think "[FrameIdx + 0] = SrcReg". - if (RC == V8::IntRegsRegisterClass) - BuildMI(MBB, I, V8::STri, 3).addFrameIndex(FI).addImm(0).addReg(SrcReg); - else if (RC == V8::FPRegsRegisterClass) - BuildMI(MBB, I, V8::STFri, 3).addFrameIndex(FI).addImm(0).addReg(SrcReg); - else if (RC == V8::DFPRegsRegisterClass) - BuildMI(MBB, I, V8::STDFri, 3).addFrameIndex(FI).addImm(0).addReg(SrcReg); - else - assert(0 && "Can't store this register to stack slot"); -} - -void SparcV8RegisterInfo:: -loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - unsigned DestReg, int FI, - const TargetRegisterClass *RC) const { - if (RC == V8::IntRegsRegisterClass) - BuildMI(MBB, I, V8::LDri, 2, DestReg).addFrameIndex(FI).addImm(0); - else if (RC == V8::FPRegsRegisterClass) - BuildMI(MBB, I, V8::LDFri, 2, DestReg).addFrameIndex(FI).addImm (0); - else if (RC == V8::DFPRegsRegisterClass) - BuildMI(MBB, I, V8::LDDFri, 2, DestReg).addFrameIndex(FI).addImm(0); - else - assert(0 && "Can't load this register from stack slot"); -} - -void SparcV8RegisterInfo::copyRegToReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned DestReg, unsigned SrcReg, - const TargetRegisterClass *RC) const { - if (RC == V8::IntRegsRegisterClass) - BuildMI(MBB, I, V8::ORrr, 2, DestReg).addReg(V8::G0).addReg(SrcReg); - else if (RC == V8::FPRegsRegisterClass) - BuildMI(MBB, I, V8::FMOVS, 1, DestReg).addReg(SrcReg); - else if (RC == V8::DFPRegsRegisterClass) - BuildMI(MBB, I, Subtarget.isV9() ? V8::FMOVD : V8::FpMOVD, - 1, DestReg).addReg(SrcReg); - else - assert (0 && "Can't copy this register"); -} - -MachineInstr *SparcV8RegisterInfo::foldMemoryOperand(MachineInstr* MI, - unsigned OpNum, - int FI) const { - bool isFloat = false; - switch (MI->getOpcode()) { - case V8::ORrr: - if (MI->getOperand(1).isRegister() && MI->getOperand(1).getReg() == V8::G0&& - MI->getOperand(0).isRegister() && MI->getOperand(2).isRegister()) { - if (OpNum == 0) // COPY -> STORE - return BuildMI(V8::STri, 3).addFrameIndex(FI).addImm(0) - .addReg(MI->getOperand(2).getReg()); - else // COPY -> LOAD - return BuildMI(V8::LDri, 2, MI->getOperand(0).getReg()) - .addFrameIndex(FI).addImm(0); - } - break; - case V8::FMOVS: - isFloat = true; - // FALLTHROUGH - case V8::FMOVD: - if (OpNum == 0) // COPY -> STORE - return BuildMI(isFloat ? V8::STFri : V8::STDFri, 3) - .addFrameIndex(FI).addImm(0).addReg(MI->getOperand(1).getReg()); - else // COPY -> LOAD - return BuildMI(isFloat ? V8::LDFri : V8::LDDFri, 2, - MI->getOperand(0).getReg()).addFrameIndex(FI).addImm(0); - break; - } - return 0; -} - -void SparcV8RegisterInfo:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - MachineInstr &MI = *I; - int Size = MI.getOperand(0).getImmedValue(); - if (MI.getOpcode() == V8::ADJCALLSTACKDOWN) - Size = -Size; - if (Size) - BuildMI(MBB, I, V8::ADDri, 2, V8::O6).addReg(V8::O6).addSImm(Size); - MBB.erase(I); -} - -void -SparcV8RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const { - unsigned i = 0; - MachineInstr &MI = *II; - while (!MI.getOperand(i).isFrameIndex()) { - ++i; - assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); - } - - int FrameIndex = MI.getOperand(i).getFrameIndex(); - - // Addressable stack objects are accessed using neg. offsets from %fp - MachineFunction &MF = *MI.getParent()->getParent(); - int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + - MI.getOperand(i+1).getImmedValue(); - - // Replace frame index with a frame pointer reference. - if (Offset >= -4096 && Offset <= 4095) { - // If the offset is small enough to fit in the immediate field, directly - // encode it. - MI.SetMachineOperandReg(i, V8::I6); - MI.SetMachineOperandConst(i+1, MachineOperand::MO_SignExtendedImmed,Offset); - } else { - // Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to - // scavenge a register here instead of reserving G1 all of the time. - unsigned OffHi = (unsigned)Offset >> 10U; - BuildMI(*MI.getParent(), II, V8::SETHIi, 1, V8::G1).addImm(OffHi); - // Emit G1 = G1 + I6 - BuildMI(*MI.getParent(), II, V8::ADDrr, 2, - V8::G1).addReg(V8::G1).addReg(V8::I6); - // Insert: G1+%lo(offset) into the user. - MI.SetMachineOperandReg(i, V8::G1); - MI.SetMachineOperandConst(i+1, MachineOperand::MO_SignExtendedImmed, - Offset & ((1 << 10)-1)); - } -} - -void SparcV8RegisterInfo:: -processFunctionBeforeFrameFinalized(MachineFunction &MF) const {} - -void SparcV8RegisterInfo::emitPrologue(MachineFunction &MF) const { - MachineBasicBlock &MBB = MF.front(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - - // Get the number of bytes to allocate from the FrameInfo - int NumBytes = (int) MFI->getStackSize(); - - // Emit the correct save instruction based on the number of bytes in - // the frame. Minimum stack frame size according to V8 ABI is: - // 16 words for register window spill - // 1 word for address of returned aggregate-value - // + 6 words for passing parameters on the stack - // ---------- - // 23 words * 4 bytes per word = 92 bytes - NumBytes += 92; - // Round up to next doubleword boundary -- a double-word boundary - // is required by the ABI. - NumBytes = (NumBytes + 7) & ~7; - NumBytes = -NumBytes; - - if (NumBytes >= -4096) { - BuildMI(MBB, MBB.begin(), V8::SAVEri, 2, - V8::O6).addImm(NumBytes).addReg(V8::O6); - } else { - MachineBasicBlock::iterator InsertPt = MBB.begin(); - // Emit this the hard way. This clobbers G1 which we always know is - // available here. - unsigned OffHi = (unsigned)NumBytes >> 10U; - BuildMI(MBB, InsertPt, V8::SETHIi, 1, V8::G1).addImm(OffHi); - // Emit G1 = G1 + I6 - BuildMI(MBB, InsertPt, V8::ORri, 2, V8::G1) - .addReg(V8::G1).addImm(NumBytes & ((1 << 10)-1)); - BuildMI(MBB, InsertPt, V8::SAVErr, 2, - V8::O6).addReg(V8::O6).addReg(V8::G1); - } -} - -void SparcV8RegisterInfo::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = prior(MBB.end()); - assert(MBBI->getOpcode() == V8::RETL && - "Can only put epilog before 'retl' instruction!"); - BuildMI(MBB, MBBI, V8::RESTORErr, 2, V8::G0).addReg(V8::G0).addReg(V8::G0); -} - -#include "SparcV8GenRegisterInfo.inc" - diff --git a/lib/Target/SparcV8/SparcV8RegisterInfo.h b/lib/Target/SparcV8/SparcV8RegisterInfo.h deleted file mode 100644 index f739551f869..00000000000 --- a/lib/Target/SparcV8/SparcV8RegisterInfo.h +++ /dev/null @@ -1,63 +0,0 @@ -//===- SparcV8RegisterInfo.h - SparcV8 Register Information Impl -*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the SparcV8 implementation of the MRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef SPARCV8REGISTERINFO_H -#define SPARCV8REGISTERINFO_H - -#include "llvm/Target/MRegisterInfo.h" -#include "SparcV8GenRegisterInfo.h.inc" - -namespace llvm { - -class SparcV8Subtarget; -class Type; - -struct SparcV8RegisterInfo : public SparcV8GenRegisterInfo { - SparcV8Subtarget &Subtarget; - - SparcV8RegisterInfo(SparcV8Subtarget &st); - - /// Code Generation virtual methods... - void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned SrcReg, int FrameIndex, - const TargetRegisterClass *RC) const; - - void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC) const; - - void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - unsigned DestReg, unsigned SrcReg, - const TargetRegisterClass *RC) const; - - virtual MachineInstr* foldMemoryOperand(MachineInstr* MI, - unsigned OpNum, - int FrameIndex) const; - - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; - - void eliminateFrameIndex(MachineBasicBlock::iterator II) const; - - void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; - - void emitPrologue(MachineFunction &MF) const; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; -}; - -} // end namespace llvm - -#endif diff --git a/lib/Target/SparcV8/SparcV8RegisterInfo.td b/lib/Target/SparcV8/SparcV8RegisterInfo.td deleted file mode 100644 index 07012b1626f..00000000000 --- a/lib/Target/SparcV8/SparcV8RegisterInfo.td +++ /dev/null @@ -1,118 +0,0 @@ -//===- SparcV8RegisterInfo.td - SparcV8 Register defs ------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Declarations that describe the SparcV8 register file -//===----------------------------------------------------------------------===// - -class SparcReg : Register { - field bits<5> Num; - let Namespace = "V8"; -} - -// Registers are identified with 5-bit ID numbers. -// Ri - 32-bit integer registers -class Ri num, string n> : SparcReg { - let Num = num; -} -// Rf - 32-bit floating-point registers -class Rf num, string n> : SparcReg { - let Num = num; -} -// Rd - Slots in the FP register file for 64-bit floating-point values. -class Rd num, string n, list aliases> : SparcReg { - let Num = num; - let Aliases = aliases; -} - -// Integer registers -def G0 : Ri< 0, "G0">; def G1 : Ri< 1, "G1">; def G2 : Ri< 2, "G2">; -def G3 : Ri< 3, "G3">; def G4 : Ri< 4, "G4">; def G5 : Ri< 5, "G5">; -def G6 : Ri< 6, "G6">; def G7 : Ri< 7, "G7">; -def O0 : Ri< 8, "O0">; def O1 : Ri< 9, "O1">; def O2 : Ri<10, "O2">; -def O3 : Ri<11, "O3">; def O4 : Ri<12, "O4">; def O5 : Ri<13, "O5">; -def O6 : Ri<14, "O6">; def O7 : Ri<15, "O7">; -def L0 : Ri<16, "L0">; def L1 : Ri<17, "L1">; def L2 : Ri<18, "L2">; -def L3 : Ri<19, "L3">; def L4 : Ri<20, "L4">; def L5 : Ri<21, "L5">; -def L6 : Ri<22, "L6">; def L7 : Ri<23, "L7">; -def I0 : Ri<24, "I0">; def I1 : Ri<25, "I1">; def I2 : Ri<26, "I2">; -def I3 : Ri<27, "I3">; def I4 : Ri<28, "I4">; def I5 : Ri<29, "I5">; -def I6 : Ri<30, "I6">; def I7 : Ri<31, "I7">; - -// Floating-point registers -def F0 : Rf< 0, "F0">; def F1 : Rf< 1, "F1">; def F2 : Rf< 2, "F2">; -def F3 : Rf< 3, "F3">; def F4 : Rf< 4, "F4">; def F5 : Rf< 5, "F5">; -def F6 : Rf< 6, "F6">; def F7 : Rf< 7, "F7">; def F8 : Rf< 8, "F8">; -def F9 : Rf< 9, "F9">; def F10 : Rf<10, "F10">; def F11 : Rf<11, "F11">; -def F12 : Rf<12, "F12">; def F13 : Rf<13, "F13">; def F14 : Rf<14, "F14">; -def F15 : Rf<15, "F15">; def F16 : Rf<16, "F16">; def F17 : Rf<17, "F17">; -def F18 : Rf<18, "F18">; def F19 : Rf<19, "F19">; def F20 : Rf<20, "F20">; -def F21 : Rf<21, "F21">; def F22 : Rf<22, "F22">; def F23 : Rf<23, "F23">; -def F24 : Rf<24, "F24">; def F25 : Rf<25, "F25">; def F26 : Rf<26, "F26">; -def F27 : Rf<27, "F27">; def F28 : Rf<28, "F28">; def F29 : Rf<29, "F29">; -def F30 : Rf<30, "F30">; def F31 : Rf<31, "F31">; - -// Aliases of the F* registers used to hold 64-bit fp values (doubles) -def D0 : Rd< 0, "F0", [F0, F1]>; def D1 : Rd< 2, "F2", [F2, F3]>; -def D2 : Rd< 4, "F4", [F4, F5]>; def D3 : Rd< 6, "F6", [F6, F7]>; -def D4 : Rd< 8, "F8", [F8, F9]>; def D5 : Rd<10, "F10", [F10, F11]>; -def D6 : Rd<12, "F12", [F12, F13]>; def D7 : Rd<14, "F14", [F14, F15]>; -def D8 : Rd<16, "F16", [F16, F17]>; def D9 : Rd<18, "F18", [F18, F19]>; -def D10 : Rd<20, "F20", [F20, F21]>; def D11 : Rd<22, "F22", [F22, F23]>; -def D12 : Rd<24, "F24", [F24, F25]>; def D13 : Rd<26, "F26", [F26, F27]>; -def D14 : Rd<28, "F28", [F28, F29]>; def D15 : Rd<30, "F30", [F30, F31]>; - -/// Integer and FP Condition codes. -let Namespace = "V8" in { - def ICC : Register<"ICC">; - def FCC : Register<"FCC">; -} -def FLAGS_REGS : RegisterClass<"V8", [FlagVT], 32, [ICC, FCC]> { - let Size = 32; -} - -// Register classes. -// -// FIXME: the register order should be defined in terms of the preferred -// allocation order... -// -def IntRegs : RegisterClass<"V8", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7, - I0, I1, I2, I3, I4, I5, - O0, O1, O2, O3, O4, O5, O7, - - // FIXME: G1 reserved for now for large imm generation by frame code. - G1, - // Non-allocatable regs: - G2, G3, G4, // FIXME: OK for use only in - // applications, not libraries. - O6, // stack ptr - I6, // frame ptr - I7, // return address - G0, // constant zero - G5, G6, G7 // reserved for kernel - ]> { - let MethodProtos = [{ - iterator allocation_order_end(MachineFunction &MF) const; - }]; - let MethodBodies = [{ - IntRegsClass::iterator - IntRegsClass::allocation_order_end(MachineFunction &MF) const { - // FIXME: These special regs should be taken out of the regclass! - return end()-10 // Don't allocate special registers - -1; // FIXME: G1 reserved for large imm generation by frame code. - } - }]; -} - -def FPRegs : RegisterClass<"V8", [f32], 32, [F0, F1, F2, F3, F4, F5, F6, F7, F8, - F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, - F23, F24, F25, F26, F27, F28, F29, F30, F31]>; - -def DFPRegs : RegisterClass<"V8", [f64], 64, [D0, D1, D2, D3, D4, D5, D6, D7, - D8, D9, D10, D11, D12, D13, D14, D15]>; diff --git a/lib/Target/SparcV8/SparcV8Subtarget.cpp b/lib/Target/SparcV8/SparcV8Subtarget.cpp deleted file mode 100644 index 46ea7d42848..00000000000 --- a/lib/Target/SparcV8/SparcV8Subtarget.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===- SparcV8Subtarget.cpp - SPARC Subtarget Information -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the SPARC specific subclass of TargetSubtarget. -// -//===----------------------------------------------------------------------===// - -#include "SparcV8Subtarget.h" -#include "SparcV8GenSubtarget.inc" -using namespace llvm; - -// FIXME: temporary. -#include "llvm/Support/CommandLine.h" -namespace { - cl::opt EnableV9("enable-sparc-v9-insts", cl::Hidden, - cl::desc("Enable V9 instructions in the V8 target")); -} - -SparcV8Subtarget::SparcV8Subtarget(const Module &M, const std::string &FS) { - // Set the default features. - IsV9 = false; - V8DeprecatedInsts = false; - IsVIS = false; - - // Determine default and user specified characteristics - std::string CPU = "generic"; - - // FIXME: autodetect host here! - CPU = "v9"; // What is a good way to detect V9? - - // Parse features string. - ParseSubtargetFeatures(FS, CPU); - - // Unless explicitly enabled, disable the V9 instructions. - if (!EnableV9) - IsV9 = false; -}; diff --git a/lib/Target/SparcV8/SparcV8Subtarget.h b/lib/Target/SparcV8/SparcV8Subtarget.h deleted file mode 100644 index 615d3d4fbc5..00000000000 --- a/lib/Target/SparcV8/SparcV8Subtarget.h +++ /dev/null @@ -1,42 +0,0 @@ -//=====-- SparcV8Subtarget.h - Define Subtarget for the SPARC -*- C++ -*--====// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Chris Lattner and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the SPARC specific subclass of TargetSubtarget. -// -//===----------------------------------------------------------------------===// - -#ifndef SPARC_SUBTARGET_H -#define SPARC_SUBTARGET_H - -#include "llvm/Target/TargetSubtarget.h" -#include - -namespace llvm { - class Module; - -class SparcV8Subtarget : public TargetSubtarget { - bool IsV9; - bool V8DeprecatedInsts; - bool IsVIS; -public: - SparcV8Subtarget(const Module &M, const std::string &FS); - - bool isV9() const { return IsV9; } - bool isVIS() const { return IsVIS; } - bool useDeprecatedV8Instructions() const { return V8DeprecatedInsts; } - - /// ParseSubtargetFeatures - Parses features string setting specified - /// subtarget options. Definition of function is auto generated by tblgen. - void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); - -}; - -} // end namespace llvm - -#endif diff --git a/lib/Target/SparcV8/SparcV8TargetMachine.cpp b/lib/Target/SparcV8/SparcV8TargetMachine.cpp deleted file mode 100644 index d868c10042f..00000000000 --- a/lib/Target/SparcV8/SparcV8TargetMachine.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//===-- SparcV8TargetMachine.cpp - Define TargetMachine for SparcV8 -------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -#include "SparcV8TargetMachine.h" -#include "SparcV8.h" -#include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetMachineRegistry.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Support/CommandLine.h" -#include -using namespace llvm; - -namespace { - // Register the target. - RegisterTarget X("sparcv8"," SPARC V8 (experimental)"); -} - -/// SparcV8TargetMachine ctor - Create an ILP32 architecture model -/// -SparcV8TargetMachine::SparcV8TargetMachine(const Module &M, - IntrinsicLowering *IL, - const std::string &FS) - : TargetMachine("SparcV8", IL, false, 4, 4), - Subtarget(M, FS), InstrInfo(Subtarget), - FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) { -} - -unsigned SparcV8TargetMachine::getModuleMatchQuality(const Module &M) { - std::string TT = M.getTargetTriple(); - if (TT.size() >= 6 && std::string(TT.begin(), TT.begin()+6) == "sparc-") - return 20; - - if (M.getEndianness() == Module::BigEndian && - M.getPointerSize() == Module::Pointer32) -#ifdef __sparc__ - return 20; // BE/32 ==> Prefer sparcv8 on sparc -#else - return 5; // BE/32 ==> Prefer ppc elsewhere -#endif - else if (M.getEndianness() != Module::AnyEndianness || - M.getPointerSize() != Module::AnyPointerSize) - return 0; // Match for some other target - - return 0; -} - -/// addPassesToEmitFile - Add passes to the specified pass manager -/// to implement a static compiler for this target. -/// -bool SparcV8TargetMachine::addPassesToEmitFile(PassManager &PM, - std::ostream &Out, - CodeGenFileType FileType, - bool Fast) { - if (FileType != TargetMachine::AssemblyFile) return true; - - // FIXME: Implement efficient support for garbage collection intrinsics. - PM.add(createLowerGCPass()); - - // FIXME: implement the invoke/unwind instructions! - PM.add(createLowerInvokePass()); - - // FIXME: implement the switch instruction in the instruction selector. - PM.add(createLowerSwitchPass()); - - // Print LLVM code input to instruction selector: - if (PrintMachineCode) - PM.add(new PrintFunctionPass()); - - // Make sure that no unreachable blocks are instruction selected. - PM.add(createUnreachableBlockEliminationPass()); - - PM.add(createSparcV8ISelDag(*this)); - - // Print machine instructions as they were initially generated. - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(&std::cerr)); - - PM.add(createRegisterAllocator()); - PM.add(createPrologEpilogCodeInserter()); - - // Print machine instructions after register allocation and prolog/epilog - // insertion. - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(&std::cerr)); - - PM.add(createSparcV8FPMoverPass(*this)); - - PM.add(createSparcV8DelaySlotFillerPass(*this)); - - // Print machine instructions after filling delay slots. - if (PrintMachineCode) - PM.add(createMachineFunctionPrinterPass(&std::cerr)); - - // Output assembly language. - PM.add(createSparcV8CodePrinterPass(Out, *this)); - - // Delete the MachineInstrs we generated, since they're no longer needed. - PM.add(createMachineCodeDeleter()); - return false; -} - diff --git a/lib/Target/SparcV8/SparcV8TargetMachine.h b/lib/Target/SparcV8/SparcV8TargetMachine.h deleted file mode 100644 index 09777442b5a..00000000000 --- a/lib/Target/SparcV8/SparcV8TargetMachine.h +++ /dev/null @@ -1,51 +0,0 @@ -//===-- SparcV8TargetMachine.h - Define TargetMachine for SparcV8 -*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the SparcV8 specific subclass of TargetMachine. -// -//===----------------------------------------------------------------------===// - -#ifndef SPARCV8TARGETMACHINE_H -#define SPARCV8TARGETMACHINE_H - -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetFrameInfo.h" -#include "llvm/PassManager.h" -#include "SparcV8InstrInfo.h" -#include "SparcV8Subtarget.h" - -namespace llvm { - -class IntrinsicLowering; -class Module; - -class SparcV8TargetMachine : public TargetMachine { - SparcV8Subtarget Subtarget; - SparcV8InstrInfo InstrInfo; - TargetFrameInfo FrameInfo; -public: - SparcV8TargetMachine(const Module &M, IntrinsicLowering *IL, - const std::string &FS); - - virtual const SparcV8InstrInfo *getInstrInfo() const { return &InstrInfo; } - virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; } - virtual const TargetSubtarget *getSubtargetImpl() const{ return &Subtarget; } - virtual const MRegisterInfo *getRegisterInfo() const { - return &InstrInfo.getRegisterInfo(); - } - - static unsigned getModuleMatchQuality(const Module &M); - - virtual bool addPassesToEmitFile(PassManager &PM, std::ostream &Out, - CodeGenFileType FileType, bool Fast); -}; - -} // end namespace llvm - -#endif -- 2.34.1