summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-11-08 15:16:59 -0800
committerGabe Black <gblack@eecs.umich.edu>2009-11-08 15:16:59 -0800
commitbb903b6514b743e93e429929776639879d6c59a7 (patch)
tree69301521ea20f59a8d34c3c25e4935a63e258d68 /src/arch/arm
parent48525f581c6233b8f7a8a872c5774d4e245f431c (diff)
downloadgem5-bb903b6514b743e93e429929776639879d6c59a7.tar.xz
ARM: Simplify the load/store multiple generation code.
Specifically, get rid of the big switch statement so more cases can be handled. Enumerating all the possible settings doesn't scale well. Also do some minor style clean up.
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/isa/formats/macromem.isa83
1 files changed, 27 insertions, 56 deletions
diff --git a/src/arch/arm/isa/formats/macromem.isa b/src/arch/arm/isa/formats/macromem.isa
index d978967ac..8c8ba8a1a 100644
--- a/src/arch/arm/isa/formats/macromem.isa
+++ b/src/arch/arm/isa/formats/macromem.isa
@@ -178,75 +178,46 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
{
%(constructor)s;
- uint32_t regs_to_handle = reglist;
- uint32_t start_addr = 0;
+ uint32_t regs = reglist;
+ uint32_t addr = 0;
- switch (puswl)
- {
- case 0x00: // stmda
- case 0x01: // L ldmda_l
- case 0x02: // W stmda_w
- case 0x03: // WL ldmda_wl
- start_addr = (ones << 2) - 4;
- break;
- case 0x08: // U stmia_u
- case 0x09: // U L ldmia_ul
- case 0x0a: // U W stmia
- case 0x0b: // U WL ldmia
- start_addr = 0;
- break;
- case 0x10: // P stmdb
- case 0x11: // P L ldmdb
- case 0x12: // P W stmdb
- case 0x13: // P WL ldmdb
- start_addr = (ones << 2); // U-bit is already 0 for subtract
- break;
- case 0x18: // PU stmib
- case 0x19: // PU L ldmib
- case 0x1a: // PU W stmib
- case 0x1b: // PU WL ldmib
- start_addr = 4;
- break;
- default:
- panic("Unhandled Load/Store Multiple Instruction, "
- "puswl = 0x%x", (unsigned) puswl);
- break;
- }
+ if (!up)
+ addr = (ones << 2) - 4;
+
+ if (prepost)
+ addr += 4;
// Add 0 to Rn and stick it in ureg0.
// This is equivalent to a move.
microOps[0] = new MicroAddiUop(machInst, INTREG_UREG0, RN, 0);
- unsigned j = 0;
- for (int i = 1; i < ones+1; i++) {
- // Get next available bit for transfer
- while (! ( regs_to_handle & (1<<j)))
- j++;
- regs_to_handle &= ~(1<<j);
+ unsigned reg = 0;
+ for (int i = 1; i < ones + 1; i++) {
+ // Find the next register.
+ while (!bits(regs, reg))
+ reg++;
+ replaceBits(regs, reg, 0);
if (loadop)
- microOps[i] = new MicroLdrUop(machInst, j,
- INTREG_UREG0, start_addr);
+ microOps[i] = new MicroLdrUop(machInst, reg, INTREG_UREG0, addr);
else
- microOps[i] = new MicroStrUop(machInst, j,
- INTREG_UREG0, start_addr);
+ microOps[i] = new MicroStrUop(machInst, reg, INTREG_UREG0, addr);
if (up)
- start_addr += 4;
+ addr += 4;
else
- start_addr -= 4;
+ addr -= 4;
}
+ StaticInstPtr &lastUop = microOps[numMicroops - 1];
if (writeback) {
if (up) {
- microOps[numMicroops-1] =
- new MicroAddiUop(machInst, RN, RN, ones * 4);
+ lastUop = new MicroAddiUop(machInst, RN, RN, ones * 4);
} else {
- microOps[numMicroops-1] =
- new MicroSubiUop(machInst, RN, RN, ones * 4);
+ lastUop = new MicroSubiUop(machInst, RN, RN, ones * 4);
}
}
- microOps[numMicroops-1]->setLastMicroop();
+ lastUop->setLastMicroop();
}
}};
@@ -287,14 +258,14 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
if (writeback)
{
if (up) {
- microOps[numMicroops-1] =
+ microOps[numMicroops - 1] =
new MicroAddiUop(machInst, RN, RN, disp8);
} else {
- microOps[numMicroops-1] =
+ microOps[numMicroops - 1] =
new MicroSubiUop(machInst, RN, RN, disp8);
}
}
- microOps[numMicroops-1]->setLastMicroop();
+ microOps[numMicroops - 1]->setLastMicroop();
}
}};
@@ -318,14 +289,14 @@ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
if (writeback) {
if (up) {
- microOps[numMicroops-1] =
+ microOps[numMicroops - 1] =
new MicroAddiUop(machInst, RN, RN, disp8);
} else {
- microOps[numMicroops-1] =
+ microOps[numMicroops - 1] =
new MicroSubiUop(machInst, RN, RN, disp8);
}
}
- microOps[numMicroops-1]->setLastMicroop();
+ microOps[numMicroops - 1]->setLastMicroop();
}
}};