ARM: The ARM decoder should not panic when decoding undefined holes is arch.
authorMatt Horsnell <Matt.Horsnell@ARM.com>
Tue, 18 Jan 2011 22:30:05 +0000 (16:30 -0600)
committerMatt Horsnell <Matt.Horsnell@ARM.com>
Tue, 18 Jan 2011 22:30:05 +0000 (16:30 -0600)
This can abort simulations when the fetch unit runs ahead and speculatively
decodes instructions that are off the execution path.

src/arch/arm/insts/macromem.cc
src/arch/arm/insts/pred_inst.hh
src/arch/arm/isa/formats/fp.isa
src/arch/arm/isa/formats/misc.isa
src/arch/arm/isa/insts/neon.isa
src/arch/arm/miscregs.cc

index f64fbeff94fa76df4c2354b3f459c5fbf89dd8a8..2a45cf2e680ae6c975c6091244c070527bae77e5 100644 (file)
@@ -42,7 +42,9 @@
 
 #include "arch/arm/insts/macromem.hh"
 #include "arch/arm/decoder.hh"
+#include <sstream>
 
+using namespace std;
 using namespace ArmISAInst;
 
 namespace ArmISA
@@ -180,7 +182,8 @@ VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
                 size, machInst, rMid, rn, 0, align);
         break;
       default:
-        panic("Unrecognized number of registers %d.\n", regs);
+        // Unknown number of registers
+        microOps[uopIdx++] = new Unknown(machInst);
     }
     if (wb) {
         if (rm != 15 && rm != 13) {
@@ -216,7 +219,8 @@ VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
             }
             break;
           default:
-            panic("Bad number of elements to deinterleave %d.\n", elems);
+            // Bad number of elements to deinterleave
+            microOps[uopIdx++] = new Unknown(machInst);
         }
     }
     assert(uopIdx == numMicroops);
@@ -315,7 +319,8 @@ VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
                 machInst, ufp0, rn, 0, align);
         break;
       default:
-        panic("Unrecognized load size %d.\n", regs);
+        // Unrecognized load size
+        microOps[uopIdx++] = new Unknown(machInst);
     }
     if (wb) {
         if (rm != 15 && rm != 13) {
@@ -358,7 +363,8 @@ VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
             }
             break;
           default:
-            panic("Bad size %d.\n", size);
+            // Bad size
+            microOps[uopIdx++] = new Unknown(machInst);
             break;
         }
         break;
@@ -393,7 +399,8 @@ VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
             }
             break;
           default:
-            panic("Bad size %d.\n", size);
+            // Bad size
+            microOps[uopIdx++] = new Unknown(machInst);
             break;
         }
         break;
@@ -429,7 +436,8 @@ VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
             }
             break;
           default:
-            panic("Bad size %d.\n", size);
+            // Bad size
+            microOps[uopIdx++] = new Unknown(machInst);
             break;
         }
         break;
@@ -472,13 +480,15 @@ VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
                 }
                 break;
               default:
-                panic("Bad size %d.\n", size);
+                // Bad size
+                microOps[uopIdx++] = new Unknown(machInst);
                 break;
             }
         }
         break;
       default:
-        panic("Bad number of elements to unpack %d.\n", elems);
+        // Bad number of elements to unpack
+        microOps[uopIdx++] = new Unknown(machInst);
     }
     assert(uopIdx == numMicroops);
 
@@ -536,7 +546,8 @@ VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
             }
             break;
           default:
-            panic("Bad number of elements to interleave %d.\n", elems);
+            // Bad number of elements to interleave
+            microOps[uopIdx++] = new Unknown(machInst);
         }
     }
     switch (regs) {
@@ -561,7 +572,8 @@ VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
                 size, machInst, rMid, rn, 0, align);
         break;
       default:
-        panic("Unrecognized number of registers %d.\n", regs);
+        // Unknown number of registers
+        microOps[uopIdx++] = new Unknown(machInst);
     }
     if (wb) {
         if (rm != 15 && rm != 13) {
@@ -627,7 +639,8 @@ VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
                     machInst, ufp0, vd * 2, inc * 2, lane);
             break;
           default:
-            panic("Bad size %d.\n", size);
+            // Bad size
+            microOps[uopIdx++] = new Unknown(machInst);
             break;
         }
         break;
@@ -647,7 +660,8 @@ VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
                     machInst, ufp0, vd * 2, inc * 2, lane);
             break;
           default:
