arm: Fixed undefined behaviours identified by gcc

This patch fixes the runtime errors highlighted by the undefined
behaviour sanitizer. In the end there were two issues. First, when
rotating an immediate, we ended up shifting an uint32_t by 32 in some
cases. This case is fixed by checking for a rotation by 0
positions. Second, the Mrc15 and Mcr15 are operating on an IntReg and
a MiscReg, but we used the type RegRegImmOp and passed a MiscRegIndex
as an IntRegIndex. This issue is resolved by introducing a
MiscRegRegImmOp and RegMiscRegImmOp with the appropriate types.

With these fixes there are no runtime errors identified for the full
ARM regressions.
This commit is contained in:
Andreas Hansson 2014-09-27 09:08:37 -04:00
parent 341dbf2662
commit ec41000dad
7 changed files with 134 additions and 14 deletions

View file

@ -255,6 +255,30 @@ RegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
return ss.str();
}
std::string
MiscRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss);
printReg(ss, dest);
ss << ", ";
printReg(ss, op1);
ccprintf(ss, ", #%d", imm);
return ss.str();
}
std::string
RegMiscRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss);
printReg(ss, dest);
ss << ", ";
printReg(ss, op1);
ccprintf(ss, ", #%d", imm);
return ss.str();
}
std::string
RegImmImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{

View file

@ -256,6 +256,40 @@ class RegRegImmOp : public PredOp
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
class MiscRegRegImmOp : public PredOp
{
protected:
MiscRegIndex dest;
IntRegIndex op1;
uint64_t imm;
MiscRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
MiscRegIndex _dest, IntRegIndex _op1,
uint64_t _imm) :
PredOp(mnem, _machInst, __opClass),
dest(_dest), op1(_op1), imm(_imm)
{}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
class RegMiscRegImmOp : public PredOp
{
protected:
IntRegIndex dest;
MiscRegIndex op1;
uint64_t imm;
RegMiscRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _dest, MiscRegIndex _op1,
uint64_t _imm) :
PredOp(mnem, _machInst, __opClass),
dest(_dest), op1(_op1), imm(_imm)
{}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
class RegImmImmOp : public PredOp
{
protected:

View file

@ -48,10 +48,11 @@
namespace ArmISA
{
static inline uint32_t
rotate_imm(uint32_t immValue, int rotateValue)
rotate_imm(uint32_t immValue, uint32_t rotateValue)
{
return ((immValue >> (rotateValue & 31)) |
(immValue << (32 - (rotateValue & 31))));
rotateValue &= 31;
return rotateValue == 0 ? immValue :
(immValue >> rotateValue) | (immValue << (32 - rotateValue));
}
static inline uint32_t

View file

@ -214,8 +214,8 @@ let {{
if (miscRegInfo[miscReg][MISCREG_IMPLEMENTED]) {
if (isRead)
return new Mrc15(machInst, rt, (IntRegIndex)miscReg, iss);
return new Mcr15(machInst, (IntRegIndex)miscReg, rt, iss);
return new Mrc15(machInst, rt, miscReg, iss);
return new Mcr15(machInst, miscReg, rt, iss);
} else {
return new FailUnimplemented(isRead ? "mrc" : "mcr", machInst,
csprintf("%s %s", isRead ? "mrc" : "mcr",

View file

@ -860,11 +860,11 @@ let {{
Dest = MiscNsBankedOp1;
'''
mrc15Iop = InstObjParams("mrc", "Mrc15", "RegRegImmOp",
mrc15Iop = InstObjParams("mrc", "Mrc15", "RegMiscRegImmOp",
{ "code": mrc15code,
"predicate_test": predicateTest }, [])
header_output += RegRegImmOpDeclare.subst(mrc15Iop)
decoder_output += RegRegImmOpConstructor.subst(mrc15Iop)
header_output += RegMiscRegImmOpDeclare.subst(mrc15Iop)
decoder_output += RegMiscRegImmOpConstructor.subst(mrc15Iop)
exec_output += PredOpExecute.subst(mrc15Iop)
@ -887,12 +887,12 @@ let {{
}
MiscNsBankedDest = Op1;
'''
mcr15Iop = InstObjParams("mcr", "Mcr15", "RegRegImmOp",
mcr15Iop = InstObjParams("mcr", "Mcr15", "MiscRegRegImmOp",
{ "code": mcr15code,
"predicate_test": predicateTest },
["IsSerializeAfter","IsNonSpeculative"])
header_output += RegRegImmOpDeclare.subst(mcr15Iop)
decoder_output += RegRegImmOpConstructor.subst(mcr15Iop)
header_output += MiscRegRegImmOpDeclare.subst(mcr15Iop)
decoder_output += MiscRegRegImmOpConstructor.subst(mcr15Iop)
exec_output += PredOpExecute.subst(mcr15Iop)

View file

@ -433,6 +433,66 @@ def template RegRegImmOpConstructor {{
}
}};
def template MiscRegRegImmOpDeclare {{
class %(class_name)s : public %(base_class)s
{
protected:
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
MiscRegIndex _dest, IntRegIndex _op1,
uint64_t _imm);
%(BasicExecDeclare)s
};
}};
def template MiscRegRegImmOpConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
MiscRegIndex _dest,
IntRegIndex _op1,
uint64_t _imm)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _imm)
{
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
}
}
}
}};
def template RegMiscRegImmOpDeclare {{
class %(class_name)s : public %(base_class)s
{
protected:
public:
// Constructor
%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest, MiscRegIndex _op1,
uint64_t _imm);
%(BasicExecDeclare)s
};
}};
def template RegMiscRegImmOpConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
IntRegIndex _dest,
MiscRegIndex _op1,
uint64_t _imm)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_dest, _op1, _imm)
{
%(constructor)s;
if (!(condCode == COND_AL || condCode == COND_UC)) {
for (int x = 0; x < _numDestRegs; x++) {
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
}
}
}
}};
def template RegImmImmOpDeclare {{
class %(class_name)s : public %(base_class)s
{

View file

@ -71,9 +71,10 @@ using namespace ArmISA;
TLB::TLB(const ArmTLBParams *p)
: BaseTLB(p), table(new TlbEntry[p->size]), size(p->size),
isStage2(p->is_stage2), tableWalker(p->walker), stage2Tlb(NULL),
stage2Mmu(NULL), rangeMRU(1), bootUncacheability(false),
miscRegValid(false), curTranType(NormalTran)
isStage2(p->is_stage2), stage2Req(false), _attr(0),
directToStage2(false), tableWalker(p->walker), stage2Tlb(NULL),
stage2Mmu(NULL), rangeMRU(1), bootUncacheability(false),
miscRegValid(false), curTranType(NormalTran)
{
tableWalker->setTlb(this);