Expand .cprestore directive to multiple instructions if the offset does not fit
authorAkira Hatanaka <ahatanaka@mips.com>
Tue, 13 Dec 2011 03:09:05 +0000 (03:09 +0000)
committerAkira Hatanaka <ahatanaka@mips.com>
Tue, 13 Dec 2011 03:09:05 +0000 (03:09 +0000)
in a 16-bit field.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146469 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/MipsAsmPrinter.cpp
lib/Target/Mips/MipsMCInstLower.cpp
lib/Target/Mips/MipsMCInstLower.h

index cc25c4c7bd265fc24492318f6ece3d5f498588a4..a5505d36937f868750efb00ae6712429eed1c3fa 100644 (file)
@@ -96,19 +96,17 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
 
   if (!OutStreamer.hasRawTextSupport()) {
     // Lower CPLOAD and CPRESTORE
-    if (Opc == Mips::CPLOAD) {
+    if (Opc == Mips::CPLOAD)
       MCInstLowering.LowerCPLOAD(MI, MCInsts);
-      for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); I
-          != MCInsts.end(); ++I)
+    else if (Opc == Mips::CPRESTORE)
+      MCInstLowering.LowerCPRESTORE(MI, MCInsts);
+    
+    if (!MCInsts.empty()) {
+      for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin();
+           I != MCInsts.end(); ++I)
         OutStreamer.EmitInstruction(*I);
       return;
     }
-
-    if (Opc == Mips::CPRESTORE) {
-      MCInstLowering.LowerCPRESTORE(MI, TmpInst0);
-      OutStreamer.EmitInstruction(TmpInst0);
-      return;
-    }
   }
 
   OutStreamer.EmitInstruction(TmpInst0);
index 81812919ec5b266a4424865d65c43c60179b0e1e..de65881b79484bd1d10b67a85a03122f6711f3f2 100644 (file)
@@ -137,14 +137,35 @@ void MipsMCInstLower::LowerCPLOAD(const MachineInstr *MI,
 }
 
 // Lower ".cprestore offset" to "sw $gp, offset($sp)".
-void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, MCInst &OutMI) {
-  OutMI.clear();
-  OutMI.setOpcode(Mips::SW);
-  OutMI.addOperand(MCOperand::CreateReg(Mips::GP));
-  OutMI.addOperand(MCOperand::CreateReg(Mips::SP));
+void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI,
+                                     SmallVector<MCInst, 4>& MCInsts) {
   const MachineOperand &MO = MI->getOperand(0);
   assert(MO.isImm() && "CPRESTORE's operand must be an immediate.");
-  OutMI.addOperand(MCOperand::CreateImm(MO.getImm()));
+  unsigned Offset = MO.getImm(), Reg = Mips::SP;
+  MCInst Sw;
+
+  if (Offset >= 0x8000) {
+    unsigned Hi = (Offset >> 16) + ((Offset & 0x8000) != 0); 
+    Offset &= 0xffff;
+    Reg = Mips::AT;
+
+    // lui   at,hi
+    // addu  at,at,sp
+    MCInsts.resize(2);
+    MCInsts[0].setOpcode(Mips::LUi);
+    MCInsts[0].addOperand(MCOperand::CreateReg(Mips::AT));
+    MCInsts[0].addOperand(MCOperand::CreateImm(Hi));
+    MCInsts[1].setOpcode(Mips::ADDu);
+    MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT));
+    MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT));
+    MCInsts[1].addOperand(MCOperand::CreateReg(Mips::SP));
+  }
+  
+  Sw.setOpcode(Mips::SW);
+  Sw.addOperand(MCOperand::CreateReg(Mips::GP));
+  Sw.addOperand(MCOperand::CreateReg(Reg));
+  Sw.addOperand(MCOperand::CreateImm(Offset));
+  MCInsts.push_back(Sw);
 }
 
 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO,
index 98e37e4934b5e8b31db4ac39599e42403c8f11b3..1490c142e247311bae07ab9e875b47bedba4ebe6 100644 (file)
@@ -36,7 +36,7 @@ public:
                   MipsAsmPrinter &asmprinter);  
   void Lower(const MachineInstr *MI, MCInst &OutMI) const;
   void LowerCPLOAD(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts);
-  void LowerCPRESTORE(const MachineInstr *MI, MCInst &OutMI);
+  void LowerCPRESTORE(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts); 
   void LowerUnalignedLoadStore(const MachineInstr *MI,
                                           SmallVector<MCInst, 4>& MCInsts);
 private: