aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/SparcV9/SparcV9CodeEmitter.cpp63
-rw-r--r--lib/Target/SparcV9/SparcV9FrameInfo.cpp65
-rw-r--r--lib/Target/SparcV9/SparcV9FrameInfo.h174
-rw-r--r--lib/Target/SparcV9/SparcV9InstrInfo.cpp43
-rw-r--r--lib/Target/SparcV9/SparcV9InstrInfo.h201
-rw-r--r--lib/Target/SparcV9/SparcV9InstrSelection.cpp15
-rw-r--r--lib/Target/SparcV9/SparcV9Internals.h583
-rw-r--r--lib/Target/SparcV9/SparcV9RegClassInfo.cpp9
-rw-r--r--lib/Target/SparcV9/SparcV9RegInfo.cpp88
-rw-r--r--lib/Target/SparcV9/SparcV9RegInfo.h190
-rw-r--r--lib/Target/SparcV9/SparcV9SchedInfo.cpp6
-rw-r--r--lib/Target/SparcV9/SparcV9TargetMachine.cpp122
-rw-r--r--lib/Target/SparcV9/SparcV9TargetMachine.h59
13 files changed, 845 insertions, 773 deletions
diff --git a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp
index 9a51faa4cc..bb4bdaf8a4 100644
--- a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp
+++ b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp
@@ -35,6 +35,8 @@
#include "Support/hash_set"
#include "Support/Statistic.h"
#include "SparcInternals.h"
+#include "SparcTargetMachine.h"
+#include "SparcRegInfo.h"
#include "SparcV9CodeEmitter.h"
#include "Config/alloca.h"
@@ -46,8 +48,8 @@ namespace {
Statistic<> CallbackCalls("callback", "Number CompilationCallback() calls");
}
-bool UltraSparc::addPassesToEmitMachineCode(FunctionPassManager &PM,
- MachineCodeEmitter &MCE) {
+bool SparcTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
+ MachineCodeEmitter &MCE) {
MachineCodeEmitter *M = &MCE;
DEBUG(M = MachineCodeEmitter::createFilePrinterEmitter(MCE));
PM.add(new SparcV9CodeEmitter(*this, *M));
@@ -102,10 +104,10 @@ namespace {
private:
uint64_t emitStubForFunction(Function *F);
- static void SaveRegisters(uint64_t DoubleFP[], uint64_t &FSR,
- uint64_t &FPRS, uint64_t &CCR);
- static void RestoreRegisters(uint64_t DoubleFP[], uint64_t &FSR,
- uint64_t &FPRS, uint64_t &CCR);
+ static void SaveRegisters(uint64_t DoubleFP[], uint64_t CC[],
+ uint64_t Globals[]);
+ static void RestoreRegisters(uint64_t DoubleFP[], uint64_t CC[],
+ uint64_t Globals[]);
static void CompilationCallback();
uint64_t resolveFunctionReference(uint64_t RetAddr);
@@ -209,17 +211,20 @@ void JITResolver::insertFarJumpAtAddr(int64_t Target, uint64_t Addr) {
}
}
-void JITResolver::SaveRegisters(uint64_t DoubleFP[], uint64_t &FSR,
- uint64_t &FPRS, uint64_t &CCR) {
+void JITResolver::SaveRegisters(uint64_t DoubleFP[], uint64_t CC[],
+ uint64_t Globals[]) {
#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
-#if 0
__asm__ __volatile__ (// Save condition-code registers
"stx %%fsr, %0;\n\t"
"rd %%fprs, %1;\n\t"
"rd %%ccr, %2;\n\t"
- : "=m"(FSR), "=r"(FPRS), "=r"(CCR));
-#endif
+ : "=m"(CC[0]), "=r"(CC[1]), "=r"(CC[2]));
+
+ __asm__ __volatile__ (// Save globals g1 and g5
+ "stx %%g1, %0;\n\t"
+ "stx %%g5, %0;\n\t"
+ : "=m"(Globals[0]), "=m"(Globals[1]));
// GCC says: `asm' only allows up to thirty parameters!
__asm__ __volatile__ (// Save Single/Double FP registers, part 1
@@ -261,18 +266,21 @@ void JITResolver::SaveRegisters(uint64_t DoubleFP[], uint64_t &FSR,
}
-void JITResolver::RestoreRegisters(uint64_t DoubleFP[], uint64_t &FSR,
- uint64_t &FPRS, uint64_t &CCR)
+void JITResolver::RestoreRegisters(uint64_t DoubleFP[], uint64_t CC[],
+ uint64_t Globals[])
{
#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
-#if 0
__asm__ __volatile__ (// Restore condition-code registers
"ldx %0, %%fsr;\n\t"
"wr %1, 0, %%fprs;\n\t"
"wr %2, 0, %%ccr;\n\t"
- :: "m"(FSR), "r"(FPRS), "r"(CCR));
-#endif
+ :: "m"(CC[0]), "r"(CC[1]), "r"(CC[2]));
+
+ __asm__ __volatile__ (// Restore globals g1 and g5
+ "ldx %0, %%g1;\n\t"
+ "ldx %0, %%g5;\n\t"
+ :: "m"(Globals[0]), "m"(Globals[1]));
// GCC says: `asm' only allows up to thirty parameters!
__asm__ __volatile__ (// Restore Single/Double FP registers, part 1
@@ -314,11 +322,12 @@ void JITResolver::RestoreRegisters(uint64_t DoubleFP[], uint64_t &FSR,
}
void JITResolver::CompilationCallback() {
- // Local space to save double registers
+ // Local space to save the registers
uint64_t DoubleFP[32];
- uint64_t FSR, FPRS, CCR;
+ uint64_t CC[3];
+ uint64_t Globals[2];
- SaveRegisters(DoubleFP, FSR, FPRS, CCR);
+ SaveRegisters(DoubleFP, CC, Globals);
++CallbackCalls;
uint64_t CameFrom = (uint64_t)(intptr_t)__builtin_return_address(0);
@@ -394,7 +403,7 @@ void JITResolver::CompilationCallback() {
__asm__ __volatile__ ("sub %%i7, %0, %%i7" : : "r" (Offset+12));
#endif
- RestoreRegisters(DoubleFP, FSR, FPRS, CCR);
+ RestoreRegisters(DoubleFP, CC, Globals);
}
/// emitStubForFunction - This method is used by the JIT when it needs to emit
@@ -476,7 +485,7 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg,
fakeReg = RI.getClassRegNum(fakeReg, regClass);
switch (regClass) {
- case UltraSparcRegInfo::IntRegClassID: {
+ case SparcRegInfo::IntRegClassID: {
// Sparc manual, p31
static const unsigned IntRegMap[] = {
// "o0", "o1", "o2", "o3", "o4", "o5", "o7",
@@ -494,12 +503,12 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg,
return IntRegMap[fakeReg];
break;
}
- case UltraSparcRegInfo::FloatRegClassID: {
+ case SparcRegInfo::FloatRegClassID: {
DEBUG(std::cerr << "FP reg: " << fakeReg << "\n");
- if (regType == UltraSparcRegInfo::FPSingleRegType) {
+ if (regType == SparcRegInfo::FPSingleRegType) {
// only numbered 0-31, hence can already fit into 5 bits (and 6)
DEBUG(std::cerr << "FP single reg, returning: " << fakeReg << "\n");
- } else if (regType == UltraSparcRegInfo::FPDoubleRegType) {
+ } else if (regType == SparcRegInfo::FPDoubleRegType) {
// FIXME: This assumes that we only have 5-bit register fields!
// From Sparc Manual, page 40.
// The bit layout becomes: b[4], b[3], b[2], b[1], b[5]
@@ -509,7 +518,7 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg,
}
return fakeReg;
}
- case UltraSparcRegInfo::IntCCRegClassID: {
+ case SparcRegInfo::IntCCRegClassID: {
/* xcc, icc, ccr */
static const unsigned IntCCReg[] = { 6, 4, 2 };
@@ -518,7 +527,7 @@ SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg,
DEBUG(std::cerr << "IntCC reg: " << IntCCReg[fakeReg] << "\n");
return IntCCReg[fakeReg];
}
- case UltraSparcRegInfo::FloatCCRegClassID: {
+ case SparcRegInfo::FloatCCRegClassID: {
/* These are laid out %fcc0 - %fcc3 => 0 - 3, so are correct */
DEBUG(std::cerr << "FP CC reg: " << fakeReg << "\n");
return fakeReg;
@@ -573,7 +582,7 @@ inline void SparcV9CodeEmitter::emitFarCall(uint64_t Target, Function *F) {
}
}
-void UltraSparc::replaceMachineCodeForFunction (void *Old, void *New) {
+void SparcTargetMachine::replaceMachineCodeForFunction (void *Old, void *New) {
assert (TheJITResolver &&
"Can only call replaceMachineCodeForFunction from within JIT");
uint64_t Target = (uint64_t)(intptr_t)New;
diff --git a/lib/Target/SparcV9/SparcV9FrameInfo.cpp b/lib/Target/SparcV9/SparcV9FrameInfo.cpp
new file mode 100644
index 0000000000..d283e942bb
--- /dev/null
+++ b/lib/Target/SparcV9/SparcV9FrameInfo.cpp
@@ -0,0 +1,65 @@
+//===-- Sparc.cpp - General implementation file for the Sparc 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// Interface to stack frame layout info for the UltraSPARC. Starting offsets
+// for each area of the stack frame are aligned at a multiple of
+// getStackFrameSizeAlignment().
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionInfo.h"
+#include "llvm/Target/TargetFrameInfo.h"
+#include "SparcFrameInfo.h"
+
+using namespace llvm;
+
+int
+SparcFrameInfo::getFirstAutomaticVarOffset(MachineFunction&, bool& pos) const {
+ pos = false; // static stack area grows downwards
+ return StaticAreaOffsetFromFP;
+}
+
+int
+SparcFrameInfo::getRegSpillAreaOffset(MachineFunction& mcInfo, bool& pos) const
+{
+ // ensure no more auto vars are added
+ mcInfo.getInfo()->freezeAutomaticVarsArea();
+
+ pos = false; // static stack area grows downwards
+ unsigned autoVarsSize = mcInfo.getInfo()->getAutomaticVarsSize();
+ return StaticAreaOffsetFromFP - autoVarsSize;
+}
+
+int SparcFrameInfo::getTmpAreaOffset(MachineFunction& mcInfo, bool& pos) const {
+ MachineFunctionInfo *MFI = mcInfo.getInfo();
+ MFI->freezeAutomaticVarsArea(); // ensure no more auto vars are added
+ MFI->freezeSpillsArea(); // ensure no more spill slots are added
+
+ pos = false; // static stack area grows downwards
+ unsigned autoVarsSize = MFI->getAutomaticVarsSize();
+ unsigned spillAreaSize = MFI->getRegSpillsSize();
+ int offset = autoVarsSize + spillAreaSize;
+ return StaticAreaOffsetFromFP - offset;
+}
+
+int
+SparcFrameInfo::getDynamicAreaOffset(MachineFunction& mcInfo, bool& pos) const {
+ // Dynamic stack area grows downwards starting at top of opt-args area.
+ // The opt-args, required-args, and register-save areas are empty except
+ // during calls and traps, so they are shifted downwards on each
+ // dynamic-size alloca.
+ pos = false;
+ unsigned optArgsSize = mcInfo.getInfo()->getMaxOptionalArgsSize();
+ if (int extra = optArgsSize % getStackFrameSizeAlignment())
+ optArgsSize += (getStackFrameSizeAlignment() - extra);
+ int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP;
+ assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0);
+ return offset;
+}
diff --git a/lib/Target/SparcV9/SparcV9FrameInfo.h b/lib/Target/SparcV9/SparcV9FrameInfo.h
new file mode 100644
index 0000000000..903859675c
--- /dev/null
+++ b/lib/Target/SparcV9/SparcV9FrameInfo.h
@@ -0,0 +1,174 @@
+//===-- SparcFrameInfo.h - Define TargetFrameInfo for Sparc -----*- 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// Interface to stack frame layout info for the UltraSPARC.
+// Starting offsets for each area of the stack frame are aligned at
+// a multiple of getStackFrameSizeAlignment().
+//
+//----------------------------------------------------------------------------
+
+#ifndef SPARC_FRAMEINFO_H
+#define SPARC_FRAMEINFO_H
+
+#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegInfo.h"
+
+namespace llvm {
+
+class SparcFrameInfo: public TargetFrameInfo {
+ const TargetMachine &target;
+public:
+ SparcFrameInfo(const TargetMachine &TM)
+ : TargetFrameInfo(StackGrowsDown, StackFrameSizeAlignment, 0), target(TM) {}
+
+public:
+ // These methods provide constant parameters of the frame layout.
+ //
+ int getStackFrameSizeAlignment() const { return StackFrameSizeAlignment;}
+ int getMinStackFrameSize() const { return MinStackFrameSize; }
+ int getNumFixedOutgoingArgs() const { return NumFixedOutgoingArgs; }
+ int getSizeOfEachArgOnStack() const { return SizeOfEachArgOnStack; }
+ bool argsOnStackHaveFixedSize() const { return true; }
+
+ // This method adjusts a stack offset to meet alignment rules of target.
+ // The fixed OFFSET (0x7ff) must be subtracted and the result aligned.
+ virtual int adjustAlignment(int unalignedOffset, bool growUp,
+ unsigned int align) const {
+ return unalignedOffset + (growUp? +1:-1)*((unalignedOffset-OFFSET) % align);
+ }
+
+ // These methods compute offsets using the frame contents for a
+ // particular function. The frame contents are obtained from the
+ // MachineCodeInfoForMethod object for the given function.
+ //
+ int getFirstIncomingArgOffset(MachineFunction& mcInfo, bool& growUp) const {
+ growUp = true; // arguments area grows upwards
+ return FirstIncomingArgOffsetFromFP;
+ }
+ int getFirstOutgoingArgOffset(MachineFunction& mcInfo, bool& growUp) const {
+ growUp = true; // arguments area grows upwards
+ return FirstOutgoingArgOffsetFromSP;
+ }
+ int getFirstOptionalOutgoingArgOffset(MachineFunction& mcInfo,
+ bool& growUp) const {
+ growUp = true; // arguments area grows upwards
+ return FirstOptionalOutgoingArgOffsetFromSP;
+ }
+
+ int getFirstAutomaticVarOffset(MachineFunction& mcInfo, bool& growUp) const;
+ int getRegSpillAreaOffset(MachineFunction& mcInfo, bool& growUp) const;
+ int getTmpAreaOffset(MachineFunction& mcInfo, bool& growUp) const;
+ int getDynamicAreaOffset(MachineFunction& mcInfo, bool& growUp) const;
+
+ //
+ // These methods specify the base register used for each stack area
+ // (generally FP or SP)
+ //
+ virtual int getIncomingArgBaseRegNum() const {
+ return (int) target.getRegInfo().getFramePointer();
+ }
+ virtual int getOutgoingArgBaseRegNum() const {
+ return (int) target.getRegInfo().getStackPointer();
+ }
+ virtual int getOptionalOutgoingArgBaseRegNum() const {
+ return (int) target.getRegInfo().getStackPointer();
+ }
+ virtual int getAutomaticVarBaseRegNum() const {
+ return (int) target.getRegInfo().getFramePointer();
+ }
+ virtual int getRegSpillAreaBaseRegNum() const {
+ return (int) target.getRegInfo().getFramePointer();
+ }
+ virtual int getDynamicAreaBaseRegNum() const {
+ return (int) target.getRegInfo().getStackPointer();
+ }
+
+ virtual int getIncomingArgOffset(MachineFunction& mcInfo,
+ unsigned argNum) const {
+ assert(argsOnStackHaveFixedSize());
+
+ unsigned relativeOffset = argNum * getSizeOfEachArgOnStack();
+ bool growUp; // do args grow up or down
+ int firstArg = getFirstIncomingArgOffset(mcInfo, growUp);
+ return growUp ? firstArg + relativeOffset : firstArg - relativeOffset;
+ }
+
+ virtual int getOutgoingArgOffset(MachineFunction& mcInfo,
+ unsigned argNum) const {
+ assert(argsOnStackHaveFixedSize());
+ //assert(((int) argNum - this->getNumFixedOutgoingArgs())
+ // <= (int) mcInfo.getInfo()->getMaxOptionalNumArgs());
+
+ unsigned relativeOffset = argNum * getSizeOfEachArgOnStack();
+ bool growUp; // do args grow up or down
+ int firstArg = getFirstOutgoingArgOffset(mcInfo, growUp);
+ return growUp ? firstArg + relativeOffset : firstArg - relativeOffset;
+ }
+
+private:
+ /*----------------------------------------------------------------------
+ This diagram shows the stack frame layout used by llc on Sparc V9.
+ Note that only the location of automatic variables, spill area,
+ temporary storage, and dynamically allocated stack area are chosen
+ by us. The rest conform to the Sparc V9 ABI.
+ All stack addresses are offset by OFFSET = 0x7ff (2047).
+
+ Alignment assumptions and other invariants:
+ (1) %sp+OFFSET and %fp+OFFSET are always aligned on 16-byte boundary
+ (2) Variables in automatic, spill, temporary, or dynamic regions
+ are aligned according to their size as in all memory accesses.
+ (3) Everything below the dynamically allocated stack area is only used
+ during a call to another function, so it is never needed when
+ the current function is active. This is why space can be allocated
+ dynamically by incrementing %sp any time within the function.
+
+ STACK FRAME LAYOUT:
+
+ ...
+ %fp+OFFSET+176 Optional extra incoming arguments# 1..N
+ %fp+OFFSET+168 Incoming argument #6
+ ... ...
+ %fp+OFFSET+128 Incoming argument #1
+ ... ...
+ ---%fp+OFFSET-0--------Bottom of caller's stack frame--------------------
+ %fp+OFFSET-8 Automatic variables <-- ****TOP OF STACK FRAME****
+ Spill area
+ Temporary storage
+ ...
+
+ %sp+OFFSET+176+8N Bottom of dynamically allocated stack area
+ %sp+OFFSET+168+8N Optional extra outgoing argument# N
+ ... ...
+ %sp+OFFSET+176 Optional extra outgoing argument# 1
+ %sp+OFFSET+168 Outgoing argument #6
+ ... ...
+ %sp+OFFSET+128 Outgoing argument #1
+ %sp+OFFSET+120 Save area for %i7
+ ... ...
+ %sp+OFFSET+0 Save area for %l0 <-- ****BOTTOM OF STACK FRAME****
+
+ *----------------------------------------------------------------------*/
+
+ // All stack addresses must be offset by 0x7ff (2047) on Sparc V9.
+ static const int OFFSET = (int) 0x7ff;
+ static const int StackFrameSizeAlignment = 16;
+ static const int MinStackFrameSize = 176;
+ static const int NumFixedOutgoingArgs = 6;
+ static const int SizeOfEachArgOnStack = 8;
+ static const int FirstIncomingArgOffsetFromFP = 128 + OFFSET;
+ static const int FirstOptionalIncomingArgOffsetFromFP = 176 + OFFSET;
+ static const int StaticAreaOffsetFromFP = 0 + OFFSET;
+ static const int FirstOutgoingArgOffsetFromSP = 128 + OFFSET;
+ static const int FirstOptionalOutgoingArgOffsetFromSP = 176 + OFFSET;
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/lib/Target/SparcV9/SparcV9InstrInfo.cpp b/lib/Target/SparcV9/SparcV9InstrInfo.cpp
index 11b0c7beab..af458ea039 100644
--- a/lib/Target/SparcV9/SparcV9InstrInfo.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrInfo.cpp
@@ -9,8 +9,6 @@
//
//===----------------------------------------------------------------------===//
-#include "SparcInternals.h"
-#include "SparcInstrSelectionSupport.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
@@ -22,6 +20,9 @@
#include "llvm/CodeGen/MachineFunctionInfo.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "SparcInternals.h"
+#include "SparcInstrSelectionSupport.h"
+#include "SparcInstrInfo.h"
namespace llvm {
@@ -41,7 +42,7 @@ static const uint32_t MAXSIMM = (1 << 12) - 1; // set bits in simm13 field of OR
//---------------------------------------------------------------------------
uint64_t
-UltraSparcInstrInfo::ConvertConstantToIntType(const TargetMachine &target,
+SparcInstrInfo::ConvertConstantToIntType(const TargetMachine &target,
const Value *V,
const Type *destType,
bool &isValidConstant) const
@@ -406,7 +407,7 @@ InitializeMaxConstantsTable()
//---------------------------------------------------------------------------
-// class UltraSparcInstrInfo
+// class SparcInstrInfo
//
// Purpose:
// Information about individual instructions.
@@ -416,7 +417,7 @@ InitializeMaxConstantsTable()
//---------------------------------------------------------------------------
/*ctor*/
-UltraSparcInstrInfo::UltraSparcInstrInfo()
+SparcInstrInfo::SparcInstrInfo()
: TargetInstrInfo(SparcMachineInstrDesc,
/*descSize = */ V9::NUM_TOTAL_OPCODES,
/*numRealOpCodes = */ V9::NUM_REAL_OPCODES)
@@ -425,7 +426,7 @@ UltraSparcInstrInfo::UltraSparcInstrInfo()
}
bool
-UltraSparcInstrInfo::ConstantMayNotFitInImmedField(const Constant* CV,
+SparcInstrInfo::ConstantMayNotFitInImmedField(const Constant* CV,
const Instruction* I) const
{
if (I->getOpcode() >= MaxConstantsTable.size()) // user-defined op (or bug!)
@@ -455,12 +456,12 @@ UltraSparcInstrInfo::ConstantMayNotFitInImmedField(const Constant* CV,
// Any stack space required is allocated via MachineFunction.
//
void
-UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
- Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const
+SparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const
{
assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
"I only know about constant values and global addresses");
@@ -552,7 +553,7 @@ UltraSparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
// Any stack space required is allocated via MachineFunction.
//
void
-UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
+SparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
Function* F,
Value* val,
Instruction* dest,
@@ -613,7 +614,7 @@ UltraSparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
// Temporary stack space required is allocated via MachineFunction.
//
void
-UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
+SparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
Function* F,
Value* val,
Instruction* dest,
@@ -664,11 +665,11 @@ UltraSparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
// Any stack space required is allocated via MachineFunction.
//
void
-UltraSparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
- Function *F,
- Value* src,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
+SparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
+ Function *F,
+ Value* src,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
MachineCodeForInstruction& mcfi) const
{
bool loadConstantToReg = false;
@@ -760,7 +761,7 @@ CreateBitExtensionInstructions(bool signExtend,
// Any stack space required is allocated via MachineFunction.
//
void
-UltraSparcInstrInfo::CreateSignExtensionInstructions(
+SparcInstrInfo::CreateSignExtensionInstructions(
const TargetMachine& target,
Function* F,
Value* srcVal,
@@ -782,7 +783,7 @@ UltraSparcInstrInfo::CreateSignExtensionInstructions(
// Any stack space required is allocated via MachineFunction.
//
void
-UltraSparcInstrInfo::CreateZeroExtensionInstructions(
+SparcInstrInfo::CreateZeroExtensionInstructions(
const TargetMachine& target,
Function* F,
Value* srcVal,
diff --git a/lib/Target/SparcV9/SparcV9InstrInfo.h b/lib/Target/SparcV9/SparcV9InstrInfo.h
new file mode 100644
index 0000000000..0926c072f9
--- /dev/null
+++ b/lib/Target/SparcV9/SparcV9InstrInfo.h
@@ -0,0 +1,201 @@
+//===-- SparcInstrInfo.h - Define TargetInstrInfo for Sparc -----*- 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 class contains information about individual instructions.
+// Most information is stored in the SparcMachineInstrDesc array above.
+// Other information is computed on demand, and most such functions
+// default to member functions in base class TargetInstrInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SPARC_INSTRINFO_H
+#define SPARC_INSTRINFO_H
+
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "SparcInternals.h"
+
+namespace llvm {
+
+struct SparcInstrInfo : public TargetInstrInfo {
+ SparcInstrInfo();
+
+ // All immediate constants are in position 1 except the
+ // store instructions and SETxx.
+ //
+ virtual int getImmedConstantPos(MachineOpCode opCode) const {
+ bool ignore;
+ if (this->maxImmedConstant(opCode, ignore) != 0) {
+ // 1st store opcode
+ assert(! this->isStore((MachineOpCode) V9::STBr - 1));
+ // last store opcode
+ assert(! this->isStore((MachineOpCode) V9::STXFSRi + 1));
+
+ if (opCode == V9::SETSW || opCode == V9::SETUW ||
+ opCode == V9::SETX || opCode == V9::SETHI)
+ return 0;
+ if (opCode >= V9::STBr && opCode <= V9::STXFSRi)
+ return 2;
+ return 1;
+ }
+ else
+ return -1;
+ }
+
+ /// createNOPinstr - returns the target's implementation of NOP, which is
+ /// usually a pseudo-instruction, implemented by a degenerate version of
+ /// another instruction, e.g. X86: xchg ax, ax; SparcV9: sethi 0, g0
+ ///
+ MachineInstr* createNOPinstr() const {
+ return BuildMI(V9::SETHI, 2).addZImm(0).addReg(SparcIntRegClass::g0);
+ }
+
+ /// isNOPinstr - not having a special NOP opcode, we need to know if a given
+ /// instruction is interpreted as an `official' NOP instr, i.e., there may be
+ /// more than one way to `do nothing' but only one canonical way to slack off.
+ ///
+ bool isNOPinstr(const MachineInstr &MI) const {
+ // Make sure the instruction is EXACTLY `sethi g0, 0'
+ if (MI.getOpcode() == V9::SETHI && MI.getNumOperands() == 2) {
+ const MachineOperand &op0 = MI.getOperand(0), &op1 = MI.getOperand(1);
+ if (op0.isImmediate() && op0.getImmedValue() == 0 &&
+ op1.isMachineRegister() &&
+ op1.getMachineRegNum() == SparcIntRegClass::g0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual bool hasResultInterlock(MachineOpCode opCode) const
+ {
+ // All UltraSPARC instructions have interlocks (note that delay slots
+ // are not considered here).
+ // However, instructions that use the result of an FCMP produce a
+ // 9-cycle stall if they are issued less than 3 cycles after the FCMP.
+ // Force the compiler to insert a software interlock (i.e., gap of
+ // 2 other groups, including NOPs if necessary).
+ return (opCode == V9::FCMPS || opCode == V9::FCMPD || opCode == V9::FCMPQ);
+ }
+
+ //-------------------------------------------------------------------------
+ // Queries about representation of LLVM quantities (e.g., constants)
+ //-------------------------------------------------------------------------
+
+ virtual bool ConstantMayNotFitInImmedField(const Constant* CV,
+ const Instruction* I) const;
+
+ //-------------------------------------------------------------------------
+ // Code generation support for creating individual machine instructions
+ //-------------------------------------------------------------------------
+
+ // Get certain common op codes for the current target. This and all the
+ // Create* methods below should be moved to a machine code generation class
+ //
+ virtual MachineOpCode getNOPOpCode() const { return V9::NOP; }
+
+ // Get the value of an integral constant in the form that must
+ // be put into the machine register. The specified constant is interpreted
+ // as (i.e., converted if necessary to) the specified destination type. The
+ // result is always returned as an uint64_t, since the representation of
+ // int64_t and uint64_t are identical. The argument can be any known const.
+ //
+ // isValidConstant is set to true if a valid constant was found.
+ //
+ virtual uint64_t ConvertConstantToIntType(const TargetMachine &target,
+ const Value *V,
+ const Type *destType,
+ bool &isValidConstant) const;
+
+ // Create an instruction sequence to put the constant `val' into
+ // the virtual register `dest'. `val' may be a Constant or a
+ // GlobalValue, viz., the constant address of a global variable or function.
+ // The generated instructions are returned in `mvec'.
+ // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+ // Any stack space required is allocated via mcff.
+ //
+ virtual void CreateCodeToLoadConst(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
+
+ // Create an instruction sequence to copy an integer value `val'
+ // to a floating point value `dest' by copying to memory and back.
+ // val must be an integral type. dest must be a Float or Double.
+ // The generated instructions are returned in `mvec'.
+ // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+ // Any stack space required is allocated via mcff.
+ //
+ virtual void CreateCodeToCopyIntToFloat(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
+
+ // Similarly, create an instruction sequence to copy an FP value
+ // `val' to an integer value `dest' by copying to memory and back.
+ // The generated instructions are returned in `mvec'.
+ // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+ // Any stack space required is allocated via mcff.
+ //
+ virtual void CreateCodeToCopyFloatToInt(const TargetMachine& target,
+ Function* F,
+ Value* val,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
+
+ // Create instruction(s) to copy src to dest, for arbitrary types
+ // The generated instructions are returned in `mvec'.
+ // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+ // Any stack space required is allocated via mcff.
+ //
+ virtual void CreateCopyInstructionsByType(const TargetMachine& target,
+ Function* F,
+ Value* src,
+ Instruction* dest,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
+
+ // Create instruction sequence to produce a sign-extended register value
+ // from an arbitrary sized value (sized in bits, not bytes).
+ // The generated instructions are appended to `mvec'.
+ // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+ // Any stack space required is allocated via mcff.
+ //
+ virtual void CreateSignExtensionInstructions(const TargetMachine& target,
+ Function* F,
+ Value* srcVal,
+ Value* destVal,
+ unsigned int numLowBits,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
+
+ // Create instruction sequence to produce a zero-extended register value
+ // from an arbitrary sized value (sized in bits, not bytes).
+ // The generated instructions are appended to `mvec'.
+ // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+ // Any stack space required is allocated via mcff.
+ //
+ virtual void CreateZeroExtensionInstructions(const TargetMachine& target,
+ Function* F,
+ Value* srcVal,
+ Value* destVal,
+ unsigned int numLowBits,
+ std::vector<MachineInstr*>& mvec,
+ MachineCodeForInstruction& mcfi) const;
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/lib/Target/SparcV9/SparcV9InstrSelection.cpp b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
index 21e884be8e..c5fa145a8e 100644
--- a/lib/Target/SparcV9/SparcV9InstrSelection.cpp
+++ b/lib/Target/SparcV9/SparcV9InstrSelection.cpp
@@ -11,9 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "SparcInstrSelectionSupport.h"
-#include "SparcInternals.h"
-#include "SparcRegClassInfo.h"
#include "llvm/Constants.h"
#include "llvm/ConstantHandling.h"
#include "llvm/DerivedTypes.h"
@@ -28,6 +25,10 @@
#include "llvm/CodeGen/MachineFunctionInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineInstrAnnot.h"
+#include "SparcInstrSelectionSupport.h"
+#include "SparcInternals.h"
+#include "SparcRegClassInfo.h"
+#include "SparcRegInfo.h"
#include "Support/MathExtras.h"
#include <algorithm>
#include <cmath>
@@ -1583,8 +1584,8 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
// -- For non-FP values, create an add-with-0 instruction
//
if (retVal != NULL) {
- const UltraSparcRegInfo& regInfo =