summaryrefslogtreecommitdiff
path: root/src/arch/arm/isa
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:09 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:09 -0500
commit61a5e71be7408ebd05df7778e58ea46d3fdb9e73 (patch)
treebd73564a814fe883cdc0f811b3f12c5fb6f97314 /src/arch/arm/isa
parent9d4a1bf2ba936499277b96054fbc83c478c0c6be (diff)
downloadgem5-61a5e71be7408ebd05df7778e58ea46d3fdb9e73.tar.xz
ARM: Decode the thumb version of the ldrd and strd instructions.
Diffstat (limited to 'src/arch/arm/isa')
-rw-r--r--src/arch/arm/isa/formats/mem.isa58
1 files changed, 52 insertions, 6 deletions
diff --git a/src/arch/arm/isa/formats/mem.isa b/src/arch/arm/isa/formats/mem.isa
index 1c69a5e00..b055b080f 100644
--- a/src/arch/arm/isa/formats/mem.isa
+++ b/src/arch/arm/isa/formats/mem.isa
@@ -263,8 +263,8 @@ def format Thumb32LdrStrDExTbh() {{
const uint32_t op3 = bits(machInst, 7, 4);
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
- /* This isn't used yet, and that makes gcc upset. */
- //const IntRegIndex rt2 = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
+ const IntRegIndex rt2 = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
+ const uint32_t imm8 = bits(machInst, 7, 0);
if (bits(op1, 1) == 0 && bits(op2, 1) == 0) {
if (op1 == 0) {
const uint32_t imm = bits(machInst, 7, 0) << 2;
@@ -296,24 +296,70 @@ def format Thumb32LdrStrDExTbh() {{
case 0x5:
return new %(ldrexh)s(machInst, rt, rn, true, 0);
case 0x7:
- return new WarnUnimplemented("ldrexd", machInst);
+ return new %(ldrexd)s(machInst, rt, rt2, rn, true, 0);
default:
return new Unknown(machInst);
}
}
}
} else {
+ const uint32_t puw = (bits(machInst, 24, 23) << 1) |
+ bits(machInst, 21);
+ const uint32_t dimm = imm8 << 2;
if (bits(op2, 0) == 0) {
- return new WarnUnimplemented("strd", machInst);
+ switch (puw) {
+ case 0x1:
+ return new %(strd_w)s(machInst, rt, rt2, rn, false, dimm);
+ case 0x3:
+ return new %(strd_uw)s(machInst, rt, rt2, rn, true, dimm);
+ case 0x4:
+ return new %(strd_p)s(machInst, rt, rt2, rn, false, dimm);
+ case 0x5:
+ return new %(strd_pw)s(machInst, rt, rt2, rn, false, dimm);
+ case 0x6:
+ return new %(strd_pu)s(machInst, rt, rt2, rn, true, dimm);
+ case 0x7:
+ return new %(strd_puw)s(machInst, rt, rt2, rn, true, dimm);
+ default:
+ return new Unknown(machInst);
+ }
} else {
- return new WarnUnimplemented("ldrd", machInst);
+ switch (puw) {
+ case 0x1:
+ return new %(ldrd_w)s(machInst, rt, rt2, rn, false, dimm);
+ case 0x3:
+ return new %(ldrd_uw)s(machInst, rt, rt2, rn, true, dimm);
+ case 0x4:
+ return new %(ldrd_p)s(machInst, rt, rt2, rn, false, dimm);
+ case 0x5:
+ return new %(ldrd_pw)s(machInst, rt, rt2, rn, false, dimm);
+ case 0x6:
+ return new %(ldrd_pu)s(machInst, rt, rt2, rn, true, dimm);
+ case 0x7:
+ return new %(ldrd_puw)s(machInst, rt, rt2, rn, true, dimm);
+ default:
+ return new Unknown(machInst);
+ }
}
}
}
''' % {
"ldrex" : "LDREX_" + loadImmClassName(False, True, False, size=4),
"ldrexb" : "LDREXB_" + loadImmClassName(False, True, False, size=1),
- "ldrexh" : "LDREXH_" + loadImmClassName(False, True, False, size=2)
+ "ldrexh" : "LDREXH_" + loadImmClassName(False, True, False, size=2),
+ "ldrexd" : "LDREXD_" + loadDoubleImmClassName(False, True, False),
+ "ldrd_w" : loadDoubleImmClassName(True, False, True),
+ "ldrd_uw" : loadDoubleImmClassName(True, True, True),
+ "ldrd_p" : loadDoubleImmClassName(False, False, False),
+ "ldrd_pw" : loadDoubleImmClassName(False, False, True),
+ "ldrd_pu" : loadDoubleImmClassName(False, True, False),
+ "ldrd_puw" : loadDoubleImmClassName(False, True, True),
+ "strd_w" : storeDoubleImmClassName(True, False, True),
+ "strd_uw" : storeDoubleImmClassName(True, True, True),
+ "strd_p" : storeDoubleImmClassName(False, False, False),
+ "strd_pw" : storeDoubleImmClassName(False, False, True),
+ "strd_pu" : storeDoubleImmClassName(False, True, False),
+ "strd_puw" : storeDoubleImmClassName(False, True, True)
}
}};