Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 59 additions & 15 deletions arch/riscv/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,19 @@ static int ensure_additional_extension(DisasContext *dc, enum riscv_additional_f
return 0;
}

/* Dual-owner extension gate (e.g. Zbb / Zbkb both own ANDN, ROL, REV8, ...):
* succeed if either extension is enabled. ensure_additional_extension()
* raises the illegal-instruction exception on failure, so it must not be
* called for the first alternative before checking the second one.
*/
static int ensure_any_additional_extension(DisasContext *dc, enum riscv_additional_feature ext1, enum riscv_additional_feature ext2)
{
if(riscv_has_additional_ext(cpu, ext1) || riscv_has_additional_ext(cpu, ext2)) {
return 1;
}
ensure_additional_extension(dc, ext1);
return 0;
}
static int ensure_fp_extension(DisasContext *dc, int precision_bit)
{
switch((enum riscv_floating_point_precision)extract64(dc->opcode, precision_bit, 2)) {
Expand Down Expand Up @@ -870,6 +883,29 @@ static void gen_arith(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2)
{
TCGv source1, source2, cond1, cond2, zeroreg, resultopt1;
target_ulong mask;
switch(opc) {
case OPC_RISC_MUL:
case OPC_RISC_MULH:
case OPC_RISC_MULHSU:
case OPC_RISC_MULHU:
case OPC_RISC_DIV:
case OPC_RISC_DIVU:
case OPC_RISC_REM:
case OPC_RISC_REMU:
#if defined(TARGET_RISCV64)
case OPC_RISC_MULW:
case OPC_RISC_DIVW:
case OPC_RISC_DIVUW:
case OPC_RISC_REMW:
case OPC_RISC_REMUW:
#endif
if(!ensure_extension(dc, RISCV_FEATURE_RVM)) {
return;
}
break;
default:
break;
}
source1 = tcg_temp_local_new();
source2 = tcg_temp_local_new();
gen_get_gpr(source1, rs1);
Expand Down Expand Up @@ -1117,21 +1153,21 @@ static void gen_arith(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2)
tcg_gen_add_tl(source1, source1, source2);
break;
case OPC_RISC_ANDN:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
tcg_gen_not_tl(source2, source2);
tcg_gen_and_tl(source1, source1, source2);
break;
case OPC_RISC_ORN:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
tcg_gen_not_tl(source2, source2);
tcg_gen_or_tl(source1, source1, source2);
break;
case OPC_RISC_XNOR:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
tcg_gen_xor_tl(source1, source1, source2);
Expand Down Expand Up @@ -1242,7 +1278,7 @@ static void gen_arith(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2)
break;
#endif
case OPC_RISC_ROL:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
cond1 = tcg_temp_new();
Expand All @@ -1251,7 +1287,7 @@ static void gen_arith(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2)
tcg_temp_free(cond1);
break;
case OPC_RISC_ROLW:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
cond1 = tcg_temp_new_i64();
Expand All @@ -1265,13 +1301,13 @@ static void gen_arith(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2)
break;

case OPC_RISC_ROR:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
tcg_gen_rotr_tl(source1, source1, source2);
break;
case OPC_RISC_RORW:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
cond1 = tcg_temp_new_i64();
Expand Down Expand Up @@ -1467,13 +1503,13 @@ static void gen_arith_bitmanip(DisasContext *dc, int rd, int rs1, target_long im
tcg_gen_ext32s_i64(source1, source1);
break;
case OPC_RISC_RORI:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
tcg_gen_rotri_tl(source1, source1, (imm & BITMANIP_SHAMT_MASK));
break;
case OPC_RISC_RORIW:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
t0 = tcg_temp_new_i64();
Expand All @@ -1491,13 +1527,13 @@ static void gen_arith_bitmanip(DisasContext *dc, int rd, int rs1, target_long im
tcg_gen_shli_i64(source1, source1, (imm & BITMANIP_SHAMT_MASK));
break;
case OPC_RISC_REV8_32:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
tcg_gen_bswap32_i32(source1, source1);
break;
case OPC_RISC_REV8_64:
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZBB) && !ensure_additional_extension(dc, RISCV_FEATURE_ZBKB)) {
if(!ensure_any_additional_extension(dc, RISCV_FEATURE_ZBB, RISCV_FEATURE_ZBKB)) {
return;
}
tcg_gen_bswap64_i64(source1, source1);
Expand Down Expand Up @@ -3662,7 +3698,10 @@ static void gen_fp_arith(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs
if(rm == 0x0) { /* FMV */
gen_helper_fmv_x_h(write_int_rd, cpu_env, cpu_fpr[rs1], rm_reg);
} else if(rm == 0x1) {
gen_helper_fclass_h(write_int_rd, cpu_env, cpu_fpr[rs1]);
TCGv_i64 rs1_boxed = tcg_temp_local_new_i64();
gen_unbox_float(RISCV_HALF_PRECISION, env, rs1_boxed, cpu_fpr[rs1]);
gen_helper_fclass_h(write_int_rd, cpu_env, rs1_boxed);
tcg_temp_free_i64(rs1_boxed);
} else {
kill_unknown(dc, RISCV_EXCP_ILLEGAL_INST);
}
Expand Down Expand Up @@ -3718,9 +3757,6 @@ static void gen_system(DisasContext *dc, uint32_t opc, int rd, int rs1, int rs2,
gen_exit_tb_no_chaining(dc->base.tb);
dc->base.is_jmp = DISAS_BRANCH;
break;
case 0x4: /* SFENCE.VM */
gen_helper_tlb_flush(cpu_env);
break;
case 0x5: /* WFI */
tcg_gen_movi_tl(cpu_pc, dc->npc);
gen_helper_wfi(cpu_env);
Expand Down Expand Up @@ -6390,6 +6426,10 @@ static void decode_RV32_64C1(CPUState *env, DisasContext *dc)
if(!ensure_additional_extension(dc, RISCV_FEATURE_ZCB)) {
break;
}
/* C.MUL additionally requires M or Zmmul. */
if(!ensure_extension(dc, RISCV_FEATURE_RVM)) {
break;
}
/* C.MUL -> mul rd', rd', rs2' */
gen_arith(dc, OPC_RISC_MUL, rs1s, rs1s, rs2s);
break;
Expand All @@ -6399,6 +6439,10 @@ static void decode_RV32_64C1(CPUState *env, DisasContext *dc)
}
/* C.ZEXT.B, C.SEXT.B, C.ZEXT.H, C.SEXT.H, C.ZEXT.W, C.NOT */
uint8_t c_op = extract32(dc->opcode, 2, 3);
if((c_op == 1 || c_op == 2 || c_op == 3) &&
!ensure_additional_extension(dc, RISCV_FEATURE_ZBB)) {
break;
}

switch(c_op) {
case 0:
Expand Down