arch-riscv: Fix compressed branch op offset
There is a bug in RISC-V's compressed branch instructions where the
offsets are not stored in ImmOp's immediate field, causing incorrect
branchTarget() return values. This patch adds a new compressed branch
op format, CBOp, which correctly stores the offset.
Change-Id: Iac6e9b091d63f3dce4717ee5a9ec31a7cbd6c377
Reviewed-on: https://gem5-review.googlesource.com/8441
Reviewed-by: Tuan Ta <qtt2@cornell.edu>
Maintainer: Alec Roelke <ar4jc@virginia.edu>
diff --git a/src/arch/riscv/isa/decoder.isa b/src/arch/riscv/isa/decoder.isa
index ecee161..bbed650 100644
--- a/src/arch/riscv/isa/decoder.isa
+++ b/src/arch/riscv/isa/decoder.isa
@@ -212,30 +212,16 @@
offset |= ~((int64_t)0x7FF);
NPC = PC + offset;
}}, IsIndirectControl, IsUncondControl, IsCall);
- format BOp {
+ format CBOp {
0x6: c_beqz({{
- int64_t offset = CIMM5<2:1> << 1 |
- CIMM3<1:0> << 3 |
- CIMM5<0:0> << 5 |
- CIMM5<4:3> << 6;
- if (CIMM3<2:2> > 0)
- offset |= ~((int64_t)0xFF);
-
if (Rp1 == 0)
- NPC = PC + offset;
+ NPC = PC + imm;
else
NPC = NPC;
}}, IsDirectControl, IsCondControl);
0x7: c_bnez({{
- int64_t offset = CIMM5<2:1> << 1 |
- CIMM3<1:0> << 3 |
- CIMM5<0:0> << 5 |
- CIMM5<4:3> << 6;
- if (CIMM3<2:2> > 0)
- offset |= ~((int64_t)0xFF);
-
if (Rp1 != 0)
- NPC = PC + offset;
+ NPC = PC + imm;
else
NPC = NPC;
}}, IsDirectControl, IsCondControl);
diff --git a/src/arch/riscv/isa/formats/compressed.isa b/src/arch/riscv/isa/formats/compressed.isa
index 03b7fb1..3ebc1c6 100644
--- a/src/arch/riscv/isa/formats/compressed.isa
+++ b/src/arch/riscv/isa/formats/compressed.isa
@@ -47,6 +47,25 @@
exec_output = ImmExecute.subst(iop)
}};
+def format CBOp(code, *opt_flags) {{
+ imm_code = """
+ imm = CIMM5<2:1> << 1 |
+ CIMM3<1:0> << 3 |
+ CIMM5<0:0> << 5 |
+ CIMM5<4:3> << 6;
+ if (CIMM3<2:2> > 0)
+ imm |= ~((int64_t)0xFF);
+ """
+ regs = ['_srcRegIdx[0]','_srcRegIdx[1]']
+ iop = InstObjParams(name, Name, 'ImmOp<int64_t>',
+ {'code': code, 'imm_code': imm_code,
+ 'regs': ','.join(regs)}, opt_flags)
+ header_output = BranchDeclare.subst(iop)
+ decoder_output = ImmConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BranchExecute.subst(iop)
+}};
+
def format CompressedLoad(ldisp_code, memacc_code,
ea_code, mem_flags=[], inst_flags=[]) {{
(header_output, decoder_output, decode_block, exec_output) = \