Added code to handle spilling and reloading of FSRs.
authorSanjiv Gupta <sanjiv.gupta@microchip.com>
Fri, 10 Apr 2009 15:10:14 +0000 (15:10 +0000)
committerSanjiv Gupta <sanjiv.gupta@microchip.com>
Fri, 10 Apr 2009 15:10:14 +0000 (15:10 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68783 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PIC16/PIC16ISelLowering.cpp
lib/Target/PIC16/PIC16ISelLowering.h
lib/Target/PIC16/PIC16InstrInfo.cpp
lib/Target/PIC16/PIC16InstrInfo.td

index 550ac5bc289325258fec9fcd78c6844fa6324912..e0603bbbef26867d4a7da5fc8648fe00740d864b 100644 (file)
@@ -153,7 +153,7 @@ static SDValue getOutFlag(SDValue &Op) {
   return Flag;
 }
 // Get the TmpOffset for FrameIndex
-unsigned PIC16TargetLowering::GetTmpOffsetForFI(unsigned FI) {
+unsigned PIC16TargetLowering::GetTmpOffsetForFI(unsigned FI, unsigned size) {
   std::map<unsigned, unsigned>::iterator 
             MapIt = FiTmpOffsetMap.find(FI);
   if (MapIt != FiTmpOffsetMap.end())
@@ -161,7 +161,8 @@ unsigned PIC16TargetLowering::GetTmpOffsetForFI(unsigned FI) {
 
   // This FI (FrameIndex) is not yet mapped, so map it
   FiTmpOffsetMap[FI] = TmpSize; 
-  return TmpSize++;
+  TmpSize += size;
+  return FiTmpOffsetMap[FI];
 }
 
 // To extract chain value from the SDValue Nodes
@@ -849,14 +850,14 @@ SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op,
                                DAG.getEntryNode(),
                                Op, ES, 
                                DAG.getConstant (1, MVT::i8), // Banksel.
-                               DAG.getConstant (GetTmpOffsetForFI(FI), 
+                               DAG.getConstant (GetTmpOffsetForFI(FI, 1), 
                                                 MVT::i8));
 
   // Load the value from ES.
   SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other);
   SDValue Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Store,
                              ES, DAG.getConstant (1, MVT::i8),
-                             DAG.getConstant (GetTmpOffsetForFI(FI), 
+                             DAG.getConstant (GetTmpOffsetForFI(FI, 1), 
                              MVT::i8));
     
   return Load.getValue(0);
index 8b441c861a18831139ff01338b39c86bf3d1dec1..03397beab1891a8495c8dba7b24f9e4cdd89daaa 100644 (file)
@@ -137,7 +137,7 @@ namespace llvm {
     // This function returns the Tmp Offset for FrameIndex. If any TmpOffset 
     // already exists for the FI then it returns the same else it creates the 
     // new offset and returns.
-    unsigned GetTmpOffsetForFI(unsigned FI); 
+    unsigned GetTmpOffsetForFI(unsigned FI, unsigned slot_size); 
     void ResetTmpOffsetMap() { FiTmpOffsetMap.clear(); SetTmpSize(0); }
 
     // Return the size of Tmp variable 
index 99c27fdac77fb0b67b50d268a527286121596c87..8d8a0199540134cfc7eb758f120c16e2fa77c35e 100644 (file)
@@ -85,12 +85,25 @@ void PIC16InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
     //MachineRegisterInfo &RI = MF.getRegInfo();
     BuildMI(MBB, I, DL, get(PIC16::movwf))
       .addReg(SrcReg, false, false, isKill)
-      .addImm(PTLI->GetTmpOffsetForFI(FI))
+      .addImm(PTLI->GetTmpOffsetForFI(FI, 1))
+      .addExternalSymbol(tmpName)
+      .addImm(1); // Emit banksel for it.
+  }
+  else if (RC == PIC16::FSR16RegisterClass) {
+    // This is a 16-bit register and the frameindex given by llvm is of
+    // size two here. Break this index N into two zero based indexes and 
+    // put one into the map. The second one is always obtained by adding 1
+    // to the first zero based index. In fact it is going to use 3 slots
+    // as saving FSRs corrupts W also and hence we need to save/restore W also.
+
+    unsigned opcode = (SrcReg == PIC16::FSR0) ? PIC16::save_fsr0 
+                                                 : PIC16::save_fsr1;
+    BuildMI(MBB, I, DL, get(opcode))
+      .addReg(SrcReg, false, false, isKill)
+      .addImm(PTLI->GetTmpOffsetForFI(FI, 3))
       .addExternalSymbol(tmpName)
       .addImm(1); // Emit banksel for it.
   }
-  else if (RC == PIC16::FSR16RegisterClass)
-    assert(0 && "Don't know yet how to store a FSR16 to stack slot");
   else
     assert(0 && "Can't store this register to stack slot");
 }
@@ -114,12 +127,24 @@ void PIC16InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
     //MachineFunction &MF = *MBB.getParent();
     //MachineRegisterInfo &RI = MF.getRegInfo();
     BuildMI(MBB, I, DL, get(PIC16::movf), DestReg)
-      .addImm(PTLI->GetTmpOffsetForFI(FI))
+      .addImm(PTLI->GetTmpOffsetForFI(FI, 1))
+      .addExternalSymbol(tmpName)
+      .addImm(1); // Emit banksel for it.
+  }
+  else if (RC == PIC16::FSR16RegisterClass) {
+    // This is a 16-bit register and the frameindex given by llvm is of
+    // size two here. Break this index N into two zero based indexes and 
+    // put one into the map. The second one is always obtained by adding 1
+    // to the first zero based index. In fact it is going to use 3 slots
+    // as saving FSRs corrupts W also and hence we need to save/restore W also.
+
+    unsigned opcode = (DestReg == PIC16::FSR0) ? PIC16::restore_fsr0 
+                                                 : PIC16::restore_fsr1;
+    BuildMI(MBB, I, DL, get(opcode), DestReg)
+      .addImm(PTLI->GetTmpOffsetForFI(FI, 3))
       .addExternalSymbol(tmpName)
       .addImm(1); // Emit banksel for it.
   }