-            panic("Bad size %d.\n", size);
+            // Bad size
+            microOps[uopIdx++] = new Unknown(machInst);
             break;
         }
         break;
@@ -668,7 +682,8 @@ VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
                     machInst, ufp0, vd * 2, inc * 2, lane);
             break;
           default:
-            panic("Bad size %d.\n", size);
+            // Bad size
+            microOps[uopIdx++] = new Unknown(machInst);
             break;
         }
         break;
@@ -690,13 +705,15 @@ VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
                         machInst, ufp0, (vd + offset) * 2, inc * 2, lane);
                 break;
               default:
-                panic("Bad size %d.\n", size);
+                // Bad size
+                microOps[uopIdx++] = new Unknown(machInst);
                 break;
             }
         }
         break;
       default:
-        panic("Bad number of elements to pack %d.\n", elems);
+        // Bad number of elements to unpack
+        microOps[uopIdx++] = new Unknown(machInst);
     }
     switch (storeSize) {
       case 1:
@@ -757,7 +774,8 @@ VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
                 machInst, ufp0, rn, 0, align);
         break;
       default:
-        panic("Unrecognized store size %d.\n", regs);
+        // Bad store size
+        microOps[uopIdx++] = new Unknown(machInst);
     }
     if (wb) {
         if (rm != 15 && rm != 13) {
index f779b46f5542061d0b8fb25e2ea9b3abd5612b1d..c441d1f32bfc418766c2714c7be6fe9fdfdb00eb 100644 (file)
@@ -78,9 +78,10 @@ modified_imm(uint8_t ctrlImm, uint8_t dataImm)
 }
 
 static inline uint64_t
-simd_modified_imm(bool op, uint8_t cmode, uint8_t data)
+simd_modified_imm(bool op, uint8_t cmode, uint8_t data, bool &immValid)
 {
     uint64_t bigData = data;
+    immValid = true;
     switch (cmode) {
       case 0x0:
       case 0x1:
@@ -139,9 +140,10 @@ simd_modified_imm(bool op, uint8_t cmode, uint8_t data)
             bigData |= (bigData << 32);
             break;
         }
-        // Fall through
+        // Fall through, immediate encoding is invalid.
       default:
-        panic("Illegal modified SIMD immediate parameters.\n");
+        immValid = false;
+        break;
     }
     return bigData;
 }
index 9d40a4a4326b9ee43341c70a5bd11198b0544cd3..3a0cad1c5e175e25859c5742db20320232d6773f 100644 (file)
@@ -758,7 +758,15 @@ let {{
                                       bits(machInst, 24)) << 7) |
                             (bits(machInst, 18, 16) << 4) |
                             (bits(machInst, 3, 0) << 0);
