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.
This commit is contained in:
Matt Horsnell 2011-01-18 16:30:05 -06:00
parent 11bef2ab38
commit adbd84ab9f
6 changed files with 105 additions and 49 deletions

View 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) {

View 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;
}

View 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) {

View 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);

View 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];
}
}
'''

View 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;
}