arch-riscv: Fix c.jalr and c.jr instruction (#1163)
The bit 0 of register should be 0 for jump address. Wrong handling the jump address may cause infinite run or segment fault. gem5 issue: https://github.com/gem5/gem5/issues/981
This commit is contained in:
@@ -448,12 +448,12 @@ decode QUADRANT default Unknown::unknown() {
|
||||
}
|
||||
0x4: decode CFUNCT1 {
|
||||
0x0: decode RC2 {
|
||||
0x0: Jump::c_jr({{
|
||||
0x0: CJump::c_jr({{
|
||||
if (RC1 == 0) {
|
||||
return std::make_shared<IllegalInstFault>(
|
||||
"source reg x0", machInst);
|
||||
}
|
||||
NPC = rvZext(Rc1);
|
||||
NPC = rvZext(Rc1 & (~0x1));
|
||||
}}, IsIndirectControl, IsUncondControl);
|
||||
default: CROp::c_mv({{
|
||||
// RC1 == 0 is HINT
|
||||
@@ -468,9 +468,9 @@ decode QUADRANT default Unknown::unknown() {
|
||||
return std::make_shared<BreakpointFault>(
|
||||
xc->pcState());
|
||||
}}, IsSerializeAfter, IsNonSpeculative, No_OpClass);
|
||||
default: Jump::c_jalr({{
|
||||
default: CJump::c_jalr({{
|
||||
ra = rvSext(NPC);
|
||||
NPC = rvZext(Rc1);
|
||||
NPC = rvZext(Rc1 & (~0x1));
|
||||
}}, IsIndirectControl, IsUncondControl, IsCall);
|
||||
}
|
||||
default: CompressedROp::c_add({{
|
||||
|
||||
@@ -157,6 +157,36 @@ def template CBasicExecute {{
|
||||
}
|
||||
}};
|
||||
|
||||
def template CJumpExecute {{
|
||||
Fault
|
||||
%(class_name)s::execute(
|
||||
ExecContext *xc, trace::InstRecord *traceData) const
|
||||
{
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(code)s;
|
||||
%(op_wb)s;
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
std::unique_ptr<PCStateBase>
|
||||
%(class_name)s::branchTarget(ThreadContext *tc) const
|
||||
{
|
||||
PCStateBase *pc_ptr = tc->pcState().clone();
|
||||
pc_ptr->as<PCState>().set(tc->getReg(srcRegIdx(0)) & ~0x1);
|
||||
return std::unique_ptr<PCStateBase>{pc_ptr};
|
||||
}
|
||||
|
||||
std::string
|
||||
%(class_name)s::generateDisassembly(
|
||||
Addr pc, const loader::SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << mnemonic << ' ' << registerName(srcRegIdx(0));
|
||||
return ss.str();
|
||||
}
|
||||
}};
|
||||
|
||||
def format CompressedROp(code, *opt_flags) {{
|
||||
regs = ['destRegIdx(0)','srcRegIdx(1)']
|
||||
iop = InstObjParams(name, Name, 'RegOp',
|
||||
@@ -166,3 +196,14 @@ def format CompressedROp(code, *opt_flags) {{
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = CBasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format CJump(code, *opt_flags) {{
|
||||
regs = ['srcRegIdx(0)']
|
||||
iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
|
||||
{'code': code, 'imm_code': 'imm = 0;',
|
||||
'regs': ','.join(regs)}, opt_flags)
|
||||
header_output = JumpDeclare.subst(iop)
|
||||
decoder_output = JumpConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = CJumpExecute.subst(iop)
|
||||
}};
|
||||
|
||||
@@ -315,12 +315,8 @@ def template JumpExecute {{
|
||||
Addr pc, const loader::SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << mnemonic << ' ';
|
||||
if (QUADRANT == 0x3)
|
||||
ss << registerName(destRegIdx(0)) << ", "
|
||||
<< imm << "(" << registerName(srcRegIdx(0)) << ")";
|
||||
else
|
||||
ss << registerName(srcRegIdx(0));
|
||||
ss << mnemonic << ' ' << registerName(destRegIdx(0)) << ", "
|
||||
<< imm << "(" << registerName(srcRegIdx(0)) << ")";
|
||||
return ss.str();
|
||||
}
|
||||
}};
|
||||
|
||||
Reference in New Issue
Block a user