-        const uint64_t bigImm = simd_modified_imm(op, cmode, imm);
+
+        // Check for invalid immediate encodings and return an unknown op
+        // if it happens
+        bool immValid = true;
+        const uint64_t bigImm = simd_modified_imm(op, cmode, imm, immValid);
+        if (!immValid) {
+            return new Unknown(machInst);
+        }
+
         if (op) {
             if (bits(cmode, 3) == 0) {
                 if (bits(cmode, 0) == 0) {
index c2003fe6d169233b90f7a1266705d9f38e0f9ed7..6a734a5822bbceba7f95c9c7403bf31d2bdf5d47 100644 (file)
@@ -100,7 +100,10 @@ let {{
           case MISCREG_NOP:
             return new NopInst(machInst);
           case NUM_MISCREGS:
-            return new Unknown(machInst);
+            return new FailUnimplemented(
+                    csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown",
+                    crn, opc1, crm, opc2, isRead ? "read" : "write").c_str(),
+                    machInst);
           case MISCREG_DCCISW:
             return new WarnUnimplemented(
                     isRead ? "mrc dccisw" : "mcr dcisw", machInst);
index a2948b90ae153a563d5f21cacba8e5f427bd1bf8..5aca525a4ca4d97aaa7449eddd2f7c77c85ee053 100644 (file)
@@ -871,14 +871,21 @@ let {{
         if readDest:
             readDestCode = 'destElem = gtoh(destReg.elements[i]);'
         eWalkCode += '''
-        assert(imm >= 0 && imm < eCount);
-        for (unsigned i = 0; i < eCount; i++) {
-            Element srcElem1 = gtoh(srcReg1.elements[i]);
-            Element srcElem2 = gtoh(srcReg2.elements[imm]);
-            Element destElem;
-            %(readDest)s
-            %(op)s
-            destReg.elements[i] = htog(destElem);
+        if (imm < 0 && imm >= eCount) {
+#if FULL_SYSTEM
+            fault = new UndefinedInstruction;
+#else
+            fault = new UndefinedInstruction(false, mnemonic);
+#endif
+        } else {
+            for (unsigned i = 0; i < eCount; i++) {
+                Element srcElem1 = gtoh(srcReg1.elements[i]);
+                Element srcElem2 = gtoh(srcReg2.elements[imm]);
+                Element destElem;
+                %(readDest)s
+                %(op)s
+                destReg.elements[i] = htog(destElem);
+            }
         }
         ''' % { "op" : op, "readDest" : readDestCode }
         for reg in range(rCount):
@@ -919,14 +926,21 @@ let {{
         if readDest:
             readDestCode = 'destElem = gtoh(destReg.elements[i]);'
         eWalkCode += '''
-        assert(imm >= 0 && imm < eCount);
-        for (unsigned i = 0; i < eCount; i++) {
-            Element srcElem1 = gtoh(srcReg1.elements[i]);
-            Element srcElem2 = gtoh(srcReg2.elements[imm]);
-            BigElement destElem;
-            %(readDest)s
-            %(op)s
-            destReg.elements[i] = htog(destElem);
+        if (imm < 0 && imm >= eCount) {
+#if FULL_SYSTEM
+            fault = new UndefinedInstruction;
+#else
+            fault = new UndefinedInstruction(false, mnemonic);
+#endif
+        } else {
+            for (unsigned i = 0; i < eCount; i++) {
+                Element srcElem1 = gtoh(srcReg1.elements[i]);
+                Element srcElem2 = gtoh(srcReg2.elements[imm]);
+                BigElement destElem;
+                %(readDest)s
+                %(op)s
+                destReg.elements[i] = htog(destElem);
+            }
         }
         ''' % { "op" : op, "readDest" : readDestCode }
         for reg in range(2 * rCount):
@@ -965,14 +979,21 @@ let {{
         if readDest:
             readDestCode = 'destReg = destRegs[i];'
         eWalkCode += '''
-        assert(imm >= 0 && imm < rCount);
-        for (unsigned i = 0; i < rCount; i++) {
-            FloatReg srcReg1 = srcRegs1[i];
-            FloatReg srcReg2 = srcRegs2[imm];
-            FloatReg destReg;
-            %(readDest)s
-            %(op)s
-            destRegs[i] = destReg;
+        if (imm < 0 && imm >= eCount) {
+#if FULL_SYSTEM
+            fault = new UndefinedInstruction;
+#else
+            fault = new UndefinedInstruction(false, mnemonic);
+#endif
+        } else {
+            for (unsigned i = 0; i < rCount; i++) {
+                FloatReg srcReg1 = srcRegs1[i];
+                FloatReg srcReg2 = srcRegs2[imm];
+                FloatReg destReg;
+                %(readDest)s
+                %(op)s
+                destRegs[i] = destReg;
+            }
         }
         ''' % { "op" : op, "readDest" : readDestCode }
         for reg in range(rCount):
@@ -3277,8 +3298,14 @@ let {{
                 destReg.elements[i] = srcReg1.elements[index];
             } else {
                 index -= eCount;
-                assert(index < eCount);
-                destReg.elements[i] = srcReg2.elements[index];
+                if (index >= eCount)
+#if FULL_SYSTEM
+                    fault = new UndefinedInstruction;
+#else
+                    fault = new UndefinedInstruction(false, mnemonic);
+#endif
+                else
+                    destReg.elements[i] = srcReg2.elements[index];
             }
         }
     '''
index fd861befce381fd2db0892a9a7c4ee436c5e9435..13dec0add62d1417c8b5851d4bf3b361911756ca 100644 (file)
@@ -451,8 +451,6 @@ decodeCP15Reg(unsigned crn, unsigned opc1, unsigned crm, unsigned opc2)
         // Implementation defined
         break;
     }
-    warn("Unknown miscreg: CRn: %d Opc1: %d CRm: %d opc2: %d\n",
-            crn, opc1, crm, opc2);
     // Unrecognized register
     return NUM_MISCREGS;
 }