static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
{
- /* check for compressed insn */
+ /* If not handled, we'll raise an illegal instruction exception */
+ bool handled = false;
+
+ /*
+ * A table with predicate (i.e., guard) functions and decoder functions
+ * that are tested in-order until a decoder matches onto the opcode.
+ */
+ const struct {
+ bool (*guard_func)(CPURISCVState *, DisasContext *);
+ bool (*decode_func)(DisasContext *, uint32_t);
+ } decoders[] = {
+ { always_true_p, decode_insn32 },
+ };
+
+ /* Check for compressed insn */
if (extract16(opcode, 0, 2) != 3) {
if (!has_ext(ctx, RVC)) {
gen_exception_illegal(ctx);
} else {
ctx->opcode = opcode;
ctx->pc_succ_insn = ctx->base.pc_next + 2;
- if (!decode_insn16(ctx, opcode)) {
- gen_exception_illegal(ctx);
- }
+ handled = decode_insn16(ctx, opcode);
}
} else {
uint32_t opcode32 = opcode;
@@ -862,10 +880,18 @@ static void decode_opc(CPURISCVState *env, DisasContext
*ctx, uint16_t opcode)
ctx->base.pc_next + 2));
ctx->opcode = opcode32;
ctx->pc_succ_insn = ctx->base.pc_next + 4;
- if (!decode_insn32(ctx, opcode32)) {
- gen_exception_illegal(ctx);
+
+ for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
+ if (!decoders[i].guard_func(env, ctx))
+ continue;
+
+ if ((handled = decoders[i].decode_func(ctx, opcode32)))