Add completely untested support for mtcrf/mfcrf encoding
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9RegInfo.cpp
index 0c36d3b63a779bc80e60a4a20035f3142dacd567..8a827187aee650e9936a9046d0811a622d9d9367 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/InstrSelection.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
+#include "MachineFunctionInfo.h"
+#include "MachineCodeForInstruction.h"
 #include "MachineInstrAnnot.h"
 #include "RegAlloc/LiveRangeInfo.h"
 #include "RegAlloc/LiveRange.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iOther.h"
+#include "llvm/Instructions.h"
 #include "SparcV9Internals.h"
 #include "SparcV9RegClassInfo.h"
 #include "SparcV9RegInfo.h"
+#include "SparcV9FrameInfo.h"
 #include "SparcV9TargetMachine.h"
+#include "SparcV9TmpInstr.h"
+#include <iostream>
 
 namespace llvm {
 
@@ -272,7 +273,7 @@ int SparcV9RegInfo::getRegType(int unifiedRegNum) const
 //
 unsigned SparcV9RegInfo::getRegClassIDOfType(const Type *type,
                                                 bool isCCReg) const {
-  Type::PrimitiveID ty = type->getPrimitiveID();
+  Type::TypeID ty = type->getTypeID();
   unsigned res;
     
   // FIXME: Comparing types like this isn't very safe...
@@ -373,7 +374,7 @@ void SparcV9RegInfo::suggestRegs4MethodArgs(const Function *Meth,
   // Count the arguments, *ignoring* whether they are int or FP args.
   // Use this common arg numbering to pick the right int or fp register.
   unsigned argNo=0;
-  for(Function::const_aiterator I = Meth->abegin(), E = Meth->aend();
+  for(Function::const_arg_iterator I = Meth->arg_begin(), E = Meth->arg_end();
       I != E; ++I, ++argNo) {
     LiveRange *LR = LRI.getLiveRangeForValue(I);
     assert(LR && "No live range found for method arg");
@@ -409,7 +410,7 @@ void SparcV9RegInfo::colorMethodArgs(const Function *Meth,
   // for each argument
   // for each argument.  count INT and FP arguments separately.
   unsigned argNo=0, intArgNo=0, fpArgNo=0;
-  for(Function::const_aiterator I = Meth->abegin(), E = Meth->aend();
+  for(Function::const_arg_iterator I = Meth->arg_begin(), E = Meth->arg_end();
       I != E; ++I, ++argNo) {
     // get the LR of arg
     LiveRange *LR = LRI.getLiveRangeForValue(I);
@@ -455,7 +456,7 @@ void SparcV9RegInfo::colorMethodArgs(const Function *Meth,
       //
       if( isArgInReg ) {
        if( regClassIDOfArgReg != RegClassID ) {
-          assert(0 && "This could should work but it is not tested yet");
+         // NOTE: This code has not been well-tested.
           
          // It is a variable argument call: the float reg must go in a %o reg.
          // We have to move an int reg to a float reg via memory.
@@ -465,7 +466,7 @@ void SparcV9RegInfo::colorMethodArgs(const Function *Meth,
                  regClassIDOfArgReg == IntRegClassID &&
                  "This should only be an Int register for an FP argument");
           
-         int TmpOff = MachineFunction::get(Meth).getInfo()->pushTempValue(
+         int TmpOff = MachineFunction::get(Meth).getInfo<SparcV9FunctionInfo>()->pushTempValue(
                                                 getSpilledRegSize(regType));
          cpReg2MemMI(InstrnsBefore,
                       UniArgReg, getFramePointer(), TmpOff, IntRegType);
@@ -492,7 +493,7 @@ void SparcV9RegInfo::colorMethodArgs(const Function *Meth,
         // a full double-word so the offset does not need to be adjusted.
         if (regType == FPSingleRegType) {
           unsigned argSize = target.getTargetData().getTypeSize(LR->getType());
-          unsigned slotSize = frameInfo.getSizeOfEachArgOnStack();
+          unsigned slotSize = SparcV9FrameInfo::SizeOfEachArgOnStack;
           assert(argSize <= slotSize && "Insufficient slot size!");
           offsetFromFP += slotSize - argSize;
         }
@@ -550,7 +551,7 @@ void SparcV9RegInfo::colorMethodArgs(const Function *Meth,
         // a full double-word so the offset does not need to be adjusted.
         if (regType == FPSingleRegType) {
           unsigned argSize = target.getTargetData().getTypeSize(LR->getType());
-          unsigned slotSize = frameInfo.getSizeOfEachArgOnStack();
+          unsigned slotSize = SparcV9FrameInfo::SizeOfEachArgOnStack;
           assert(argSize <= slotSize && "Insufficient slot size!");
           offsetFromFP += slotSize - argSize;
         }
@@ -743,82 +744,80 @@ SparcV9RegInfo::cpReg2RegMI(std::vector<MachineInstr*>& mvec,
     mvec.push_back(MI);
 }
 
-//---------------------------------------------------------------------------
-// Copy from a register to memory (i.e., Store). Register number must 
-// be the unified register number
-//---------------------------------------------------------------------------
-
-
-void
-SparcV9RegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec,
-                               unsigned SrcReg, 
-                               unsigned PtrReg,
-                               int Offset, int RegType,
-                               int scratchReg) const {
-  MachineInstr * MI = NULL;
-  int OffReg = -1;
-
-  // If the Offset will not fit in the signed-immediate field, find an
-  // unused register to hold the offset value.  This takes advantage of
-  // the fact that all the opcodes used below have the same size immed. field.
-  // Use the register allocator, PRA, to find an unused reg. at this MI.
-  // 
-  if (RegType != IntCCRegType)          // does not use offset below
-    if (! target.getInstrInfo()->constantFitsInImmedField(V9::LDXi, Offset)) {
-#ifdef CAN_FIND_FREE_REGISTER_TRANSPARENTLY
-      RegClass* RC = PRA.getRegClassByID(this->getRegClassIDOfRegType(RegType));
-      OffReg = PRA.getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef);
-#else
-      // Default to using register g4 for holding large offsets
-      OffReg = getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,
-                                SparcV9IntRegClass::g4);
-#endif
-      assert(OffReg >= 0 && "FIXME: cpReg2MemMI cannot find an unused reg.");
-      mvec.push_back(BuildMI(V9::SETSW, 2).addZImm(Offset).addReg(OffReg));
-    }
+/// cpReg2MemMI - Generate SparcV9 MachineInstrs to store a register
+/// (SrcReg) to memory, at [PtrReg + Offset].  Register numbers must be the
+/// unified register numbers.  RegType must be the SparcV9 register type
+/// of SrcReg. When SrcReg is %ccr, scratchReg must be the
+/// number of a free integer register.  The newly-generated MachineInstrs
+/// are appended to mvec.
+///
+void SparcV9RegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec,
+                                 unsigned SrcReg, unsigned PtrReg, int Offset,
+                                 int RegType, int scratchReg) const {
+  unsigned OffReg = SparcV9::g4; // Use register g4 for holding large offsets
+  bool useImmediateOffset = true;
+
+  // If the Offset will not fit in the signed-immediate field, we put it in
+  // register g4. This takes advantage of the fact that all the opcodes
+  // used below have the same size immed. field.
+  if (RegType != IntCCRegType
+      && !target.getInstrInfo()->constantFitsInImmedField(V9::LDXi, Offset)) {
+    // Put the offset into a register. We could do this in fewer steps,
+    // in some cases (see CreateSETSWConst()) but we're being lazy.
+    MachineInstr *MI = BuildMI(V9::SETHI, 2).addZImm(Offset).addMReg(OffReg,
+      MachineOperand::Def);
+    MI->getOperand(0).markHi32();
+    mvec.push_back(MI);
+    MI = BuildMI(V9::ORi,3).addMReg(OffReg).addZImm(Offset).addMReg(OffReg,
+      MachineOperand::Def);
+    MI->getOperand(1).markLo32();
+    mvec.push_back(MI);
+    MI = BuildMI(V9::SRAi5,3).addMReg(OffReg).addZImm(0).addMReg(OffReg,
+      MachineOperand::Def);
+    mvec.push_back(MI);
+    useImmediateOffset = false;
+  }
 
+  MachineInstr *MI = 0;
   switch (RegType) {
   case IntRegType:
-    if (target.getInstrInfo()->constantFitsInImmedField(V9::STXi, Offset))
+    if (useImmediateOffset)
       MI = BuildMI(V9::STXi,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset);
     else
       MI = BuildMI(V9::STXr,3).addMReg(SrcReg).addMReg(PtrReg).addMReg(OffReg);
     break;
 
   case FPSingleRegType:
-    if (target.getInstrInfo()->constantFitsInImmedField(V9::STFi, Offset))
+    if (useImmediateOffset)
       MI = BuildMI(V9::STFi, 3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset);
     else
       MI = BuildMI(V9::STFr, 3).addMReg(SrcReg).addMReg(PtrReg).addMReg(OffReg);
     break;
 
   case FPDoubleRegType:
-    if (target.getInstrInfo()->constantFitsInImmedField(V9::STDFi, Offset))
+    if (useImmediateOffset)
       MI = BuildMI(V9::STDFi,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset);
     else
       MI = BuildMI(V9::STDFr,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(OffReg);
     break;
 
   case IntCCRegType:
-    assert(scratchReg >= 0 && "Need scratch reg to store %ccr to memory");
-    assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg");
-    MI = (BuildMI(V9::RDCCR, 2)
-          .addMReg(getUnifiedRegNum(SparcV9RegInfo::IntCCRegClassID,
-                                    SparcV9IntCCRegClass::ccr))
-          .addMReg(scratchReg, MachineOperand::Def));
+    assert(scratchReg >= 0 && getRegType(scratchReg) == IntRegType
+           && "Need a scratch reg of integer type to load or store %ccr");
+    MI = BuildMI(V9::RDCCR, 2).addMReg(SparcV9::ccr)
+           .addMReg(scratchReg, MachineOperand::Def);
     mvec.push_back(MI);
-    
     cpReg2MemMI(mvec, scratchReg, PtrReg, Offset, IntRegType);
     return;
 
   case SpecialRegType: // used only for %fsr itself.
   case FloatCCRegType: {
-    unsigned fsrReg =  getUnifiedRegNum(SparcV9RegInfo::SpecialRegClassID,
-                                           SparcV9SpecialRegClass::fsr);
-    if (target.getInstrInfo()->constantFitsInImmedField(V9::STXFSRi, Offset))
-      MI=BuildMI(V9::STXFSRi,3).addMReg(fsrReg).addMReg(PtrReg).addSImm(Offset);
+    if (useImmediateOffset)
+      MI = BuildMI(V9::STXFSRi,3).addMReg(SparcV9::fsr).addMReg(PtrReg)
+             .addSImm(Offset);
     else
-      MI=BuildMI(V9::STXFSRr,3).addMReg(fsrReg).addMReg(PtrReg).addMReg(OffReg);
+      MI = BuildMI(V9::STXFSRr,3).addMReg(SparcV9::fsr).addMReg(PtrReg)
+             .addMReg(OffReg);
     break;
   }
   default:
@@ -827,45 +826,42 @@ SparcV9RegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec,
   mvec.push_back(MI);
 }
 
+/// cpMem2RegMI - Generate SparcV9 MachineInstrs to load a register
+/// (DestReg) from memory, at [PtrReg + Offset].  Register numbers must be the
+/// unified register numbers.  RegType must be the SparcV9 register type
+/// of DestReg. When DestReg is %ccr, scratchReg must be the
+/// number of a free integer register.  The newly-generated MachineInstrs
+/// are appended to mvec.
+///
+void SparcV9RegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec,
+                                 unsigned PtrReg, int Offset, unsigned DestReg,
+                                 int RegType, int scratchReg) const {
+  unsigned OffReg = SparcV9::g4; // Use register g4 for holding large offsets
+  bool useImmediateOffset = true;
+
+  // If the Offset will not fit in the signed-immediate field, we put it in
+  // register g4. This takes advantage of the fact that all the opcodes
+  // used below have the same size immed. field.
+  if (RegType != IntCCRegType
+      && !target.getInstrInfo()->constantFitsInImmedField(V9::LDXi, Offset)) {
+    MachineInstr *MI = BuildMI(V9::SETHI, 2).addZImm(Offset).addMReg(OffReg,
+      MachineOperand::Def);
+    MI->getOperand(0).markHi32();
+    mvec.push_back(MI);
+    MI = BuildMI(V9::ORi,3).addMReg(OffReg).addZImm(Offset).addMReg(OffReg,
+      MachineOperand::Def);
+    MI->getOperand(1).markLo32();
+    mvec.push_back(MI);
+    MI = BuildMI(V9::SRAi5,3).addMReg(OffReg).addZImm(0).addMReg(OffReg,
+      MachineOperand::Def);
+    mvec.push_back(MI);
+    useImmediateOffset = false;
+  }
 
-//---------------------------------------------------------------------------
-// Copy from memory to a reg (i.e., Load) Register number must be the unified
-// register number
-//---------------------------------------------------------------------------
-
-
-void
-SparcV9RegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec,
-                               unsigned PtrReg,        
-                               int Offset,
-                               unsigned DestReg,
-                               int RegType,
-                               int scratchReg) const {
-  MachineInstr * MI = NULL;
-  int OffReg = -1;
-
-  // If the Offset will not fit in the signed-immediate field, find an
-  // unused register to hold the offset value.  This takes advantage of
-  // the fact that all the opcodes used below have the same size immed. field.
-  // Use the register allocator, PRA, to find an unused reg. at this MI.
-  // 
-  if (RegType != IntCCRegType)          // does not use offset below
-    if (! target.getInstrInfo()->constantFitsInImmedField(V9::LDXi, Offset)) {
-#ifdef CAN_FIND_FREE_REGISTER_TRANSPARENTLY
-      RegClass* RC = PRA.getRegClassByID(this->getRegClassIDOfRegType(RegType));
-      OffReg = PRA.getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef);
-#else
-      // Default to using register g4 for holding large offsets
-      OffReg = getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,
-                                SparcV9IntRegClass::g4);
-#endif
-      assert(OffReg >= 0 && "FIXME: cpReg2MemMI cannot find an unused reg.");
-      mvec.push_back(BuildMI(V9::SETSW, 2).addZImm(Offset).addReg(OffReg));
-    }
-
+  MachineInstr *MI = 0;
   switch (RegType) {
   case IntRegType:
-    if (target.getInstrInfo()->constantFitsInImmedField(V9::LDXi, Offset))
+    if (useImmediateOffset)
       MI = BuildMI(V9::LDXi, 3).addMReg(PtrReg).addSImm(Offset)
           .addMReg(DestReg, MachineOperand::Def);
     else
@@ -874,7 +870,7 @@ SparcV9RegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec,
     break;
 
   case FPSingleRegType:
-    if (target.getInstrInfo()->constantFitsInImmedField(V9::LDFi, Offset))
+    if (useImmediateOffset)
       MI = BuildMI(V9::LDFi, 3).addMReg(PtrReg).addSImm(Offset)
           .addMReg(DestReg, MachineOperand::Def);
     else
@@ -883,7 +879,7 @@ SparcV9RegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec,
     break;
 
   case FPDoubleRegType:
-    if (target.getInstrInfo()->constantFitsInImmedField(V9::LDDFi, Offset))
+    if (useImmediateOffset)
       MI= BuildMI(V9::LDDFi, 3).addMReg(PtrReg).addSImm(Offset)
           .addMReg(DestReg, MachineOperand::Def);
     else
@@ -892,26 +888,21 @@ SparcV9RegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec,
     break;
 
   case IntCCRegType:
-    assert(scratchReg >= 0 && "Need scratch reg to load %ccr from memory");
-    assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg");
+    assert(scratchReg >= 0 && getRegType(scratchReg) == IntRegType
+           && "Need a scratch reg of integer type to load or store %ccr");
     cpMem2RegMI(mvec, PtrReg, Offset, scratchReg, IntRegType);
-    MI = (BuildMI(V9::WRCCRr, 3)
-          .addMReg(scratchReg)
-          .addMReg(SparcV9IntRegClass::g0)
-          .addMReg(getUnifiedRegNum(SparcV9RegInfo::IntCCRegClassID,
-                                    SparcV9IntCCRegClass::ccr), MachineOperand::Def));
+    MI = BuildMI(V9::WRCCRr, 3).addMReg(scratchReg).addMReg(SparcV9::g0)
+           .addMReg(SparcV9::ccr, MachineOperand::Def);
     break;
     
   case SpecialRegType: // used only for %fsr itself
   case FloatCCRegType: {
-    unsigned fsrRegNum =  getUnifiedRegNum(SparcV9RegInfo::SpecialRegClassID,
-                                           SparcV9SpecialRegClass::fsr);
-    if (target.getInstrInfo()->constantFitsInImmedField(V9::LDXFSRi, Offset))
+    if (useImmediateOffset)
       MI = BuildMI(V9::LDXFSRi, 3).addMReg(PtrReg).addSImm(Offset)
-        .addMReg(fsrRegNum, MachineOperand::UseAndDef);
+        .addMReg(SparcV9::fsr, MachineOperand::Def);
     else
       MI = BuildMI(V9::LDXFSRr, 3).addMReg(PtrReg).addMReg(OffReg)
-        .addMReg(fsrRegNum, MachineOperand::UseAndDef);
+        .addMReg(SparcV9::fsr, MachineOperand::Def);
     break;
   }
   default:
@@ -929,11 +920,11 @@ SparcV9RegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec,
 
 void
 SparcV9RegInfo::cpValue2Value(Value *Src, Value *Dest,
-                                 std::vector<MachineInstr*>& mvec) const {
+                              std::vector<MachineInstr*>& mvec) const {
   int RegType = getRegTypeForDataType(Src->getType());
   MachineInstr * MI = NULL;
 
-  switch( RegType ) {
+  switch (RegType) {
   case IntRegType:
     MI = BuildMI(V9::ADDr, 3).addReg(Src).addMReg(getZeroRegNum())
       .addRegDef(Dest);
@@ -945,7 +936,7 @@ SparcV9RegInfo::cpValue2Value(Value *Src, Value *Dest,
     MI = BuildMI(V9::FMOVD, 2).addReg(Src).addRegDef(Dest);
     break;
   default:
-    assert(0 && "Unknow RegType in CpValu2Value");
+    assert(0 && "Unknown RegType in cpValue2Value");
   }
 
   mvec.push_back(MI);