arch-arm: Unify VLdmStm behaviour when reg out of index
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 19 Nov 2019 11:29:39 +0000 (11:29 +0000)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 10 Dec 2019 10:15:05 +0000 (10:15 +0000)
The generic VLdmStm class (modelling A32 VLDM/VSTM) is handling a wrong
register list in a inconsistent way. Some instructions are opting
for being decoded as Unknown, while others handle it inside the
macro instruction constructor by manually adjusting the reglist.

Those are two valid implementation of the CONSTRAINT UNPREDICTABLE
behaviour (1 and 3):

"If regs > 16 || (d+regs) > 32 , then one of the following behaviors must
occur:
1) The instruction is UNDEFINED .
2) The instruction executes as NOP .
3)  One or more of the SIMD and floating-point registers are UNKNOWN . If
the instruction specifies writeback, the base register becomes UNKNOWN .
This behavior does not affect any general-purpose registers."

This patch unfies the behaviour by always opting for option 1) over 3)

Change-Id: I4f98409243d5a2ec64113fe9c87e961a391abe94
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Ciro Santilli <ciro.santilli@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23106
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/arm/insts/macromem.cc
src/arch/arm/isa/formats/fp.isa

index 7ed62f283ccb7204d48c8d04af69fd82b9ad8d09..e6de8321d1400877c33fad810b8257d03241ad14 100644 (file)
@@ -1446,15 +1446,6 @@ MacroVFPMemOp::MacroVFPMemOp(const char *mnem, ExtMachInst machInst,
     // 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 > NumFloatV7ArchRegs)
-        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 > NumFloatV7ArchRegs)
-        count = NumFloatV7ArchRegs;
-
     numMicroops = count * (single ? 1 : 2) + (writeback ? 1 : 0);
     microOps = new StaticInstPtr[numMicroops];
 
index a87988f141f50f1e1fb7ccbaad68e82c75a6d314..133f918d92e587927c8716e5dd7ea8d8d8d41b96 100644 (file)
@@ -1873,10 +1873,29 @@ def format ThumbNeonData() {{
 
 let {{
     header_output = '''
+    bool
+    wrongVLdmStmRegs(IntRegIndex start_reg, uint8_t count, bool single);
+
     StaticInstPtr
     decodeExtensionRegLoadStore(ExtMachInst machInst);
     '''
     decoder_output = '''
+    bool
+    wrongVLdmStmRegs(RegIndex start_reg, uint8_t count, bool single)
+    {
+        if (single) {
+            const auto regs = count;
+            if (regs == 0 || start_reg + regs > NumFloatV7ArchRegs)
+                return true;
+        } else {
+            const auto regs = count/2;
+            if (regs == 0 || start_reg + regs > NumFloatV7ArchRegs ||
+                regs > 16)
+                return true;
+        }
+        return false;
+    }
+
     StaticInstPtr
     decodeExtensionRegLoadStore(ExtMachInst machInst)
     {
@@ -1923,7 +1942,7 @@ let {{
             break;
           case 0x1:
             {
-                if (offset == 0 || vd + offset/2 > NumFloatV7ArchRegs) {
+                if (wrongVLdmStmRegs(vd, offset, single)) {
                     break;
                 }
                 switch (bits(opcode, 1, 0)) {
@@ -1946,12 +1965,20 @@ let {{
             }
           case 0x2:
             if (bits(opcode, 1, 0) == 0x2) {
-                // If rn == sp, then this is called vpush.
-                return new VLdmStm(machInst, rn, vd, single,
-                                   false, true, false, offset);
+                if (wrongVLdmStmRegs(vd, offset, single)) {
+                    break;
+                } else {
+                    // If rn == sp, then this is called vpush.
+                    return new VLdmStm(machInst, rn, vd, single,
+                                       false, true, false, offset);
+                }
             } else if (bits(opcode, 1, 0) == 0x3) {
-                return new VLdmStm(machInst, rn, vd, single,
-                                   false, true, true, offset);
+                if (wrongVLdmStmRegs(vd, offset, single)) {
+                    break;
+                } else {
+                    return new VLdmStm(machInst, rn, vd, single,
+                                       false, true, true, offset);
+                }
             }
             M5_FALLTHROUGH;
           case 0x3: