From: Christoph Müllner <christoph.muell...@vrull.eu> This patch adds support for the T-Head Bitmanip instructions. The patch uses the T-Head specific decoder and translation.
As the instructions are similar to those of Zb*, we can reuse a lot of existing infrastructure code. Signed-off-by: Christoph Müllner <christoph.muell...@vrull.eu> --- target/riscv/cpu.c | 3 + target/riscv/cpu.h | 3 + target/riscv/insn_trans/trans_xthead.c.inc | 124 +++++++++++++++++++++ target/riscv/meson.build | 3 + target/riscv/translate.c | 9 ++ target/riscv/xtheadba.decode | 46 ++++++++ target/riscv/xtheadbb.decode | 62 +++++++++++ target/riscv/xtheadbs.decode | 32 ++++++ 8 files changed, 282 insertions(+) create mode 100644 target/riscv/xtheadba.decode create mode 100644 target/riscv/xtheadbb.decode create mode 100644 target/riscv/xtheadbs.decode diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index a72722cfa6..d129a6112a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -920,6 +920,9 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("zhinxmin", RISCVCPU, cfg.ext_zhinxmin, false), /* Vendor-specific custom extensions */ + DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false), + DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false), + DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false), DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false), DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false), DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 4ae22cf529..9e2b3d6f56 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -440,6 +440,9 @@ struct RISCVCPUConfig { uint64_t mimpid; /* Vendor-specific custom extensions */ + bool ext_xtheadba; + bool ext_xtheadbb; + bool ext_xtheadbs; bool ext_xtheadcmo; bool ext_xtheadsync; bool ext_XVentanaCondOps; diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc index 0a6719b2e2..b2d523b905 100644 --- a/target/riscv/insn_trans/trans_xthead.c.inc +++ b/target/riscv/insn_trans/trans_xthead.c.inc @@ -70,3 +70,127 @@ NOP_PRIVCHECK(th_sync_i, REQUIRE_PRIV_MHSU) NOP_PRIVCHECK(th_sync_is, REQUIRE_PRIV_MHSU) NOP_PRIVCHECK(th_sync_s, REQUIRE_PRIV_MHSU) +/* + * th.addsl is similar to sh[123]add (from Zba), but not an + * alternative encoding: while sh[123] applies the shift to rs1, + * th.addsl shifts rs2. + */ + +#define GEN_TH_ADDSL(SHAMT) \ +static void gen_th_addsl##SHAMT(TCGv ret, TCGv arg1, TCGv arg2) \ +{ \ + TCGv t = tcg_temp_new(); \ + tcg_gen_shli_tl(t, arg2, SHAMT); \ + tcg_gen_add_tl(ret, t, arg1); \ + tcg_temp_free(t); \ +} + +GEN_TH_ADDSL(1) +GEN_TH_ADDSL(2) +GEN_TH_ADDSL(3) + +#define GEN_TRANS_TH_ADDSL(SHAMT) \ +static bool trans_th_addsl##SHAMT(DisasContext *ctx, \ + arg_th_addsl##SHAMT * a) \ +{ \ + return gen_arith(ctx, a, EXT_NONE, gen_th_addsl##SHAMT, NULL); \ +} + +GEN_TRANS_TH_ADDSL(1) +GEN_TRANS_TH_ADDSL(2) +GEN_TRANS_TH_ADDSL(3) + + +/* th.srri is an alternate encoding for rori (from Zbb) */ +static bool trans_th_srri(DisasContext *ctx, arg_th_srri * a) +{ + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_rotri_tl, NULL); +} + +/* th.srriw is an alternate encoding for roriw (from Zbb) */ +static bool trans_th_srriw(DisasContext *ctx, arg_th_srriw *a) +{ + ctx->ol = MXL_RV32; + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_roriw, NULL); +} + +/* th.ext and th.extu perform signed/unsigned bitfield extraction */ +static bool gen_th_bfextract(DisasContext *ctx, arg_th_bfext *a, + void (*f)(TCGv, TCGv, unsigned int, unsigned int)) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv source = get_gpr(ctx, a->rs1, EXT_ZERO); + + if (a->lsb <= a->msb) { + f(dest, source, a->lsb, a->msb - a->lsb + 1); + gen_set_gpr(ctx, a->rd, dest); + } + return true; +} + +static bool trans_th_ext(DisasContext *ctx, arg_th_ext *a) +{ + return gen_th_bfextract(ctx, a, tcg_gen_sextract_tl); +} + +static bool trans_th_extu(DisasContext *ctx, arg_th_extu *a) +{ + return gen_th_bfextract(ctx, a, tcg_gen_extract_tl); +} + +/* th.ff0: find first zero (clz on an inverted input) */ +static void gen_th_ff0(TCGv ret, TCGv arg1) +{ + TCGv t = tcg_temp_new(); + tcg_gen_not_tl(t, arg1); + gen_clz(ret, t); + tcg_temp_free(t); +} + +static bool trans_th_ff0(DisasContext *ctx, arg_th_ff0 *a) +{ + return gen_unary(ctx, a, EXT_NONE, gen_th_ff0); +} + +/* th.ff1 is an alternate encoding for clz (from Zbb) */ +static bool trans_th_ff1(DisasContext *ctx, arg_th_ff1 *a) +{ + return gen_unary(ctx, a, EXT_NONE, gen_clz); +} + +/* th.rev is an alternate encoding for the RV64 rev8 (from Zbb) */ +static bool trans_th_rev(DisasContext *ctx, arg_th_rev *a) +{ + return gen_unary(ctx, a, EXT_NONE, tcg_gen_bswap_tl); +} + +/* th.revw is a sign-extended byte-swap of the lower word */ +static void gen_th_revw(TCGv ret, TCGv arg1) +{ + tcg_gen_bswap_tl(ret, arg1); + tcg_gen_sari_tl(ret, ret, 32); +} + +static bool trans_th_revw(DisasContext *ctx, arg_th_revw *a) +{ + return gen_unary(ctx, a, EXT_NONE, gen_th_revw); +} + +/* th.tstnbz is equivalent to an orc.b (from Zbb) with inverted result */ +static void gen_th_tstnbz(TCGv ret, TCGv source1) +{ + gen_orc_b(ret, source1); + tcg_gen_not_tl(ret, ret); +} + +static bool trans_th_tstnbz(DisasContext *ctx, arg_th_tstnbz *a) +{ + return gen_unary(ctx, a, EXT_ZERO, gen_th_tstnbz); +} + +/* th.tst is an alternate encoding for bexti (from Zbs) */ +static bool trans_th_tst(DisasContext *ctx, arg_th_tst *a) +{ + return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bext); +} + diff --git a/target/riscv/meson.build b/target/riscv/meson.build index f201cc6997..5ee37683cb 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -2,6 +2,9 @@ gen = [ decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']), decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'), + decodetree.process('xtheadba.decode', extra_args: '--static-decode=decode_xtheadba'), + decodetree.process('xtheadbb.decode', extra_args: '--static-decode=decode_xtheadbb'), + decodetree.process('xtheadbs.decode', extra_args: '--static-decode=decode_xtheadbs'), decodetree.process('xtheadcmo.decode', extra_args: '--static-decode=decode_xtheadcmo'), decodetree.process('xtheadsync.decode', extra_args: '--static-decode=decode_xtheadsync'), decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'), diff --git a/target/riscv/translate.c b/target/riscv/translate.c index a63cc3de46..f662e403f8 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -132,6 +132,9 @@ static bool always_true_p(DisasContext *ctx __attribute__((__unused__))) return ctx->cfg_ptr->ext_ ## ext ; \ } +MATERIALISE_EXT_PREDICATE(xtheadba) +MATERIALISE_EXT_PREDICATE(xtheadbb) +MATERIALISE_EXT_PREDICATE(xtheadbs) MATERIALISE_EXT_PREDICATE(xtheadcmo) MATERIALISE_EXT_PREDICATE(xtheadsync) MATERIALISE_EXT_PREDICATE(XVentanaCondOps) @@ -720,6 +723,9 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm) #include "decode-insn32.c.inc" /* Include decoders for factored-out extensions */ +#include "decode-xtheadba.c.inc" +#include "decode-xtheadbb.c.inc" +#include "decode-xtheadbs.c.inc" #include "decode-xtheadcmo.c.inc" #include "decode-xtheadsync.c.inc" #include "decode-XVentanaCondOps.c.inc" @@ -1042,6 +1048,9 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode) bool (*decode_func)(DisasContext *, uint32_t); } decoders[] = { { always_true_p, decode_insn32 }, + { has_xtheadba_p, decode_xtheadba }, + { has_xtheadbb_p, decode_xtheadbb }, + { has_xtheadbs_p, decode_xtheadbs }, { has_xtheadcmo_p, decode_xtheadcmo }, { has_xtheadsync_p, decode_xtheadsync }, { has_XVentanaCondOps_p, decode_XVentanaCodeOps }, diff --git a/target/riscv/xtheadba.decode b/target/riscv/xtheadba.decode new file mode 100644 index 0000000000..4e5e3f12f0 --- /dev/null +++ b/target/riscv/xtheadba.decode @@ -0,0 +1,46 @@ +# +# RISC-V instruction decode for the XTheadBa extension +# +# Copyright (c) 2022 Dr. Philipp Tomsich, philipp.toms...@vrull.eu +# Christoph Muellner, christoph.muell...@vrull.eu +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# The XTheadBa extension provides instructions for address calculations, +# implementing the functional equivalent of a subset of Zba. +# +# It is documented in +# https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.0.0/xthead-2022-09-05-2.0.0.pdf +# +# The instruction contained in XTheadBb is: +# - th.addsl add rotate-right by immediate +# (similar to sh[123]add, but with rs1 and rs2 switched) +# This instruction reuses an existing instruction format. + +# Fields +%rs2 20:5 +%rs1 15:5 +%rd 7:5 + +# Argument sets +&r rd rs1 rs2 !extern + +# Formats: +@r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd + +# *** Bitmanip addressing instructions +# Instead of defining a new encoding, we simply use the decoder to +# extract the imm[0:1] field and dispatch to separate translation +# functions (mirroring the `sh[123]add` instructions from Zba and +# the regular RVI `add` instruction. +# +# The only difference between sh[123]add and addsl is that the sohift +# is applied to rs1 (for addsl) instead of rs2 (for sh[123]add). +# +# Note that shift-by-0 is a valid operation according to the manual. +# This will be equivalent to a regular add. +add 0000000 ..... ..... 001 ..... 0001011 @r +th_addsl1 0000001 ..... ..... 001 ..... 0001011 @r +th_addsl2 0000010 ..... ..... 001 ..... 0001011 @r +th_addsl3 0000011 ..... ..... 001 ..... 0001011 @r + diff --git a/target/riscv/xtheadbb.decode b/target/riscv/xtheadbb.decode new file mode 100644 index 0000000000..2754a6444b --- /dev/null +++ b/target/riscv/xtheadbb.decode @@ -0,0 +1,62 @@ +# +# RISC-V instruction decode for the XTheadBb extension +# +# Copyright (c) 2022 Dr. Philipp Tomsich, philipp.toms...@vrull.eu +# Christoph Muellner, christoph.muell...@vrull.eu +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# The XTheadBb extension provides basic bit-manipulation instructions, +# implementing the functional equivalent of a subset of Zbb. +# +# It is documented in +# https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.0.0/xthead-2022-09-05-2.0.0.pdf +# +# The instructions contained in XTheadBb are: +# - th.srri rotate-right by immediate (matches rori) +# - th.srriw rotate-right by immediate, w-form (matches roriw) +# - th.rev byte-reverse register (matches RV64-form of rev8) +# - th.revw byte-reverse low word, sign-extend result (no equivalent) +# - th.ext signed bitfield-extract (no equivalent) +# - th.extu unsigned bitfield-extract (no equivalent) +# - th.ff0 find-first zero (equivalent to clz on the inverted operand) +# - th.ff1 find-first one (matches clz) +# - th.tstnbz test for zero-bytes (equivalent to the inverted result of orc.b) +# - th.tst test for bit (equivalent to bexti) +# +# These instructions generally reuse existing instruction formats. +# Only the th.ext and th.ext introduce a new, vendor-defined instruction format. + +# Fields +%rs2 20:5 +%rs1 15:5 +%rd 7:5 +%sh5 20:5 +%sh6 20:6 + +# Argument sets +&r2 rd rs1 !extern +&shift shamt rs1 rd !extern +&th_bfext msb lsb rs1 rd + +# Formats: +@r2 ....... ..... ..... ... ..... ....... &r2 %rs1 %rd +@th_bfext msb:6 lsb:6 ..... ... ..... ....... &th_bfext %rs1 %rd + +# Formats 64: +@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd + +# Formats 128: +@sh6 ...... ...... ..... ... ..... ....... &shift shamt=%sh6 %rs1 %rd + +# *** Bitmanip instructions +th_ext ...... ...... ..... 010 ..... 0001011 @th_bfext +th_extu ...... ...... ..... 011 ..... 0001011 @th_bfext +th_ff0 1000010 00000 ..... 001 ..... 0001011 @r2 +th_ff1 1000011 00000 ..... 001 ..... 0001011 @r2 +th_srri 000100 ...... ..... 001 ..... 0001011 @sh6 +th_srriw 0001010 ..... ..... 001 ..... 0001011 @sh5 +th_rev 1000001 00000 ..... 001 ..... 0001011 @r2 +th_revw 1001000 00000 ..... 001 ..... 0001011 @r2 +th_tstnbz 1000000 00000 ..... 001 ..... 0001011 @r2 + diff --git a/target/riscv/xtheadbs.decode b/target/riscv/xtheadbs.decode new file mode 100644 index 0000000000..7aa345b207 --- /dev/null +++ b/target/riscv/xtheadbs.decode @@ -0,0 +1,32 @@ +# +# RISC-V instruction decode for the XTheadBb extension +# +# Copyright (c) 2022 Dr. Philipp Tomsich, philipp.toms...@vrull.eu +# Christoph Muellner, christoph.muell...@vrull.eu +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# XTheadBs provides basic bit-manipulation instructions, +# implementing the functional equivalent of a subset of Zbs. +# +# It is documented in +# https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.0.0/xthead-2022-09-05-2.0.0.pdf +# +# The instruction contained in XTheadBb is: +# - th.tst test if bit is set (matches bexti) +# +# The instruction reuses an existing instruction format. + +# Fields +%rs1 15:5 +%rd 7:5 +%sh6 20:6 + +# Argument sets +&shift shamt rs1 rd !extern + +# Formats 128: +@sh6 ...... ...... ..... ... ..... ....... &shift shamt=%sh6 %rs1 %rd + +# *** Bitmanip single-bit instructions +th_tst 100010 ...... ..... 001 ..... 0001011 @sh6 -- 2.37.2