ARM: Add base classes for VFP load/store multiple.
authorGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:04 +0000 (12:58 -0500)
committerGabe Black <gblack@eecs.umich.edu>
Wed, 2 Jun 2010 17:58:04 +0000 (12:58 -0500)
src/arch/arm/insts/macromem.cc
src/arch/arm/insts/macromem.hh

index bb69f0991e116823d903c758a456210d4131a1ea..35ec686febab62f844d857474efe0620ac71facc 100644 (file)
@@ -118,4 +118,64 @@ MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst,
     lastUop->setLastMicroop();
 }
 
+MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
+                             OpClass __opClass, IntRegIndex rn,
+                             RegIndex vd, bool single, bool up,
+                             bool writeback, bool load, uint32_t offset) :
+    PredMacroOp(mnem, machInst, __opClass)
+{
+    const int maxMicroops = 17;
+    microOps = new StaticInstPtr[maxMicroops];
+    int i = 0;
+
+    // The lowest order bit selects fldmx (set) or fldmd (clear). These seem
+    // to be functionally identical except that fldmx is deprecated. For now
+    // we'll assume they're otherwise interchangable.
+    int count = (single ? offset : (offset / 2));
+    if (count == 0 || count > NumFloatArchRegs)
+        warn_once("Bad offset field for VFP load/store multiple.\n");
+    if (count == 0) {
+        // Force there to be at least one microop so the macroop makes sense.
+        writeback = true;
+    }
+    if (count > NumFloatArchRegs)
+        count = NumFloatArchRegs;
+
+    uint32_t addr = 0;
+
+    if (up)
+        addr = -4 * offset;
+
+    for (int j = 0; j < count; j++) {
+        if (load) {
+            microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
+                                              true, addr);
+            if (!single)
+                microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
+                                                  true, addr + 4);
+        } else {
+            microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
+                                              true, addr);
+            if (!single)
+                microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
+                                                  true, addr + 4);
+        }
+        addr += (single ? 4 : 8);
+    }
+
+    if (writeback) {
+        if (up) {
+            microOps[i++] =
+                new MicroAddiUop(machInst, rn, rn, 4 * offset);
+        } else {
+            microOps[i++] =
+                new MicroSubiUop(machInst, rn, rn, 4 * offset);
+        }
+    }
+
+    numMicroops = i;
+    assert(numMicroops <= maxMicroops);
+    microOps[numMicroops - 1]->setLastMicroop();
+}
+
 }
index 8cad327109330ae1bac10fdc23df69424dff3e6d..21a37a29eda652c246b29805cdaa2938c782bce3 100644 (file)
@@ -101,6 +101,14 @@ class MacroMemOp : public PredMacroOp
                bool writeback, bool load, uint32_t reglist);
 };
 
+class MacroVFPMemOp : public PredMacroOp
+{
+  protected:
+    MacroVFPMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
+                  IntRegIndex rn, RegIndex vd, bool single, bool up,
+                  bool writeback, bool load, uint32_t offset);
+};
+
 }
 
 #endif //__ARCH_ARM_INSTS_MACROMEM_HH__