summaryrefslogtreecommitdiff
path: root/src/arch/arm/insts/macromem.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/insts/macromem.cc')
-rw-r--r--src/arch/arm/insts/macromem.cc32
1 files changed, 21 insertions, 11 deletions
diff --git a/src/arch/arm/insts/macromem.cc b/src/arch/arm/insts/macromem.cc
index e5c374089..8e9e60f30 100644
--- a/src/arch/arm/insts/macromem.cc
+++ b/src/arch/arm/insts/macromem.cc
@@ -136,8 +136,6 @@ MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
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
@@ -153,26 +151,39 @@ MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
if (count > NumFloatArchRegs)
count = NumFloatArchRegs;
+ numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0);
+ microOps = new StaticInstPtr[numMicroops];
+
uint32_t addr = 0;
- if (up)
- addr = -4 * offset;
+ if (!up)
+ addr = 4 * offset;
+ bool tempUp = up;
for (int j = 0; j < count; j++) {
if (load) {
microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
- true, addr);
+ tempUp, addr);
if (!single)
microOps[i++] = new MicroLdrFpUop(machInst, vd++, rn,
- true, addr + 4);
+ tempUp, addr + 4);
} else {
microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
- true, addr);
+ tempUp, addr);
if (!single)
microOps[i++] = new MicroStrFpUop(machInst, vd++, rn,
- true, addr + 4);
+ tempUp, addr + 4);
+ }
+ if (!tempUp) {
+ addr -= (single ? 4 : 8);
+ // The microops don't handle negative displacement, so turn if we
+ // hit zero, flip polarity and start adding.
+ if (addr == 0) {
+ tempUp = true;
+ }
+ } else {
+ addr += (single ? 4 : 8);
}
- addr += (single ? 4 : 8);
}
if (writeback) {
@@ -185,8 +196,7 @@ MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
}
}
- numMicroops = i;
- assert(numMicroops <= maxMicroops);
+ assert(numMicroops == i);
microOps[numMicroops - 1]->setLastMicroop();
}