Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
---
target/riscv/insn16-32.decode | 24 ++++++++++++++++++++++++
target/riscv/insn16-64.decode | 31 +++++++++++++++++++++++++++++++
target/riscv/translate.c | 18 +++++++++++++++++-
target/riscv/meson.build | 7 +++++--
4 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/target/riscv/insn16-32.decode b/target/riscv/insn16-32.decode
index 0819b17028..f83f43e955 100644
--- a/target/riscv/insn16-32.decode
+++ b/target/riscv/insn16-32.decode
@@ -16,6 +16,30 @@
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
+# Fields imported from insn16.decode:
+%rd 7:5
+%rs1_3 7:3 !function=ex_rvc_register
+%rs2_3 2:3 !function=ex_rvc_register
+%rs2_5 2:5
+
+# Immediates imported from insn16.decode:
+%uimm_cl_w 5:1 10:3 6:1 !function=ex_shift_2
+%uimm_6bit_lw 2:2 12:1 4:3 !function=ex_shift_2
+%uimm_6bit_sw 7:2 9:4 !function=ex_shift_2
+%imm_cj 12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
+
+# Argument sets imported from insn16.decode:
+&j imm rd !extern
+&i imm rs1 rd !extern
+&s imm rs1 rs2 !extern
+
+# Formats 16 imported from insn16.decode:
+@cl_w ... ... ... .. ... .. &i imm=%uimm_cl_w rs1=%rs1_3 rd=%rs2_3
+@cj ... ........... .. &j imm=%imm_cj
+@c_lwsp ... . ..... ..... .. &i imm=%uimm_6bit_lw rs1=2 %rd
+@c_swsp ... . ..... ..... .. &s imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5
+@cs_w ... ... ... .. ... .. &s imm=%uimm_cl_w rs1=%rs1_3 rs2=%rs2_3
+
# *** RV32C Standard Extension (Quadrant 0) ***
flw 011 ... ... .. ... 00 @cl_w
fsw 111 ... ... .. ... 00 @cs_w
diff --git a/target/riscv/insn16-64.decode b/target/riscv/insn16-64.decode
index 672e1e916f..dbef1e5365 100644
--- a/target/riscv/insn16-64.decode
+++ b/target/riscv/insn16-64.decode
@@ -16,6 +16,37 @@
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
+# Fields imported from insn16.decode:
+%rd 7:5
+%rs1_3 7:3 !function=ex_rvc_register
+%rs2_3 2:3 !function=ex_rvc_register
+%rs2_5 2:5
+
+# Immediates imported from insn16.decode:
+%imm_ci 12:s1 2:5
+%uimm_cl_d 5:2 10:3 !function=ex_shift_3
+%uimm_6bit_ld 2:3 12:1 5:2 !function=ex_shift_3
+%uimm_6bit_lw 2:2 12:1 4:3 !function=ex_shift_2
+%uimm_6bit_sd 7:3 10:3 !function=ex_shift_3
+
+# Argument sets imported from insn16.decode:
+&empty !extern
+&r rd rs1 rs2 !extern
+&i imm rs1 rd !extern
+&s imm rs1 rs2 !extern
+&j imm rd !extern
+&b imm rs2 rs1 !extern
+&u imm rd !extern
+&shift shamt rs1 rd !extern
+
+# Formats 16 imported from insn16.decode:
+@ci ... . ..... ..... .. &i imm=%imm_ci rs1=%rd %rd
+@cl_d ... ... ... .. ... .. &i imm=%uimm_cl_d rs1=%rs1_3 rd=%rs2_3
+@cs_d ... ... ... .. ... .. &s imm=%uimm_cl_d rs1=%rs1_3 rs2=%rs2_3
+@cs_2 ... ... ... .. ... .. &r rs2=%rs2_3 rs1=%rs1_3 rd=%rs1_3
+@c_ldsp ... . ..... ..... .. &i imm=%uimm_6bit_ld rs1=2 %rd
+@c_sdsp ... . ..... ..... .. &s imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5
+
# *** RV64C Standard Extension (Quadrant 0) ***
ld 011 ... ... .. ... 00 @cl_d
sd 111 ... ... .. ... 00 @cs_d
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 4af55deaea..9a93c77fd6 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -602,6 +602,10 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
/* Include the auto-generated decoder for 16 bit insn */
#include "decode-insn16.c.inc"
+#include "decode-insn16-32.c.inc"
+#ifdef TARGET_RISCV64
+# include "decode-insn16-64.c.inc"
+#endif
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
{
@@ -612,7 +616,19 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
} else {
ctx->pc_succ_insn = ctx->base.pc_next + 2;
if (!decode_insn16(ctx, opcode)) {
- gen_exception_illegal(ctx);
+ if (riscv_cpu_is_32bit(env)) {
+ if (!decode_insn16_32(ctx, opcode)) {
+ gen_exception_illegal(ctx);
+ }
+ } else {
+#ifdef TARGET_RISCV64
+ if (!decode_insn16_64(ctx, opcode)) {
+ gen_exception_illegal(ctx);
+ }
+#else
+ gen_exception_illegal(ctx);
+#endif
+ }
}
}
} else {
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index 88ab850682..d17b478120 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -1,12 +1,15 @@
# FIXME extra_args should accept files()
dir = meson.current_source_dir()
gen32 = [
- decodetree.process('insn16.decode', extra_args: [dir / 'insn16-32.decode', '--static-decode=decode_insn16', '--insnwidth=16']),
+ decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
+ decodetree.process('insn16-32.decode', extra_args: ['--static-decode=decode_insn16_32', '--insnwidth=16']),
decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
]
gen64 = [
- decodetree.process('insn16.decode', extra_args: [dir / 'insn16-64.decode', '--static-decode=decode_insn16', '--insnwidth=16']),
+ decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
+ decodetree.process('insn16-32.decode', extra_args: ['--static-decode=decode_insn16_32', '--insnwidth=16']),
+ decodetree.process('insn16-64.decode', extra_args: ['--static-decode=decode_insn16_64', '--insnwidth=16']),
decodetree.process('insn32.decode', extra_args: [dir / 'insn32-64.decode', '--static-decode=decode_insn32']),
]
--
2.31.0
On 4/2/21 1:03 PM, Alistair Francis wrote:
> Signed-off-by: Alistair Francis<alistair.francis@wdc.com>
> ---
> target/riscv/insn16-32.decode | 24 ++++++++++++++++++++++++
> target/riscv/insn16-64.decode | 31 +++++++++++++++++++++++++++++++
> target/riscv/translate.c | 18 +++++++++++++++++-
> target/riscv/meson.build | 7 +++++--
> 4 files changed, 77 insertions(+), 3 deletions(-)
Having these split out from the main decode file was a cool trick when we were
sure that we never needed to support both. Now, I think it would be better to
merge the patterns back in to the main insn16.decode file.
You'd begin by adding a REQUIRE_64BIT(ctx) macro, much like the other REQUIRE
macros in translate.c, using the translate-local is_32bit() function as
discussed earlier.
You add this to all of the trans_* functions that are currently #ifdef
TARGET_RISCV64, and merge the insn32-64.decode bits in first.
There may well be an issue of missing helper functions, particularly when it
comes to RVF/RVD/RVV. There's a suggestion that I made for Claudio for i386
that may help here:
https://lists.gnu.org/archive/html/qemu-devel/2021-02/msg08595.html
where you add stubs that allow the gen_helper_foo() function to be declared,
insist that it be optimized away, and reduce to an abort with -O0.
Only after insn32.decode is complete, do insn16.decode. That's because many of
the insns here will need the REQUIRE_64BIT in place for correctness.
E.g.
{
ld 011 ... ... .. ... 00 @cl_d
flw 011 ... ... .. ... 00 @cl_w
}
Since ld already has REQUIRE_64BIT, for is_32bit it returns false, and we fall
into the flw code.
There will be one extra helper required, when the 64-bit RVC insn has a set of
illegal operands:
static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
{
REQUIRE_64BIT(ctx);
return trans_illegal(ctx, a);
}
for use with quadrant 1:
{
c64_illegal 001 - 00000 ----- 01 # c.addiw, RES rd=0
addiw 001 . ..... ..... 01 @ci
jal 001 ........... 01 @cj rd=1 # C.JAL
}
and quadrant 2:
{
c64_illegal 011 - 00000 ----- 10 # c.ldsp, RES rd=0
ld 011 . ..... ..... 10 @c_ldsp
flw 011 . ..... ..... 10 @c_lwsp
}
r~
© 2016 - 2026 Red Hat, Inc.