From: Matt Horsnell Date: Tue, 18 Jan 2011 22:30:05 +0000 (-0600) Subject: ARM: The ARM decoder should not panic when decoding undefined holes is arch. X-Git-Tag: stable_2012_02_02~643 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=adbd84ab9fffdcdce18f564acffa508c10164c9f;p=gem5.git ARM: The ARM decoder should not panic when decoding undefined holes is arch. This can abort simulations when the fetch unit runs ahead and speculatively decodes instructions that are off the execution path. --- diff --git a/src/arch/arm/insts/macromem.cc b/src/arch/arm/insts/macromem.cc index f64fbeff9..2a45cf2e6 100644 --- a/src/arch/arm/insts/macromem.cc +++ b/src/arch/arm/insts/macromem.cc @@ -42,7 +42,9 @@ #include "arch/arm/insts/macromem.hh" #include "arch/arm/decoder.hh" +#include +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) { diff --git a/src/arch/arm/insts/pred_inst.hh b/src/arch/arm/insts/pred_inst.hh index f779b46f5..c441d1f32 100644 --- a/src/arch/arm/insts/pred_inst.hh +++ b/src/arch/arm/insts/pred_inst.hh @@ -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; } diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa index 9d40a4a43..3a0cad1c5 100644 --- a/src/arch/arm/isa/formats/fp.isa +++ b/src/arch/arm/isa/formats/fp.isa @@ -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) { diff --git a/src/arch/arm/isa/formats/misc.isa b/src/arch/arm/isa/formats/misc.isa index c2003fe6d..6a734a582 100644 --- a/src/arch/arm/isa/formats/misc.isa +++ b/src/arch/arm/isa/formats/misc.isa @@ -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); diff --git a/src/arch/arm/isa/insts/neon.isa b/src/arch/arm/isa/insts/neon.isa index a2948b90a..5aca525a4 100644 --- a/src/arch/arm/isa/insts/neon.isa +++ b/src/arch/arm/isa/insts/neon.isa @@ -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]; } } ''' diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc index fd861befc..13dec0add 100644 --- a/src/arch/arm/miscregs.cc +++ b/src/arch/arm/miscregs.cc @@ -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; }