Added support for RISC-V PAUSE instruction from Zihintpause extension, enabeld by default.
Signed-off-by: Dao Lu <da...@rivosinc.com> --- target/riscv/cpu.c | 2 ++ target/riscv/cpu.h | 1 + target/riscv/insn32.decode | 7 ++++++- target/riscv/insn_trans/trans_rvi.c.inc | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ccacdee215..183fb37fdf 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -825,6 +825,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), + DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true), DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false), DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false), DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false), @@ -996,6 +997,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int max_str_len) * extensions by an underscore. */ struct isa_ext_data isa_edata_arr[] = { + ISA_EDATA_ENTRY(zihintpause, ext_zihintpause), ISA_EDATA_ENTRY(zfh, ext_zfh), ISA_EDATA_ENTRY(zfhmin, ext_zfhmin), ISA_EDATA_ENTRY(zfinx, ext_zfinx), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index fe6c9a2c92..e466a04a59 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -394,6 +394,7 @@ struct RISCVCPUConfig { bool ext_counters; bool ext_ifencei; bool ext_icsr; + bool ext_zihintpause; bool ext_svinval; bool ext_svnapot; bool ext_svpbmt; diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 4033565393..595fdcdad8 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -149,7 +149,12 @@ srl 0000000 ..... ..... 101 ..... 0110011 @r sra 0100000 ..... ..... 101 ..... 0110011 @r or 0000000 ..... ..... 110 ..... 0110011 @r and 0000000 ..... ..... 111 ..... 0110011 @r -fence ---- pred:4 succ:4 ----- 000 ----- 0001111 + +{ + pause 0000 0001 0000 00000 000 00000 0001111 + fence ---- pred:4 succ:4 ----- 000 ----- 0001111 +} + fence_i ---- ---- ---- ----- 001 ----- 0001111 csrrw ............ ..... 001 ..... 1110011 @csr csrrs ............ ..... 010 ..... 1110011 @csr diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index f1342f30f8..528c30c9a2 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -18,6 +18,12 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ +#define REQUIRE_ZIHINTPAUSE(ctx) do { \ + if (!ctx->cfg_ptr->ext_zihintpause) { \ + return false; \ + } \ +} while (0) + static bool trans_illegal(DisasContext *ctx, arg_empty *a) { gen_exception_illegal(ctx); @@ -796,6 +802,18 @@ static bool trans_srad(DisasContext *ctx, arg_srad *a) return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL); } +static bool trans_pause(DisasContext *ctx, arg_pause *a) +{ + REQUIRE_ZIHINTPAUSE(ctx); + + /* + * PAUSE is a no-op in QEMU, + * however we need to clear the reservation + */ + tcg_gen_movi_tl(load_res, -1); + + return true; +} static bool trans_fence(DisasContext *ctx, arg_fence *a) { -- 2.36.0