mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-17 21:35:07 +00:00
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
This commit is contained in:
parent
e7c839ed5a
commit
c6aaf5acf9
@ -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;
|
||||
}
|
@ -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 <iostream>
|
||||
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<SparcV8Subtarget>().isV9())
|
||||
return false;
|
||||
|
||||
bool Changed = false;
|
||||
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
|
||||
FI != FE; ++FI)
|
||||
Changed |= runOnMachineBasicBlock(*FI);
|
||||
return Changed;
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <iosfwd>
|
||||
#include <cassert>
|
||||
|
||||
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
|
@ -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<string Name, list<SubtargetFeature> Features>
|
||||
: Processor<Name, NoItineraries, Features>;
|
||||
|
||||
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;
|
||||
}
|
@ -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 <cctype>
|
||||
#include <iostream>
|
||||
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<const Value *, unsigned> 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 << "<unknown operand type>"; 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
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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<dag ops, string asmstr, list<dag> 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<dag ops, string asmstr, list<dag> pattern>
|
||||
: InstV8<ops, asmstr, pattern> {
|
||||
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<bits<3> op2Val, dag ops, string asmstr, list<dag> pattern>
|
||||
: F2<ops, asmstr, pattern> {
|
||||
bits<5> rd;
|
||||
|
||||
let op2 = op2Val;
|
||||
|
||||
let Inst{29-25} = rd;
|
||||
}
|
||||
|
||||
class F2_2<bits<4> condVal, bits<3> op2Val, dag ops, string asmstr,
|
||||
list<dag> pattern> : F2<ops, asmstr, pattern> {
|
||||
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<dag ops, string asmstr, list<dag> pattern>
|
||||
: InstV8<ops, asmstr, pattern> {
|
||||
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<bits<2> opVal, bits<6> op3val, dag ops,
|
||||
string asmstr, list<dag> pattern> : F3<ops, asmstr, pattern> {
|
||||
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<bits<2> opVal, bits<6> op3val, dag ops,
|
||||
string asmstr, list<dag> pattern> : F3<ops, asmstr, pattern> {
|
||||
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<bits<2> opVal, bits<6> op3val, bits<9> opfval, dag ops,
|
||||
string asmstr, list<dag> pattern> : F3<ops, asmstr, pattern> {
|
||||
bits<5> rs2;
|
||||
|
||||
let op = opVal;
|
||||
let op3 = op3val;
|
||||
|
||||
let Inst{13-5} = opfval; // fp opcode
|
||||
let Inst{4-0} = rs2;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -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 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((unsigned)N->getValue() & 1023, MVT::i32);
|
||||
}]>;
|
||||
|
||||
def HI22 : SDNodeXForm<imm, [{
|
||||
// Transformation function: shift the immediate value down into the low bits.
|
||||
return CurDAG->getTargetConstant((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<i32, 2, "SelectADDRrr", []>;
|
||||
def ADDRri : ComplexPattern<i32, 2, "SelectADDRri", []>;
|
||||
|
||||
// Address operands
|
||||
def MEMrr : Operand<i32> {
|
||||
let PrintMethod = "printMemOperand";
|
||||
let NumMIOperands = 2;
|
||||
let MIOperandInfo = (ops IntRegs, IntRegs);
|
||||
}
|
||||
def MEMri : Operand<i32> {
|
||||
let PrintMethod = "printMemOperand";
|
||||
let NumMIOperands = 2;
|
||||
let MIOperandInfo = (ops IntRegs, i32imm);
|
||||
}
|
||||
|
||||
// Branch targets have OtherVT type.
|
||||
def brtarget : Operand<OtherVT>;
|
||||
def calltarget : Operand<i32>;
|
||||
|
||||
// Operand for printing out a condition code.
|
||||
let PrintMethod = "printV8CCOperand" in
|
||||
def V8CC : Operand<i32>;
|
||||
|
||||
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<int N> : 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<int N> : 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<dag ops, string asmstr, list<dag> pattern>
|
||||
: InstV8<ops, asmstr, pattern>;
|
||||
|
||||
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<bits<4> cc, dag ops, string asmstr, list<dag> pattern>
|
||||
: F2_2<cc, 0b010, ops, asmstr, pattern> {
|
||||
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<bits<4> cc, dag ops, string asmstr, list<dag> pattern>
|
||||
: F2_2<cc, 0b110, ops, asmstr, pattern> {
|
||||
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)>;
|
@ -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 <iostream>
|
||||
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"
|
||||
|
@ -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
|
@ -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<string n> : Register<n> {
|
||||
field bits<5> Num;
|
||||
let Namespace = "V8";
|
||||
}
|
||||
|
||||
// Registers are identified with 5-bit ID numbers.
|
||||
// Ri - 32-bit integer registers
|
||||
class Ri<bits<5> num, string n> : SparcReg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
// Rf - 32-bit floating-point registers
|
||||
class Rf<bits<5> num, string n> : SparcReg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
// Rd - Slots in the FP register file for 64-bit floating-point values.
|
||||
class Rd<bits<5> num, string n, list<Register> aliases> : SparcReg<n> {
|
||||
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]>;
|
@ -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<bool> 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;
|
||||
};
|
@ -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 <string>
|
||||
|
||||
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
|
@ -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 <iostream>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
// Register the target.
|
||||
RegisterTarget<SparcV8TargetMachine> 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;
|
||||
}
|
||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user