aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/SparcV9/SparcV9Instr.def6
-rw-r--r--lib/Target/SparcV9/SparcV9Internals.h8
-rw-r--r--lib/Target/SparcV9/SparcV9RegClassInfo.h38
-rw-r--r--lib/Target/SparcV9/SparcV9RegInfo.cpp127
4 files changed, 158 insertions, 21 deletions
diff --git a/lib/Target/SparcV9/SparcV9Instr.def b/lib/Target/SparcV9/SparcV9Instr.def
index 368cc5ad76..cf70b31b12 100644
--- a/lib/Target/SparcV9/SparcV9Instr.def
+++ b/lib/Target/SparcV9/SparcV9Instr.def
@@ -38,6 +38,7 @@
// instr class flags (defined in MachineInstrInfo.h)
+
I(NOP, "nop", 0, -1, 0, false, 0, 1, SPARC_NONE, M_NOP_FLAG)
// Synthetic SPARC assembly opcodes for setting a register to a constant.
@@ -430,6 +431,11 @@ I(RETURN, "return", 2, -1, 0, false, 1, 2, SPARC_CTI, M_BRANCH_FLAG | M_RET_
I(SAVE , "save", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG)
I(RESTORE, "restore", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG)
+// Read and Write CCR register from/to an int reg
+I(RDCCR, "rd", 2, 1, 0, false, 0, 1, SPARC_IEUN, M_INT_FLAG)
+I(WRCCR, "wr", 3, 2, 0, false, 0, 1, SPARC_IEUN, M_INT_FLAG)
+
+
// Synthetic phi operation for near-SSA form of machine code
// Number of operands is variable, indicated by -1. Result is the first op.
I(PHI, "<phi>", -1, 0, 0, false, 0, 0, SPARC_INV, M_DUMMY_PHI_FLAG)
diff --git a/lib/Target/SparcV9/SparcV9Internals.h b/lib/Target/SparcV9/SparcV9Internals.h
index 72b234f72c..2f151b7887 100644
--- a/lib/Target/SparcV9/SparcV9Internals.h
+++ b/lib/Target/SparcV9/SparcV9Internals.h
@@ -254,6 +254,9 @@ class UltraSparcRegInfo : public MachineRegInfo
const unsigned getCallInstNumArgs(const MachineInstr *CallMI) const;
+ MachineInstr * cpCCR2IntMI(const unsigned IntReg) const;
+ MachineInstr * cpInt2CCRMI(const unsigned IntReg) const;
+
public:
@@ -371,9 +374,8 @@ class UltraSparcRegInfo : public MachineRegInfo
return SparcFloatRegOrder::getRegName( reg - 32);
else if( reg < (64+32+4) )
return SparcFloatCCRegOrder::getRegName( reg -32 - 64);
- else if ( reg == 64+32+4)
- return "xcc"; // only integer cc reg
-
+ else if( reg < (64+32+4+2) ) // two names: %xcc and %ccr
+ return SparcIntCCRegOrder::getRegName( reg -32 - 64 - 4);
else if (reg== InvalidRegNum) //****** TODO: Remove */
return "<*NoReg*>";
else
diff --git a/lib/Target/SparcV9/SparcV9RegClassInfo.h b/lib/Target/SparcV9/SparcV9RegClassInfo.h
index 4f91268c37..fd76815750 100644
--- a/lib/Target/SparcV9/SparcV9RegClassInfo.h
+++ b/lib/Target/SparcV9/SparcV9RegClassInfo.h
@@ -191,22 +191,54 @@ class SparcFloatRegClass : public MachineRegClassInfo
//-----------------------------------------------------------------------------
// Int CC Register Class
-// Only one integer cc register is available
+// Only one integer cc register is available. However, this register is
+// referred to as %xcc when instructions like subcc are executed but
+// referred to as %ccr (i.e., %xcc + %icc") when this register is moved
+// into an integer register using RD or WR instrcutions. So, two ids are
+// allocated for two names.
//-----------------------------------------------------------------------------
+static string const IntCCRegNames[] =
+ {
+ "xcc", "ccr"
+ };
+
+
+class SparcIntCCRegOrder{
+
+ public:
+
+ enum RegsInPrefOrder {
+
+ xcc, ccr // only one is available - see the note above
+ };
+
+ static const string getRegName(const unsigned reg) {
+ assert( reg < 2 );
+ return IntCCRegNames[reg];
+ }
+
+ // according to Sparc 64 ABI, %ccr is volatile
+ inline bool isRegVolatile(const int Reg) const { return true; }
+
+
+};
+
+
+
class SparcIntCCRegClass : public MachineRegClassInfo
{
public:
SparcIntCCRegClass(unsigned ID)
- : MachineRegClassInfo(ID,1, 1) { }
+ : MachineRegClassInfo(ID, 1, 2) { }
inline void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
Node->setColor(0); // only one int cc reg is available
}
- // *** TODO: Check this
+
inline bool isRegVolatile(const int Reg) const { return true; }
};
diff --git a/lib/Target/SparcV9/SparcV9RegInfo.cpp b/lib/Target/SparcV9/SparcV9RegInfo.cpp
index a34a5305ae..9c57892392 100644
--- a/lib/Target/SparcV9/SparcV9RegInfo.cpp
+++ b/lib/Target/SparcV9/SparcV9RegInfo.cpp
@@ -896,7 +896,6 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(const unsigned SrcReg,
switch( RegType ) {
case IntRegType:
- case IntCCRegType:
case FloatCCRegType:
MI = new MachineInstr(STX, 3);
MI->SetMachineOperand(0, SrcReg, false);
@@ -921,8 +920,11 @@ MachineInstr * UltraSparcRegInfo::cpReg2MemMI(const unsigned SrcReg,
(int64_t) Offset, false);
break;
+ case IntCCRegType:
+ assert( 0 && "Cannot directly store %ccr to memory");
+
default:
- assert(0 && "Unknow RegType");
+ assert(0 && "Unknow RegType in cpReg2MemMI");
}
return MI;
@@ -945,7 +947,6 @@ MachineInstr * UltraSparcRegInfo::cpMem2RegMI(const unsigned SrcPtrReg,
switch( RegType ) {
case IntRegType:
- case IntCCRegType:
case FloatCCRegType:
MI = new MachineInstr(LDX, 3);
MI->SetMachineOperand(0, SrcPtrReg, false);
@@ -971,14 +972,21 @@ MachineInstr * UltraSparcRegInfo::cpMem2RegMI(const unsigned SrcPtrReg,
MI->SetMachineOperand(2, DestReg, false);
break;
+ case IntCCRegType:
+ assert( 0 && "Cannot directly load into %ccr from memory");
+
default:
- assert(0 && "Unknow RegType");
+ assert(0 && "Unknow RegType in cpMem2RegMI");
}
return MI;
}
+
+
+// Following method is Not needed now
+
MachineInstr* UltraSparcRegInfo::cpValue2Value(Value *Src, Value *Dest) const {
MachineInstr * MI = NULL;
@@ -1071,28 +1079,91 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
int StackOff = PRA.StackOffsets. getNewTmpPosOffFromFP();
- /**** TODO - Handle IntCCRegType
+
+ MachineInstr *AdIBefCC, *AdIAftCC, *AdICpCC;
+
+
+ //---- Insert code for pushing the reg on stack ----------
+ if( RegType == IntCCRegType ) {
+
+ // Handle IntCCRegType specially since we cannot directly
+ // push %ccr on to the stack
+
+ const LiveVarSet *LVSetBef =
+ PRA.LVI->getLiveVarSetBeforeMInst(MInst, BB);
+
+ // get a free INTEGER register
+ int FreeIntReg =
+ PRA.getUsableRegAtMI(LR->getRegClass(), IntRegType, MInst,
+ LVSetBef, AdIBefCC, AdIAftCC);
+ // insert the instructions in reverse order since we are
+ // adding them to the front of InstrnsBefore
+ if(AdIAftCC)
+ (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdIAftCC);
+
+ AdICpCC = cpCCR2IntMI(FreeIntReg);
+ (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdICpCC);
+
+ if(AdIBefCC)
+ (PRA.AddedInstrMap[MInst]->InstrnsBefore).push_front(AdIBefCC);
+
+ cerr << "\n!! Inserted caller saving (push) inst for %ccr:";
+ if(AdIBefCC) cerr << "\t" << *(AdIBefCC);
+ cerr << "\t" << *AdICpCC;
+ if(AdIAftCC) cerr << "\t" << *(AdIAftCC);
+
+ } else {
+ // for any other register type, just add the push inst
+ MachineInstr *AdIBef =
+ cpReg2MemMI(Reg, getStackPointer(), StackOff, RegType );
+ ((PRA.AddedInstrMap[MInst])->InstrnsBefore).push_front(AdIBef);
}
- */
+
+
+ //---- Insert code for popping the reg from the stack ----------
+
+ if( RegType == IntCCRegType ) {
+
+ // Handle IntCCRegType specially since we cannot directly
+ // pop %ccr on from the stack
+
+ // get a free INT register
+ int FreeIntReg =
+ PRA.getUsableRegAtMI(LR->getRegClass(), IntRegType, MInst,
+ LVSetAft, AdIBefCC, AdIAftCC);
+
+ if(AdIBefCC)
+ (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdIBefCC);
+
+ AdICpCC = cpInt2CCRMI(FreeIntReg);
+ (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdICpCC);
- MachineInstr *AdIBef =
- cpReg2MemMI(Reg, getStackPointer(), StackOff, RegType );
+ if(AdIAftCC)
+ (PRA.AddedInstrMap[MInst]->InstrnsAfter).push_back(AdIAftCC);
+
+ cerr << "\n!! Inserted caller saving (pop) inst for %ccr:";
+ if(AdIBefCC) cerr << "\t" << *(AdIBefCC);
+ cerr << "\t" << *AdICpCC;
+ if(AdIAftCC) cerr << "\t" << *(AdIAftCC);
+
+ } else {
+ // for any other register type, just add the pop inst
+ MachineInstr *AdIAft =
+ cpMem2RegMI(getStackPointer(), StackOff, Reg, RegType );
- MachineInstr *AdIAft =
- cpMem2RegMI(getStackPointer(), StackOff, Reg, RegType );
+ ((PRA.AddedInstrMap[MInst])->InstrnsAfter).push_back(AdIAft);
- ((PRA.AddedInstrMap[MInst])->InstrnsBefore).push_front(AdIBef);
- ((PRA.AddedInstrMap[MInst])->InstrnsAfter).push_back(AdIAft);
+ }
PushedRegSet.insert( Reg );
- if(DEBUG_RA) {
- cerr << "\nFor callee save call inst:" << *MInst;
+ if(1) {
+ cerr << "\nFor call inst:" << *MInst;
cerr << "\n -inserted caller saving instrs:\n\t ";
- cerr << *AdIBef << "\n\t" << *AdIAft ;
+ cerr << *AdIBefCC << "\n\t" << *AdIAftCC ;
}
} // if not already pushed
@@ -1106,10 +1177,36 @@ void UltraSparcRegInfo::insertCallerSavingCode(const MachineInstr *MInst,
}
+//---------------------------------------------------------------------------
+// Copies %ccr into an integer register. IntReg is the UNIFIED register
+// number.
+//---------------------------------------------------------------------------
+MachineInstr * UltraSparcRegInfo::cpCCR2IntMI(const unsigned IntReg) const {
+ MachineInstr * MI = NULL;
+ MI = new MachineInstr(RDCCR, 2);
+ MI->SetMachineOperand(0, SparcIntCCRegOrder::ccr, false);
+ MI->SetMachineOperand(1, IntReg, true);
+ return MI;
+}
+
+//---------------------------------------------------------------------------
+// Copies an integer register into %ccr. IntReg is the UNIFIED register
+// number.
+//---------------------------------------------------------------------------
+
+MachineInstr * UltraSparcRegInfo::cpInt2CCRMI(const unsigned IntReg) const {
+ MachineInstr * MI = NULL;
+
+ MI = new MachineInstr(WRCCR, 3);
+ MI->SetMachineOperand(0, IntReg, false);
+ MI->SetMachineOperand(1, SparcIntRegOrder::g0, false);
+ MI->SetMachineOperand(2, SparcIntCCRegOrder::ccr, true);
+ return MI;
+}