-  else if (RC == PIC16::FSR16RegisterClass)
-    assert(0 && "Don't know yet how to load an FSR16 from stack slot");
   else
     assert(0 && "Can't load this register from stack slot");
 }
index 04c3fc6eb8d320bdf959aba12098ccb660e6a98e..abdabc68ca919912da128e9fcf0e1da5018701f9 100644 (file)
@@ -232,6 +232,24 @@ def copy_fsr:
 def copy_w:
   Pseudo<(outs GPR:$dst), (ins GPR:$src), "copy_w $dst, $src", []>;
 
+class SAVE_FSR<string OpcStr>:
+  Pseudo<(outs), 
+         (ins FSR16:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), 
+         !strconcat(OpcStr, " $ptrlo, $offset"),
+         []>; 
+def save_fsr0: SAVE_FSR<"save_fsr0">;
+def save_fsr1: SAVE_FSR<"save_fsr1">;
+
+class RESTORE_FSR<string OpcStr>:
+  Pseudo<(outs FSR16:$dst), 
+         (ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi), 
+         !strconcat(OpcStr, " $ptrlo, $offset"),
+         []>; 
+
+def restore_fsr0: RESTORE_FSR<"restore_fsr0">;
+def restore_fsr1: RESTORE_FSR<"restore_fsr1">;
+
 //--------------------------
 // Store to memory
 //-------------------------
@@ -397,19 +415,22 @@ def sublw_cc : SUBLW<0, PIC16Subcc>;
 }
 
 // Call instruction.
-let isCall = 1 in {
+let isCall = 1,
+    Defs = [W, FSR0, FSR1] in {
     def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func),
             "call ${func} + 2",
             [(PIC16call diraddr:$func)]>;
 }
 
-let isCall = 1 in {
+let isCall = 1,
+    Defs = [W, FSR0, FSR1] in {
     def CALL_1: LiteralFormat<0x1, (outs), (ins GPR:$func, PCLATHR:$pc),
             "callw",
             [(PIC16call (PIC16Connect GPR:$func, PCLATHR:$pc))]>;
 }
 
-let isCall = 1  in {
+let isCall = 1,
+    Defs = [FSR0, FSR1] in {
     def CALLW: LiteralFormat<0x1, (outs GPR:$dest), 
                                   (ins GPR:$func, PCLATHR:$pc),
             "callw",