* [PATCH v3 01/14] RISC-V: Adding XTheadCmo ISA extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 02/14] RISC-V: Adding XTheadSync " Christoph Muellner
` (12 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the XTheadCmo ISA extension.
To avoid interfering with standard extensions, decoder and translation
are in its own xthead* specific files.
Future patches should be able to easily add additional T-Head extension.
The implementation does not have much functionality (besides accepting
the instructions and not qualifying them as illegal instructions if
the hart executes in the required privilege level for the instruction),
as QEMU does not model CPU caches and instructions are documented
to not raise any exceptions.
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Explicit test for PRV_U
- Encapsule access to env-priv in inline function
- Use single decoder for XThead extensions
Changes in v3:
- Appling mask TB_FLAGS_PRIV_MMU_MASK to use of ctx->mem_idx
- Removing code from test macro REQUIRE_PRIV_MSU()
- Removing PRV_H from test macro REQUIRE_PRIV_MS()
- Remove unrelated clean-up
- Reorder decoder includes
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 81 ++++++++++++++++++++++
target/riscv/meson.build | 1 +
target/riscv/translate.c | 8 +++
target/riscv/xthead.decode | 38 ++++++++++
6 files changed, 131 insertions(+)
create mode 100644 target/riscv/insn_trans/trans_xthead.c.inc
create mode 100644 target/riscv/xthead.decode
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index cc75ca7667..43a3b9218f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -109,6 +109,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
+ ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
};
@@ -1071,6 +1072,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false),
/* Vendor-specific custom extensions */
+ DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
/* These are experimental so mark with 'x-' */
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f5609b62a2..680dd3dfbd 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -473,6 +473,7 @@ struct RISCVCPUConfig {
uint64_t mimpid;
/* Vendor-specific custom extensions */
+ bool ext_xtheadcmo;
bool ext_XVentanaCondOps;
uint8_t pmu_num;
diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc
new file mode 100644
index 0000000000..24acaf188c
--- /dev/null
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -0,0 +1,81 @@
+/*
+ * RISC-V translation routines for the T-Head vendor extensions (xthead*).
+ *
+ * Copyright (c) 2022 VRULL GmbH.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_XTHEADCMO(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadcmo) { \
+ return false; \
+ } \
+} while (0)
+
+/* XTheadCmo */
+
+static inline int priv_level(DisasContext *ctx)
+{
+#ifdef CONFIG_USER_ONLY
+ return PRV_U;
+#else
+ /* Priv level is part of mem_idx. */
+ return ctx->mem_idx & TB_FLAGS_PRIV_MMU_MASK;
+#endif
+}
+
+/* Test if priv level is M, S, or U (cannot fail). */
+#define REQUIRE_PRIV_MSU(ctx)
+
+/* Test if priv level is M or S. */
+#define REQUIRE_PRIV_MS(ctx) \
+do { \
+ int priv = priv_level(ctx); \
+ if (!(priv == PRV_M || \
+ priv == PRV_S)) { \
+ return false; \
+ } \
+} while (0)
+
+#define NOP_PRIVCHECK(insn, extcheck, privcheck) \
+static bool trans_ ## insn(DisasContext *ctx, arg_ ## insn * a) \
+{ \
+ (void) a; \
+ extcheck(ctx); \
+ privcheck(ctx); \
+ return true; \
+}
+
+NOP_PRIVCHECK(th_dcache_call, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_ciall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_cpa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_cipa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_ipa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_cva, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
+NOP_PRIVCHECK(th_dcache_civa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
+NOP_PRIVCHECK(th_dcache_iva, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
+NOP_PRIVCHECK(th_dcache_csw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_cisw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_isw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_cpal1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_dcache_cval1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+
+NOP_PRIVCHECK(th_icache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_icache_ialls, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_icache_ipa, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_icache_iva, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
+
+NOP_PRIVCHECK(th_l2cache_call, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_l2cache_ciall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+NOP_PRIVCHECK(th_l2cache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index ba25164d74..5dee37a242 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -2,6 +2,7 @@
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('xthead.decode', extra_args: '--static-decode=decode_xthead'),
decodetree.process('XVentanaCondOps.decode', extra_args: '--static-decode=decode_XVentanaCodeOps'),
]
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index df38db7553..37763e0502 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -128,6 +128,11 @@ static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
return true;
}
+static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
+{
+ return ctx->cfg_ptr->ext_xtheadcmo;
+}
+
#define MATERIALISE_EXT_PREDICATE(ext) \
static bool has_ ## ext ## _p(DisasContext *ctx) \
{ \
@@ -762,6 +767,7 @@ static int ex_rvc_shiftri(DisasContext *ctx, int imm)
/* Include the auto-generated decoder for 32 bit insn */
#include "decode-insn32.c.inc"
+#include "decode-xthead.c.inc"
static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
void (*func)(TCGv, TCGv, target_long))
@@ -1065,6 +1071,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
#include "insn_trans/trans_rvk.c.inc"
#include "insn_trans/trans_privileged.c.inc"
#include "insn_trans/trans_svinval.c.inc"
+#include "insn_trans/trans_xthead.c.inc"
#include "insn_trans/trans_xventanacondops.c.inc"
/* Include the auto-generated decoder for 16 bit insn */
@@ -1091,6 +1098,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
bool (*decode_func)(DisasContext *, uint32_t);
} decoders[] = {
{ always_true_p, decode_insn32 },
+ { has_xthead_p, decode_xthead },
{ has_XVentanaCondOps_p, decode_XVentanaCodeOps },
};
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
new file mode 100644
index 0000000000..30533a66f5
--- /dev/null
+++ b/target/riscv/xthead.decode
@@ -0,0 +1,38 @@
+#
+# Translation routines for the instructions of the XThead* ISA extensions
+#
+# Copyright (c) 2022 Christoph Muellner, christoph.muellner@vrull.eu
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# The documentation of the ISA extensions can be found here:
+# https://github.com/T-head-Semi/thead-extension-spec/releases/latest
+
+# Fields:
+%rs1 15:5
+
+# Formats
+@sfence_vm ....... ..... ..... ... ..... ....... %rs1
+
+# XTheadCmo
+th_dcache_call 0000000 00001 00000 000 00000 0001011
+th_dcache_ciall 0000000 00011 00000 000 00000 0001011
+th_dcache_iall 0000000 00010 00000 000 00000 0001011
+th_dcache_cpa 0000001 01001 ..... 000 00000 0001011 @sfence_vm
+th_dcache_cipa 0000001 01011 ..... 000 00000 0001011 @sfence_vm
+th_dcache_ipa 0000001 01010 ..... 000 00000 0001011 @sfence_vm
+th_dcache_cva 0000001 00101 ..... 000 00000 0001011 @sfence_vm
+th_dcache_civa 0000001 00111 ..... 000 00000 0001011 @sfence_vm
+th_dcache_iva 0000001 00110 ..... 000 00000 0001011 @sfence_vm
+th_dcache_csw 0000001 00001 ..... 000 00000 0001011 @sfence_vm
+th_dcache_cisw 0000001 00011 ..... 000 00000 0001011 @sfence_vm
+th_dcache_isw 0000001 00010 ..... 000 00000 0001011 @sfence_vm
+th_dcache_cpal1 0000001 01000 ..... 000 00000 0001011 @sfence_vm
+th_dcache_cval1 0000001 00100 ..... 000 00000 0001011 @sfence_vm
+th_icache_iall 0000000 10000 00000 000 00000 0001011
+th_icache_ialls 0000000 10001 00000 000 00000 0001011
+th_icache_ipa 0000001 11000 ..... 000 00000 0001011 @sfence_vm
+th_icache_iva 0000001 10000 ..... 000 00000 0001011 @sfence_vm
+th_l2cache_call 0000000 10101 00000 000 00000 0001011
+th_l2cache_ciall 0000000 10111 00000 000 00000 0001011
+th_l2cache_iall 0000000 10110 00000 000 00000 0001011
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 02/14] RISC-V: Adding XTheadSync ISA extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 01/14] RISC-V: Adding XTheadCmo ISA extension Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 20:21 ` Richard Henderson
2023-01-24 19:59 ` [PATCH v3 03/14] RISC-V: Adding XTheadBa " Christoph Muellner
` (11 subsequent siblings)
13 siblings, 1 reply; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the XTheadSync ISA extension.
The patch uses the T-Head specific decoder and translation.
The implementation introduces a helper to execute synchronization tasks:
helper_tlb_flush_all() performs a synchronized TLB flush on all CPUs.
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Use helper to synchronize CPUs and perform TLB flushes
- Change implemenation to follow latest spec update
- Use single decoder for XThead extensions
Changes in v3:
- Adjust for renamed REQUIRE_PRIV_* test macros
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/helper.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 86 ++++++++++++++++++++++
target/riscv/op_helper.c | 6 ++
target/riscv/translate.c | 2 +-
target/riscv/xthead.decode | 9 +++
7 files changed, 106 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 43a3b9218f..ae2009e89c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -110,6 +110,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
+ ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
};
@@ -1073,6 +1074,7 @@ static Property riscv_cpu_extensions[] = {
/* Vendor-specific custom extensions */
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),
/* These are experimental so mark with 'x-' */
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 680dd3dfbd..d0ab5c7bb0 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -474,6 +474,7 @@ struct RISCVCPUConfig {
/* Vendor-specific custom extensions */
bool ext_xtheadcmo;
+ bool ext_xtheadsync;
bool ext_XVentanaCondOps;
uint8_t pmu_num;
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 227c7122ef..d22656698a 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -109,6 +109,7 @@ DEF_HELPER_1(sret, tl, env)
DEF_HELPER_1(mret, tl, env)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(tlb_flush, void, env)
+DEF_HELPER_1(tlb_flush_all, void, env)
/* Native Debug */
DEF_HELPER_1(itrigger_match, void, env)
#endif
diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc
index 24acaf188c..bf5b39c749 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -22,6 +22,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADSYNC(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadsync) { \
+ return false; \
+ } \
+} while (0)
+
/* XTheadCmo */
static inline int priv_level(DisasContext *ctx)
@@ -79,3 +85,83 @@ NOP_PRIVCHECK(th_icache_iva, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU)
NOP_PRIVCHECK(th_l2cache_call, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
NOP_PRIVCHECK(th_l2cache_ciall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
NOP_PRIVCHECK(th_l2cache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+
+/* XTheadSync */
+
+static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas *a)
+{
+ (void) a;
+ REQUIRE_XTHEADSYNC(ctx);
+
+#ifndef CONFIG_USER_ONLY
+ REQUIRE_PRIV_MS(ctx);
+ decode_save_opc(ctx);
+ gen_helper_tlb_flush_all(cpu_env);
+ return true;
+#else
+ return false;
+#endif
+}
+
+#ifndef CONFIG_USER_ONLY
+static void gen_th_sync_local(DisasContext *ctx)
+{
+ /*
+ * Emulate out-of-order barriers with pipeline flush
+ * by exiting the translation block.
+ */
+ gen_set_pc_imm(ctx, ctx->pc_succ_insn);
+ tcg_gen_exit_tb(NULL, 0);
+ ctx->base.is_jmp = DISAS_NORETURN;
+}
+#endif
+
+static bool trans_th_sync(DisasContext *ctx, arg_th_sync *a)
+{
+ (void) a;
+ REQUIRE_XTHEADSYNC(ctx);
+
+#ifndef CONFIG_USER_ONLY
+ REQUIRE_PRIV_MSU(ctx);
+
+ /*
+ * th.sync is an out-of-order barrier.
+ */
+ gen_th_sync_local(ctx);
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+static bool trans_th_sync_i(DisasContext *ctx, arg_th_sync_i *a)
+{
+ (void) a;
+ REQUIRE_XTHEADSYNC(ctx);
+
+#ifndef CONFIG_USER_ONLY
+ REQUIRE_PRIV_MSU(ctx);
+
+ /*
+ * th.sync.i is th.sync plus pipeline flush.
+ */
+ gen_th_sync_local(ctx);
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+static bool trans_th_sync_is(DisasContext *ctx, arg_th_sync_is *a)
+{
+ /* This instruction has the same behaviour like th.sync.i. */
+ return trans_th_sync_i(ctx, a);
+}
+
+static bool trans_th_sync_s(DisasContext *ctx, arg_th_sync_s *a)
+{
+ /* This instruction has the same behaviour like th.sync. */
+ return trans_th_sync(ctx, a);
+}
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 878bcb03b8..48f918b71b 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -258,6 +258,12 @@ void helper_tlb_flush(CPURISCVState *env)
}
}
+void helper_tlb_flush_all(CPURISCVState *env)
+{
+ CPUState *cs = env_cpu(env);
+ tlb_flush_all_cpus_synced(cs);
+}
+
void helper_hyp_tlb_flush(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 37763e0502..dcda7cfd22 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -130,7 +130,7 @@ static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
{
- return ctx->cfg_ptr->ext_xtheadcmo;
+ return ctx->cfg_ptr->ext_xtheadcmo || ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index 30533a66f5..1d86f3a012 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -10,9 +10,11 @@
# Fields:
%rs1 15:5
+%rs2 20:5
# Formats
@sfence_vm ....... ..... ..... ... ..... ....... %rs1
+@rs2_s ....... ..... ..... ... ..... ....... %rs2 %rs1
# XTheadCmo
th_dcache_call 0000000 00001 00000 000 00000 0001011
@@ -36,3 +38,10 @@ th_icache_iva 0000001 10000 ..... 000 00000 0001011 @sfence_vm
th_l2cache_call 0000000 10101 00000 000 00000 0001011
th_l2cache_ciall 0000000 10111 00000 000 00000 0001011
th_l2cache_iall 0000000 10110 00000 000 00000 0001011
+
+# XTheadSync
+th_sfence_vmas 0000010 ..... ..... 000 00000 0001011 @rs2_s
+th_sync 0000000 11000 00000 000 00000 0001011
+th_sync_i 0000000 11010 00000 000 00000 0001011
+th_sync_is 0000000 11011 00000 000 00000 0001011
+th_sync_s 0000000 11001 00000 000 00000 0001011
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v3 02/14] RISC-V: Adding XTheadSync ISA extension
2023-01-24 19:59 ` [PATCH v3 02/14] RISC-V: Adding XTheadSync " Christoph Muellner
@ 2023-01-24 20:21 ` Richard Henderson
2023-01-30 14:05 ` Christoph Müllner
0 siblings, 1 reply; 30+ messages in thread
From: Richard Henderson @ 2023-01-24 20:21 UTC (permalink / raw)
To: Christoph Muellner, qemu-riscv, qemu-devel, Alistair Francis,
Bin Meng, Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia, Yunhai Shang,
Zhiwei Liu
On 1/24/23 09:59, Christoph Muellner wrote:
> +static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas *a)
> +{
> + (void) a;
> + REQUIRE_XTHEADSYNC(ctx);
> +
> +#ifndef CONFIG_USER_ONLY
> + REQUIRE_PRIV_MS(ctx);
> + decode_save_opc(ctx);
> + gen_helper_tlb_flush_all(cpu_env);
Why are you using decode_save_opc() when helper_tlb_flush_all() cannot raise an exception?
r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 02/14] RISC-V: Adding XTheadSync ISA extension
2023-01-24 20:21 ` Richard Henderson
@ 2023-01-30 14:05 ` Christoph Müllner
0 siblings, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-01-30 14:05 UTC (permalink / raw)
To: Richard Henderson
Cc: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt, Nelson Chu,
Kito Cheng, Cooper Qu, Lifang Xia, Yunhai Shang, Zhiwei Liu
[-- Attachment #1: Type: text/plain, Size: 591 bytes --]
On Tue, Jan 24, 2023 at 9:21 PM Richard Henderson <
richard.henderson@linaro.org> wrote:
> On 1/24/23 09:59, Christoph Muellner wrote:
> > +static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas
> *a)
> > +{
> > + (void) a;
> > + REQUIRE_XTHEADSYNC(ctx);
> > +
> > +#ifndef CONFIG_USER_ONLY
> > + REQUIRE_PRIV_MS(ctx);
> > + decode_save_opc(ctx);
> > + gen_helper_tlb_flush_all(cpu_env);
>
> Why are you using decode_save_opc() when helper_tlb_flush_all() cannot
> raise an exception?
>
No particular reason.
Will be dropped.
Thanks,
Christoph
>
>
> r~
>
[-- Attachment #2: Type: text/html, Size: 1195 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v3 03/14] RISC-V: Adding XTheadBa ISA extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 01/14] RISC-V: Adding XTheadCmo ISA extension Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 02/14] RISC-V: Adding XTheadSync " Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 04/14] RISC-V: Adding XTheadBb " Christoph Muellner
` (10 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the XTheadBa ISA extension.
The patch uses the T-Head specific decoder and translation.
Co-developed-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Split XtheadB* extension into individual commits
- Use single decoder for XThead extensions
target/riscv/cpu.c | 2 ++
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 39 ++++++++++++++++++++++
target/riscv/translate.c | 3 +-
target/riscv/xthead.decode | 22 ++++++++++++
5 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ae2009e89c..4b46130c5b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -109,6 +109,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
+ ISA_EXT_DATA_ENTRY(xtheadba, true, PRIV_VERSION_1_11_0, ext_xtheadba),
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
@@ -1073,6 +1074,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false),
/* Vendor-specific custom extensions */
+ DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, 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 d0ab5c7bb0..d3191bf27b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -473,6 +473,7 @@ struct RISCVCPUConfig {
uint64_t mimpid;
/* Vendor-specific custom extensions */
+ bool ext_xtheadba;
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 bf5b39c749..a7da156869 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -16,6 +16,12 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define REQUIRE_XTHEADBA(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadba) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADCMO(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadcmo) { \
return false; \
@@ -28,6 +34,39 @@
} \
} while (0)
+/* XTheadBa */
+
+/*
+ * 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) \
+{ \
+ REQUIRE_XTHEADBA(ctx); \
+ 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)
+
/* XTheadCmo */
static inline int priv_level(DisasContext *ctx)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index dcda7cfd22..68baf84807 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -130,7 +130,8 @@ static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
{
- return ctx->cfg_ptr->ext_xtheadcmo || ctx->cfg_ptr->ext_xtheadsync;
+ return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadcmo ||
+ ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index 1d86f3a012..b149f13018 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -2,6 +2,7 @@
# Translation routines for the instructions of the XThead* ISA extensions
#
# Copyright (c) 2022 Christoph Muellner, christoph.muellner@vrull.eu
+# Dr. Philipp Tomsich, philipp.tomsich@vrull.eu
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
@@ -9,12 +10,33 @@
# https://github.com/T-head-Semi/thead-extension-spec/releases/latest
# Fields:
+%rd 7:5
%rs1 15:5
%rs2 20:5
+# Argument sets
+&r rd rs1 rs2 !extern
+
# Formats
@sfence_vm ....... ..... ..... ... ..... ....... %rs1
@rs2_s ....... ..... ..... ... ..... ....... %rs2 %rs1
+@r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
+
+# XTheadBa
+# 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 shift
+# 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
# XTheadCmo
th_dcache_call 0000000 00001 00000 000 00000 0001011
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 04/14] RISC-V: Adding XTheadBb ISA extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (2 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 03/14] RISC-V: Adding XTheadBa " Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 05/14] RISC-V: Adding XTheadBs " Christoph Muellner
` (9 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the XTheadBb ISA extension.
The patch uses the T-Head specific decoder and translation.
Co-developed-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Split XtheadB* extension into individual commits
- Make implementation compatible with RV32.
- Use single decoder for XThead extensions
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 124 +++++++++++++++++++++
target/riscv/translate.c | 4 +-
target/riscv/xthead.decode | 20 ++++
5 files changed, 149 insertions(+), 2 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4b46130c5b..b995470dd6 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -110,6 +110,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
ISA_EXT_DATA_ENTRY(xtheadba, true, PRIV_VERSION_1_11_0, ext_xtheadba),
+ ISA_EXT_DATA_ENTRY(xtheadbb, true, PRIV_VERSION_1_11_0, ext_xtheadbb),
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
@@ -1075,6 +1076,7 @@ static Property riscv_cpu_extensions[] = {
/* 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("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 d3191bf27b..ff92705010 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -474,6 +474,7 @@ struct RISCVCPUConfig {
/* Vendor-specific custom extensions */
bool ext_xtheadba;
+ bool ext_xtheadbb;
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 a7da156869..ea6cd6e305 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -22,6 +22,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADBB(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadbb) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADCMO(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadcmo) { \
return false; \
@@ -67,6 +73,124 @@ GEN_TRANS_TH_ADDSL(1)
GEN_TRANS_TH_ADDSL(2)
GEN_TRANS_TH_ADDSL(3)
+/* XTheadBb */
+
+/* th.srri is an alternate encoding for rori (from Zbb) */
+static bool trans_th_srri(DisasContext *ctx, arg_th_srri * a)
+{
+ REQUIRE_XTHEADBB(ctx);
+ return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE,
+ tcg_gen_rotri_tl, gen_roriw, NULL);
+}
+
+/* th.srriw is an alternate encoding for roriw (from Zbb) */
+static bool trans_th_srriw(DisasContext *ctx, arg_th_srriw *a)
+{
+ REQUIRE_XTHEADBB(ctx);
+ REQUIRE_64BIT(ctx);
+ 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)
+{
+ REQUIRE_XTHEADBB(ctx);
+ return gen_th_bfextract(ctx, a, tcg_gen_sextract_tl);
+}
+
+static bool trans_th_extu(DisasContext *ctx, arg_th_extu *a)
+{
+ REQUIRE_XTHEADBB(ctx);
+ return gen_th_bfextract(ctx, a, tcg_gen_extract_tl);
+}
+
+/* th.ff0: find first zero (clz on an inverted input) */
+static bool gen_th_ff0(DisasContext *ctx, arg_th_ff0 *a, DisasExtend ext)
+{
+ TCGv dest = dest_gpr(ctx, a->rd);
+ TCGv src1 = get_gpr(ctx, a->rs1, ext);
+
+ int olen = get_olen(ctx);
+ TCGv t = tcg_temp_new();
+
+ tcg_gen_not_tl(t, src1);
+ if (olen != TARGET_LONG_BITS) {
+ if (olen == 32) {
+ gen_clzw(dest, t);
+ } else {
+ g_assert_not_reached();
+ }
+ } else {
+ gen_clz(dest, t);
+ }
+
+ tcg_temp_free(t);
+ gen_set_gpr(ctx, a->rd, dest);
+
+ return true;
+}
+
+static bool trans_th_ff0(DisasContext *ctx, arg_th_ff0 *a)
+{
+ REQUIRE_XTHEADBB(ctx);
+ return gen_th_ff0(ctx, a, EXT_NONE);
+}
+
+/* th.ff1 is an alternate encoding for clz (from Zbb) */
+static bool trans_th_ff1(DisasContext *ctx, arg_th_ff1 *a)
+{
+ REQUIRE_XTHEADBB(ctx);
+ return gen_unary_per_ol(ctx, a, EXT_NONE, gen_clz, gen_clzw);
+}
+
+static void gen_th_revw(TCGv ret, TCGv arg1)
+{
+ tcg_gen_bswap32_tl(ret, arg1, TCG_BSWAP_OS);
+}
+
+/* th.rev is an alternate encoding for the RV64 rev8 (from Zbb) */
+static bool trans_th_rev(DisasContext *ctx, arg_th_rev *a)
+{
+ REQUIRE_XTHEADBB(ctx);
+
+ return gen_unary_per_ol(ctx, a, EXT_NONE, tcg_gen_bswap_tl, gen_th_revw);
+}
+
+/* th.revw is a sign-extended byte-swap of the lower word */
+static bool trans_th_revw(DisasContext *ctx, arg_th_revw *a)
+{
+ REQUIRE_XTHEADBB(ctx);
+ REQUIRE_64BIT(ctx);
+ 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)
+{
+ REQUIRE_XTHEADBB(ctx);
+ return gen_unary(ctx, a, EXT_ZERO, gen_th_tstnbz);
+}
+
/* XTheadCmo */
static inline int priv_level(DisasContext *ctx)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 68baf84807..3bae961be0 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -130,8 +130,8 @@ static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
{
- return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadcmo ||
- ctx->cfg_ptr->ext_xtheadsync;
+ return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
+ ctx->cfg_ptr->ext_xtheadcmo || ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index b149f13018..8cd140891b 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -13,14 +13,23 @@
%rd 7:5
%rs1 15:5
%rs2 20:5
+%sh5 20:5
+%sh6 20:6
# Argument sets
&r rd rs1 rs2 !extern
+&r2 rd rs1 !extern
+&shift shamt rs1 rd !extern
+&th_bfext msb lsb rs1 rd
# Formats
@sfence_vm ....... ..... ..... ... ..... ....... %rs1
@rs2_s ....... ..... ..... ... ..... ....... %rs2 %rs1
@r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
+@r2 ....... ..... ..... ... ..... ....... &r2 %rs1 %rd
+@th_bfext msb:6 lsb:6 ..... ... ..... ....... &th_bfext %rs1 %rd
+@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
+@sh6 ...... ...... ..... ... ..... ....... &shift shamt=%sh6 %rs1 %rd
# XTheadBa
# Instead of defining a new encoding, we simply use the decoder to
@@ -38,6 +47,17 @@ th_addsl1 0000001 ..... ..... 001 ..... 0001011 @r
th_addsl2 0000010 ..... ..... 001 ..... 0001011 @r
th_addsl3 0000011 ..... ..... 001 ..... 0001011 @r
+# XTheadBb
+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
+
# XTheadCmo
th_dcache_call 0000000 00001 00000 000 00000 0001011
th_dcache_ciall 0000000 00011 00000 000 00000 0001011
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 05/14] RISC-V: Adding XTheadBs ISA extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (3 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 04/14] RISC-V: Adding XTheadBb " Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 06/14] RISC-V: Adding XTheadCondMov " Christoph Muellner
` (8 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the XTheadBs ISA extension.
The patch uses the T-Head specific decoder and translation.
Co-developed-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Split XtheadB* extension into individual commits
- Use single decoder for XThead extensions
target/riscv/cpu.c | 2 ++
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 15 +++++++++++++++
target/riscv/translate.c | 3 ++-
target/riscv/xthead.decode | 3 +++
5 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b995470dd6..805fec4d76 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -111,6 +111,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
ISA_EXT_DATA_ENTRY(xtheadba, true, PRIV_VERSION_1_11_0, ext_xtheadba),
ISA_EXT_DATA_ENTRY(xtheadbb, true, PRIV_VERSION_1_11_0, ext_xtheadbb),
+ ISA_EXT_DATA_ENTRY(xtheadbs, true, PRIV_VERSION_1_11_0, ext_xtheadbs),
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
@@ -1077,6 +1078,7 @@ static Property riscv_cpu_extensions[] = {
/* 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 ff92705010..2f92211d9f 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -475,6 +475,7 @@ struct RISCVCPUConfig {
/* 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 ea6cd6e305..339a54e3d6 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -28,6 +28,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADBS(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadbs) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADCMO(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadcmo) { \
return false; \
@@ -191,6 +197,15 @@ static bool trans_th_tstnbz(DisasContext *ctx, arg_th_tstnbz *a)
return gen_unary(ctx, a, EXT_ZERO, gen_th_tstnbz);
}
+/* XTheadBs */
+
+/* th.tst is an alternate encoding for bexti (from Zbs) */
+static bool trans_th_tst(DisasContext *ctx, arg_th_tst *a)
+{
+ REQUIRE_XTHEADBS(ctx);
+ return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bext);
+}
+
/* XTheadCmo */
static inline int priv_level(DisasContext *ctx)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 3bae961be0..96bdf5fb73 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -131,7 +131,8 @@ static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
{
return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
- ctx->cfg_ptr->ext_xtheadcmo || ctx->cfg_ptr->ext_xtheadsync;
+ ctx->cfg_ptr->ext_xtheadbs || ctx->cfg_ptr->ext_xtheadcmo ||
+ ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index 8cd140891b..8494805611 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -58,6 +58,9 @@ th_rev 1000001 00000 ..... 001 ..... 0001011 @r2
th_revw 1001000 00000 ..... 001 ..... 0001011 @r2
th_tstnbz 1000000 00000 ..... 001 ..... 0001011 @r2
+# XTheadBs
+th_tst 100010 ...... ..... 001 ..... 0001011 @sh6
+
# XTheadCmo
th_dcache_call 0000000 00001 00000 000 00000 0001011
th_dcache_ciall 0000000 00011 00000 000 00000 0001011
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 06/14] RISC-V: Adding XTheadCondMov ISA extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (4 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 05/14] RISC-V: Adding XTheadBs " Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 07/14] RISC-V: Adding T-Head multiply-accumulate instructions Christoph Muellner
` (7 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the XTheadCondMov ISA extension.
The patch uses the T-Head specific decoder and translation.
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Fix invalid use of register from dest_gpr()
- Use single decoder for XThead extensions
target/riscv/cpu.c | 2 ++
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 35 ++++++++++++++++++++++
target/riscv/translate.c | 2 +-
target/riscv/xthead.decode | 4 +++
5 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 805fec4d76..b3ede7223a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -113,6 +113,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(xtheadbb, true, PRIV_VERSION_1_11_0, ext_xtheadbb),
ISA_EXT_DATA_ENTRY(xtheadbs, true, PRIV_VERSION_1_11_0, ext_xtheadbs),
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
+ ISA_EXT_DATA_ENTRY(xtheadcondmov, true, PRIV_VERSION_1_11_0, ext_xtheadcondmov),
ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
};
@@ -1080,6 +1081,7 @@ static Property riscv_cpu_extensions[] = {
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("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, 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 2f92211d9f..5286bd487c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -477,6 +477,7 @@ struct RISCVCPUConfig {
bool ext_xtheadbb;
bool ext_xtheadbs;
bool ext_xtheadcmo;
+ bool ext_xtheadcondmov;
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 339a54e3d6..894b95a741 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -40,6 +40,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADCONDMOV(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadcondmov) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADSYNC(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadsync) { \
return false; \
@@ -264,6 +270,35 @@ NOP_PRIVCHECK(th_l2cache_call, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
NOP_PRIVCHECK(th_l2cache_ciall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
NOP_PRIVCHECK(th_l2cache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+/* XTheadCondMov */
+
+static bool gen_th_condmove(DisasContext *ctx, arg_r *a, TCGCond cond)
+{
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+ TCGv old = get_gpr(ctx, a->rd, EXT_NONE);
+ TCGv dest = dest_gpr(ctx, a->rd);
+
+ tcg_gen_movcond_tl(cond, dest, src2, ctx->zero, src1, old);
+
+ gen_set_gpr(ctx, a->rd, dest);
+ return true;
+}
+
+/* th.mveqz: "if (rs2 == 0) rd = rs1;" */
+static bool trans_th_mveqz(DisasContext *ctx, arg_th_mveqz *a)
+{
+ REQUIRE_XTHEADCONDMOV(ctx);
+ return gen_th_condmove(ctx, a, TCG_COND_EQ);
+}
+
+/* th.mvnez: "if (rs2 != 0) rd = rs1;" */
+static bool trans_th_mvnez(DisasContext *ctx, arg_th_mveqz *a)
+{
+ REQUIRE_XTHEADCONDMOV(ctx);
+ return gen_th_condmove(ctx, a, TCG_COND_NE);
+}
+
/* XTheadSync */
static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas *a)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 96bdf5fb73..d61705e775 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -132,7 +132,7 @@ static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
{
return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
ctx->cfg_ptr->ext_xtheadbs || ctx->cfg_ptr->ext_xtheadcmo ||
- ctx->cfg_ptr->ext_xtheadsync;
+ ctx->cfg_ptr->ext_xtheadcondmov || ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index 8494805611..a8ebd8a18b 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -84,6 +84,10 @@ th_l2cache_call 0000000 10101 00000 000 00000 0001011
th_l2cache_ciall 0000000 10111 00000 000 00000 0001011
th_l2cache_iall 0000000 10110 00000 000 00000 0001011
+# XTheadCondMov
+th_mveqz 0100000 ..... ..... 001 ..... 0001011 @r
+th_mvnez 0100001 ..... ..... 001 ..... 0001011 @r
+
# XTheadSync
th_sfence_vmas 0000010 ..... ..... 000 00000 0001011 @rs2_s
th_sync 0000000 11000 00000 000 00000 0001011
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 07/14] RISC-V: Adding T-Head multiply-accumulate instructions
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (5 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 06/14] RISC-V: Adding XTheadCondMov " Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension Christoph Muellner
` (6 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the T-Head MAC instructions.
The patch uses the T-Head specific decoder and translation.
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Use single decoder for XThead extensions
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 83 ++++++++++++++++++++++
target/riscv/translate.c | 3 +-
target/riscv/xthead.decode | 8 +++
5 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b3ede7223a..2ce8eb6a6f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -114,6 +114,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(xtheadbs, true, PRIV_VERSION_1_11_0, ext_xtheadbs),
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xtheadcondmov, true, PRIV_VERSION_1_11_0, ext_xtheadcondmov),
+ ISA_EXT_DATA_ENTRY(xtheadmac, true, PRIV_VERSION_1_11_0, ext_xtheadmac),
ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
};
@@ -1082,6 +1083,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false),
DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false),
+ DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, 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 5286bd487c..55aea777a0 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -478,6 +478,7 @@ struct RISCVCPUConfig {
bool ext_xtheadbs;
bool ext_xtheadcmo;
bool ext_xtheadcondmov;
+ bool ext_xtheadmac;
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 894b95a741..1c583ea8ec 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -46,6 +46,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADMAC(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadmac) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADSYNC(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadsync) { \
return false; \
@@ -299,6 +305,83 @@ static bool trans_th_mvnez(DisasContext *ctx, arg_th_mveqz *a)
return gen_th_condmove(ctx, a, TCG_COND_NE);
}
+/* XTheadMac */
+
+static bool gen_th_mac(DisasContext *ctx, arg_r *a,
+ void (*accumulate_func)(TCGv, TCGv, TCGv),
+ void (*extend_operand_func)(TCGv, TCGv))
+{
+ TCGv dest = dest_gpr(ctx, a->rd);
+ TCGv src0 = get_gpr(ctx, a->rd, EXT_NONE);
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
+ TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+ TCGv tmp = tcg_temp_new();
+
+ if (extend_operand_func) {
+ TCGv tmp2 = tcg_temp_new();
+ extend_operand_func(tmp, src1);
+ extend_operand_func(tmp2, src2);
+ tcg_gen_mul_tl(tmp, tmp, tmp2);
+ tcg_temp_free(tmp2);
+ } else {
+ tcg_gen_mul_tl(tmp, src1, src2);
+ }
+
+ accumulate_func(dest, src0, tmp);
+ gen_set_gpr(ctx, a->rd, dest);
+ tcg_temp_free(tmp);
+
+ return true;
+}
+
+/* th.mula: "rd = rd + rs1 * rs2" */
+static bool trans_th_mula(DisasContext *ctx, arg_th_mula *a)
+{
+ REQUIRE_XTHEADMAC(ctx);
+ return gen_th_mac(ctx, a, tcg_gen_add_tl, NULL);
+}
+
+/* th.mulah: "rd = sext.w(rd + sext.w(rs1[15:0]) * sext.w(rs2[15:0]))" */
+static bool trans_th_mulah(DisasContext *ctx, arg_th_mulah *a)
+{
+ REQUIRE_XTHEADMAC(ctx);
+ ctx->ol = MXL_RV32;
+ return gen_th_mac(ctx, a, tcg_gen_add_tl, tcg_gen_ext16s_tl);
+}
+
+/* th.mulaw: "rd = sext.w(rd + rs1 * rs2)" */
+static bool trans_th_mulaw(DisasContext *ctx, arg_th_mulaw *a)
+{
+ REQUIRE_XTHEADMAC(ctx);
+ REQUIRE_64BIT(ctx);
+ ctx->ol = MXL_RV32;
+ return gen_th_mac(ctx, a, tcg_gen_add_tl, NULL);
+}
+
+/* th.muls: "rd = rd - rs1 * rs2" */
+static bool trans_th_muls(DisasContext *ctx, arg_th_muls *a)
+{
+ REQUIRE_XTHEADMAC(ctx);
+ return gen_th_mac(ctx, a, tcg_gen_sub_tl, NULL);
+}
+
+/* th.mulsh: "rd = sext.w(rd - sext.w(rs1[15:0]) * sext.w(rs2[15:0]))" */
+static bool trans_th_mulsh(DisasContext *ctx, arg_th_mulsh *a)
+{
+ REQUIRE_XTHEADMAC(ctx);
+ ctx->ol = MXL_RV32;
+ return gen_th_mac(ctx, a, tcg_gen_sub_tl, tcg_gen_ext16s_tl);
+}
+
+/* th.mulsw: "rd = sext.w(rd - rs1 * rs2)" */
+static bool trans_th_mulsw(DisasContext *ctx, arg_th_mulsw *a)
+{
+ REQUIRE_XTHEADMAC(ctx);
+ REQUIRE_64BIT(ctx);
+ ctx->ol = MXL_RV32;
+ return gen_th_mac(ctx, a, tcg_gen_sub_tl, NULL);
+}
+
/* XTheadSync */
static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas *a)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index d61705e775..5be1c9da69 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -132,7 +132,8 @@ static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
{
return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
ctx->cfg_ptr->ext_xtheadbs || ctx->cfg_ptr->ext_xtheadcmo ||
- ctx->cfg_ptr->ext_xtheadcondmov || ctx->cfg_ptr->ext_xtheadsync;
+ ctx->cfg_ptr->ext_xtheadcondmov || ctx->cfg_ptr->ext_xtheadmac ||
+ ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index a8ebd8a18b..696de6cecf 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -88,6 +88,14 @@ th_l2cache_iall 0000000 10110 00000 000 00000 0001011
th_mveqz 0100000 ..... ..... 001 ..... 0001011 @r
th_mvnez 0100001 ..... ..... 001 ..... 0001011 @r
+# XTheadMac
+th_mula 00100 00 ..... ..... 001 ..... 0001011 @r
+th_mulah 00101 00 ..... ..... 001 ..... 0001011 @r
+th_mulaw 00100 10 ..... ..... 001 ..... 0001011 @r
+th_muls 00100 01 ..... ..... 001 ..... 0001011 @r
+th_mulsh 00101 01 ..... ..... 001 ..... 0001011 @r
+th_mulsw 00100 11 ..... ..... 001 ..... 0001011 @r
+
# XTheadSync
th_sfence_vmas 0000010 ..... ..... 000 00000 0001011 @rs2_s
th_sync 0000000 11000 00000 000 00000 0001011
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (6 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 07/14] RISC-V: Adding T-Head multiply-accumulate instructions Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 20:44 ` Richard Henderson
2023-01-24 19:59 ` [PATCH v3 09/14] RISC-V: Adding T-Head MemIdx extension Christoph Muellner
` (5 subsequent siblings)
13 siblings, 1 reply; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the T-Head MemPair instructions.
The patch uses the T-Head specific decoder and translation.
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Use single decoder for XThead extensions
- Use get_address() to calculate addresses
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 88 ++++++++++++++++++++++
target/riscv/translate.c | 2 +-
target/riscv/xthead.decode | 13 ++++
5 files changed, 105 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 2ce8eb6a6f..e3a10f782c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -115,6 +115,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xtheadcondmov, true, PRIV_VERSION_1_11_0, ext_xtheadcondmov),
ISA_EXT_DATA_ENTRY(xtheadmac, true, PRIV_VERSION_1_11_0, ext_xtheadmac),
+ ISA_EXT_DATA_ENTRY(xtheadmempair, true, PRIV_VERSION_1_11_0, ext_xtheadmempair),
ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
};
@@ -1084,6 +1085,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false),
DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false),
+ DEFINE_PROP_BOOL("xtheadmempair", RISCVCPU, cfg.ext_xtheadmempair, 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 55aea777a0..4f5f3b2c20 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -479,6 +479,7 @@ struct RISCVCPUConfig {
bool ext_xtheadcmo;
bool ext_xtheadcondmov;
bool ext_xtheadmac;
+ bool ext_xtheadmempair;
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 1c583ea8ec..7ab2a7a48e 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -52,6 +52,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADMEMPAIR(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadmempair) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADSYNC(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadsync) { \
return false; \
@@ -382,6 +388,88 @@ static bool trans_th_mulsw(DisasContext *ctx, arg_th_mulsw *a)
return gen_th_mac(ctx, a, tcg_gen_sub_tl, NULL);
}
+/* XTheadMemPair */
+
+static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
+ int shamt)
+{
+ TCGv rd1 = dest_gpr(ctx, a->rd1);
+ TCGv rd2 = dest_gpr(ctx, a->rd2);
+ TCGv addr1 = tcg_temp_new();
+ TCGv addr2 = tcg_temp_new();
+
+ addr1 = get_address(ctx, a->rs, a->sh2 << shamt);
+ if ((memop & MO_SIZE) == MO_64) {
+ addr2 = get_address(ctx, a->rs, 8 + (a->sh2 << shamt));
+ } else {
+ addr2 = get_address(ctx, a->rs, 4 + (a->sh2 << shamt));
+ }
+
+ tcg_gen_qemu_ld_tl(rd1, addr1, ctx->mem_idx, memop);
+ tcg_gen_qemu_ld_tl(rd2, addr2, ctx->mem_idx, memop);
+ gen_set_gpr(ctx, a->rd1, rd1);
+ gen_set_gpr(ctx, a->rd2, rd2);
+
+ tcg_temp_free(addr1);
+ tcg_temp_free(addr2);
+ return true;
+}
+
+static bool trans_th_ldd(DisasContext *ctx, arg_th_pair *a)
+{
+ REQUIRE_XTHEADMEMPAIR(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_loadpair_tl(ctx, a, MO_TESQ, 4);
+}
+
+static bool trans_th_lwd(DisasContext *ctx, arg_th_pair *a)
+{
+ REQUIRE_XTHEADMEMPAIR(ctx);
+ return gen_loadpair_tl(ctx, a, MO_TESL, 3);
+}
+
+static bool trans_th_lwud(DisasContext *ctx, arg_th_pair *a)
+{
+ REQUIRE_XTHEADMEMPAIR(ctx);
+ return gen_loadpair_tl(ctx, a, MO_TEUL, 3);
+}
+
+static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
+ int shamt)
+{
+ TCGv data1 = get_gpr(ctx, a->rd1, EXT_NONE);
+ TCGv data2 = get_gpr(ctx, a->rd2, EXT_NONE);
+ TCGv addr1 = tcg_temp_new();
+ TCGv addr2 = tcg_temp_new();
+
+ addr1 = get_address(ctx, a->rs, a->sh2 << shamt);
+ if ((memop & MO_SIZE) == MO_64) {
+ addr2 = get_address(ctx, a->rs, 8 + (a->sh2 << shamt));
+ } else {
+ addr2 = get_address(ctx, a->rs, 4 + (a->sh2 << shamt));
+ }
+
+ tcg_gen_qemu_st_tl(data1, addr1, ctx->mem_idx, memop);
+ tcg_gen_qemu_st_tl(data2, addr2, ctx->mem_idx, memop);
+
+ tcg_temp_free(addr1);
+ tcg_temp_free(addr2);
+ return true;
+}
+
+static bool trans_th_sdd(DisasContext *ctx, arg_th_pair *a)
+{
+ REQUIRE_XTHEADMEMPAIR(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_storepair_tl(ctx, a, MO_TESQ, 4);
+}
+
+static bool trans_th_swd(DisasContext *ctx, arg_th_pair *a)
+{
+ REQUIRE_XTHEADMEMPAIR(ctx);
+ return gen_storepair_tl(ctx, a, MO_TESL, 3);
+}
+
/* XTheadSync */
static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas *a)
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 5be1c9da69..27bab07994 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -133,7 +133,7 @@ static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
ctx->cfg_ptr->ext_xtheadbs || ctx->cfg_ptr->ext_xtheadcmo ||
ctx->cfg_ptr->ext_xtheadcondmov || ctx->cfg_ptr->ext_xtheadmac ||
- ctx->cfg_ptr->ext_xtheadsync;
+ ctx->cfg_ptr->ext_xtheadmempair || ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index 696de6cecf..ff2a83b56d 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -11,16 +11,21 @@
# Fields:
%rd 7:5
+%rd1 7:5
+%rs 15:5
%rs1 15:5
+%rd2 20:5
%rs2 20:5
%sh5 20:5
%sh6 20:6
+%sh2 25:2
# Argument sets
&r rd rs1 rs2 !extern
&r2 rd rs1 !extern
&shift shamt rs1 rd !extern
&th_bfext msb lsb rs1 rd
+&th_pair rd1 rs rd2 sh2
# Formats
@sfence_vm ....... ..... ..... ... ..... ....... %rs1
@@ -30,6 +35,7 @@
@th_bfext msb:6 lsb:6 ..... ... ..... ....... &th_bfext %rs1 %rd
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
@sh6 ...... ...... ..... ... ..... ....... &shift shamt=%sh6 %rs1 %rd
+@th_pair ..... .. ..... ..... ... ..... ....... &th_pair %rd1 %rs %rd2 %sh2
# XTheadBa
# Instead of defining a new encoding, we simply use the decoder to
@@ -96,6 +102,13 @@ th_muls 00100 01 ..... ..... 001 ..... 0001011 @r
th_mulsh 00101 01 ..... ..... 001 ..... 0001011 @r
th_mulsw 00100 11 ..... ..... 001 ..... 0001011 @r
+# XTheadMemPair
+th_ldd 11111 .. ..... ..... 100 ..... 0001011 @th_pair
+th_lwd 11100 .. ..... ..... 100 ..... 0001011 @th_pair
+th_lwud 11110 .. ..... ..... 100 ..... 0001011 @th_pair
+th_sdd 11111 .. ..... ..... 101 ..... 0001011 @th_pair
+th_swd 11100 .. ..... ..... 101 ..... 0001011 @th_pair
+
# XTheadSync
th_sfence_vmas 0000010 ..... ..... 000 00000 0001011 @rs2_s
th_sync 0000000 11000 00000 000 00000 0001011
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension
2023-01-24 19:59 ` [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension Christoph Muellner
@ 2023-01-24 20:44 ` Richard Henderson
2023-01-30 2:03 ` LIU Zhiwei
2023-01-31 18:01 ` Christoph Müllner
0 siblings, 2 replies; 30+ messages in thread
From: Richard Henderson @ 2023-01-24 20:44 UTC (permalink / raw)
To: Christoph Muellner, qemu-riscv, qemu-devel, Alistair Francis,
Bin Meng, Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia, Yunhai Shang,
Zhiwei Liu
On 1/24/23 09:59, Christoph Muellner wrote:
> +static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
> + int shamt)
> +{
> + TCGv rd1 = dest_gpr(ctx, a->rd1);
> + TCGv rd2 = dest_gpr(ctx, a->rd2);
> + TCGv addr1 = tcg_temp_new();
> + TCGv addr2 = tcg_temp_new();
> +
> + addr1 = get_address(ctx, a->rs, a->sh2 << shamt);
> + if ((memop & MO_SIZE) == MO_64) {
> + addr2 = get_address(ctx, a->rs, 8 + (a->sh2 << shamt));
> + } else {
> + addr2 = get_address(ctx, a->rs, 4 + (a->sh2 << shamt));
> + }
> +
> + tcg_gen_qemu_ld_tl(rd1, addr1, ctx->mem_idx, memop);
> + tcg_gen_qemu_ld_tl(rd2, addr2, ctx->mem_idx, memop);
> + gen_set_gpr(ctx, a->rd1, rd1);
> + gen_set_gpr(ctx, a->rd2, rd2);
Since dest_gpr may return cpu_gpr[n], this may update the rd1 before recognizing the
exception that the second load may generate. Is that correct?
The manual says that rd1, rd2, and rs1 must not be the same, but you do not check this.
r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension
2023-01-24 20:44 ` Richard Henderson
@ 2023-01-30 2:03 ` LIU Zhiwei
2023-01-30 5:43 ` Richard Henderson
2023-01-31 18:01 ` Christoph Müllner
1 sibling, 1 reply; 30+ messages in thread
From: LIU Zhiwei @ 2023-01-30 2:03 UTC (permalink / raw)
To: Richard Henderson, Christoph Muellner, qemu-riscv, qemu-devel,
Alistair Francis, Bin Meng, Philipp Tomsich, Heiko Stübner,
Palmer Dabbelt, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang
On 2023/1/25 4:44, Richard Henderson wrote:
> On 1/24/23 09:59, Christoph Muellner wrote:
>> +static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp
>> memop,
>> + int shamt)
>> +{
>> + TCGv rd1 = dest_gpr(ctx, a->rd1);
>> + TCGv rd2 = dest_gpr(ctx, a->rd2);
>> + TCGv addr1 = tcg_temp_new();
>> + TCGv addr2 = tcg_temp_new();
>> +
>> + addr1 = get_address(ctx, a->rs, a->sh2 << shamt);
>> + if ((memop & MO_SIZE) == MO_64) {
>> + addr2 = get_address(ctx, a->rs, 8 + (a->sh2 << shamt));
>> + } else {
>> + addr2 = get_address(ctx, a->rs, 4 + (a->sh2 << shamt));
>> + }
>> +
>> + tcg_gen_qemu_ld_tl(rd1, addr1, ctx->mem_idx, memop);
>> + tcg_gen_qemu_ld_tl(rd2, addr2, ctx->mem_idx, memop);
>> + gen_set_gpr(ctx, a->rd1, rd1);
>> + gen_set_gpr(ctx, a->rd2, rd2);
>
> Since dest_gpr may return cpu_gpr[n], this may update the rd1 before
> recognizing the exception that the second load may generate. Is that
> correct?
Thanks. It's a bug. We should load all memory addresses to local TCG
temps first.
Do you think we should probe all the memory addresses for the store pair
instructions? If so, can we avoid the use of a helper function?
>
> The manual says that rd1, rd2, and rs1 must not be the same, but you
> do not check this.
The main reason is that assembler can do this check. Is it necessary to
check this in QEMU?
Best Regards,
Zhiwei
>
>
> r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension
2023-01-30 2:03 ` LIU Zhiwei
@ 2023-01-30 5:43 ` Richard Henderson
2023-01-30 8:41 ` LIU Zhiwei
0 siblings, 1 reply; 30+ messages in thread
From: Richard Henderson @ 2023-01-30 5:43 UTC (permalink / raw)
To: LIU Zhiwei, Christoph Muellner, qemu-riscv, qemu-devel,
Alistair Francis, Bin Meng, Philipp Tomsich, Heiko Stübner,
Palmer Dabbelt, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang
On 1/29/23 16:03, LIU Zhiwei wrote:
> Thanks. It's a bug. We should load all memory addresses to local TCG temps first.
>
> Do you think we should probe all the memory addresses for the store pair instructions? If
> so, can we avoid the use of a helper function?
Depends on what the hardware does. Even with a trap in the middle the stores are
restartable, since no register state changes.
But if you'd like no changes verifying both stores, for this case you can pack the pair
into a larger data type: TCGv_i64 for pair of 32-bit, and TCGv_i128 for pair of 64-bit.
Patches for TCGv_i128 [1] are just finishing review; patches to describe atomicity of the
larger operation are also on list [2]. Anyway, the idea is that you issue one TCG memory
operation, the entire operation is validated, and then the stores happen.
> The main reason is that assembler can do this check. Is it necessary to check this in QEMU?
Yes. Conciser what happens when the insn is encoded with .long. Does the hardware trap
an illegal instruction? Is the behavior simply unspecified? The manual could be improved
to specify, akin to the Arm terms: UNDEFINED, CONSTRAINED UNPREDICTABLE, IMPLEMENTATION
DEFINED, etc.
r~
[1] https://patchew.org/QEMU/20230126043824.54819-1-richard.henderson@linaro.org/
[2] https://patchew.org/QEMU/20221118094754.242910-1-richard.henderson@linaro.org/
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension
2023-01-30 5:43 ` Richard Henderson
@ 2023-01-30 8:41 ` LIU Zhiwei
2023-01-30 19:03 ` Richard Henderson
0 siblings, 1 reply; 30+ messages in thread
From: LIU Zhiwei @ 2023-01-30 8:41 UTC (permalink / raw)
To: Richard Henderson, Christoph Muellner, qemu-riscv, qemu-devel,
Alistair Francis, Bin Meng, Philipp Tomsich, Heiko Stübner,
Palmer Dabbelt, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang
[-- Attachment #1: Type: text/plain, Size: 2836 bytes --]
On 2023/1/30 13:43, Richard Henderson wrote:
> On 1/29/23 16:03, LIU Zhiwei wrote:
>> Thanks. It's a bug. We should load all memory addresses to local TCG
>> temps first.
>>
>> Do you think we should probe all the memory addresses for the store
>> pair instructions? If so, can we avoid the use of a helper function?
>
> Depends on what the hardware does. Even with a trap in the middle the
> stores are restartable, since no register state changes.
I refer to the specification of LDP and STP on AARCH64. The
specification allows
"any access performed before the exception was taken is repeated".
In detailed,
"If, according to these rules, an instruction is executed as a sequence of accesses, exceptions, including interrupts,
can be taken during that sequence, regardless of the memory type being accessed. If any of these exceptions are
returned from using their preferred return address, the instruction that generated the sequence of accesses is
re-executed, and so any access performed before the exception was taken is repeated. See also Taking an interrupt
during a multi-access load or store on page D1-4664."
However I see the implementation of LDP and STP on QEMU are in different
ways. LDP will only load the first register when it ensures no trap in
the second access.
So I have two questions here.
1) One for the QEMU implementation about LDP. Can we implement the LDP
as two directly loads to cpu registers instead of local TCG temps?
2) One for the comment. Why register state changes cause
non-restartable? Do you mean if the first register changes, it may
influence the calculation of address after the trap?
"Even with a trap in the middle the stores are restartable, since no register state changes."
>
> But if you'd like no changes verifying both stores, for this case you
> can pack the pair into a larger data type: TCGv_i64 for pair of
> 32-bit, and TCGv_i128 for pair of 64-bit.
> Patches for TCGv_i128 [1] are just finishing review; patches to
> describe atomicity of the larger operation are also on list [2].
> Anyway, the idea is that you issue one TCG memory operation, the
> entire operation is validated, and then the stores happen.
>
>
>> The main reason is that assembler can do this check. Is it necessary
>> to check this in QEMU?
>
> Yes. Conciser what happens when the insn is encoded with .long. Does
> the hardware trap an illegal instruction? Is the behavior simply
> unspecified? The manual could be improved to specify, akin to the Arm
> terms: UNDEFINED, CONSTRAINED UNPREDICTABLE, IMPLEMENTATION DEFINED, etc.
>
>
Thanks, I will fix the manual.
Best Regards,
Zhiwei
> r~
>
> [1]
> https://patchew.org/QEMU/20230126043824.54819-1-richard.henderson@linaro.org/
> [2]
> https://patchew.org/QEMU/20221118094754.242910-1-richard.henderson@linaro.org/
[-- Attachment #2: Type: text/html, Size: 4185 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension
2023-01-30 8:41 ` LIU Zhiwei
@ 2023-01-30 19:03 ` Richard Henderson
2023-01-31 2:34 ` LIU Zhiwei
0 siblings, 1 reply; 30+ messages in thread
From: Richard Henderson @ 2023-01-30 19:03 UTC (permalink / raw)
To: LIU Zhiwei, Christoph Muellner, qemu-riscv, qemu-devel,
Alistair Francis, Bin Meng, Philipp Tomsich, Heiko Stübner,
Palmer Dabbelt, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang
On 1/29/23 22:41, LIU Zhiwei wrote:
>
> On 2023/1/30 13:43, Richard Henderson wrote:
>> On 1/29/23 16:03, LIU Zhiwei wrote:
>>> Thanks. It's a bug. We should load all memory addresses to local TCG temps first.
>>>
>>> Do you think we should probe all the memory addresses for the store pair instructions?
>>> If so, can we avoid the use of a helper function?
>>
>> Depends on what the hardware does. Even with a trap in the middle the stores are
>> restartable, since no register state changes.
>
> I refer to the specification of LDP and STP on AARCH64. The specification allows
>
> "any access performed before the exception was taken is repeated".
>
> In detailed,
>
> "If, according to these rules, an instruction is executed as a sequence of accesses, exceptions, including interrupts,
> can be taken during that sequence, regardless of the memory type being accessed. If any of these exceptions are
> returned from using their preferred return address, the instruction that generated the sequence of accesses is
> re-executed, and so any access performed before the exception was taken is repeated. See also Taking an interrupt
> during a multi-access load or store on page D1-4664."
>
> However I see the implementation of LDP and STP on QEMU are in different ways. LDP will
> only load the first register when it ensures no trap in the second access.
>
> So I have two questions here.
>
> 1) One for the QEMU implementation about LDP. Can we implement the LDP as two directly
> loads to cpu registers instead of local TCG temps?
For the Thead specification, where rd1 != rs1 (and you enforce it), then yes, I suppose
you could load directly to the cpu registers, because on restart rs1 would be unmodified.
For AArch64, which you quote above, there is no constraint that the destinations do not
overlap the address register, so we must implement "LDP r0, r1, [r0]" as a load into temps.
> 2) One for the comment. Why register state changes cause non-restartable? Do you mean if
> the first register changes, it may influence the calculation of address after the trap?
Yes, that's what I mean about non-restartable -- if any of the input registers are changed
before the trap is recognized.
>> Yes. Conciser what happens when the insn is encoded with .long. Does the hardware trap
>> an illegal instruction? Is the behavior simply unspecified? The manual could be
>> improved to specify, akin to the Arm terms: UNDEFINED, CONSTRAINED UNPREDICTABLE,
>> IMPLEMENTATION DEFINED, etc.
>>
>>
> Thanks, I will fix the manual.
Excellent, thanks.
r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension
2023-01-30 19:03 ` Richard Henderson
@ 2023-01-31 2:34 ` LIU Zhiwei
0 siblings, 0 replies; 30+ messages in thread
From: LIU Zhiwei @ 2023-01-31 2:34 UTC (permalink / raw)
To: Richard Henderson, Christoph Muellner, qemu-riscv, qemu-devel,
Alistair Francis, Bin Meng, Philipp Tomsich, Heiko Stübner,
Palmer Dabbelt, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang
On 2023/1/31 3:03, Richard Henderson wrote:
> On 1/29/23 22:41, LIU Zhiwei wrote:
>>
>> On 2023/1/30 13:43, Richard Henderson wrote:
>>> On 1/29/23 16:03, LIU Zhiwei wrote:
>>>> Thanks. It's a bug. We should load all memory addresses to local
>>>> TCG temps first.
>>>>
>>>> Do you think we should probe all the memory addresses for the store
>>>> pair instructions? If so, can we avoid the use of a helper function?
>>>
>>> Depends on what the hardware does. Even with a trap in the middle
>>> the stores are restartable, since no register state changes.
>>
>> I refer to the specification of LDP and STP on AARCH64. The
>> specification allows
>>
>> "any access performed before the exception was taken is repeated".
>>
>> In detailed,
>>
>> "If, according to these rules, an instruction is executed as a
>> sequence of accesses, exceptions, including interrupts,
>> can be taken during that sequence, regardless of the memory type
>> being accessed. If any of these exceptions are
>> returned from using their preferred return address, the instruction
>> that generated the sequence of accesses is
>> re-executed, and so any access performed before the exception was
>> taken is repeated. See also Taking an interrupt
>> during a multi-access load or store on page D1-4664."
>>
>> However I see the implementation of LDP and STP on QEMU are in
>> different ways. LDP will only load the first register when it ensures
>> no trap in the second access.
>>
>> So I have two questions here.
>>
>> 1) One for the QEMU implementation about LDP. Can we implement the
>> LDP as two directly loads to cpu registers instead of local TCG temps?
>
> For the Thead specification, where rd1 != rs1 (and you enforce it),
> then yes, I suppose you could load directly to the cpu registers,
> because on restart rs1 would be unmodified.
>
> For AArch64, which you quote above, there is no constraint that the
> destinations do not overlap the address register, so we must implement
> "LDP r0, r1, [r0]" as a load into temps.
>
Got it. Thanks.
>
>> 2) One for the comment. Why register state changes cause
>> non-restartable? Do you mean if the first register changes, it may
>> influence the calculation of address after the trap?
>
> Yes, that's what I mean about non-restartable -- if any of the input
> registers are changed before the trap is recognized.
>
>
Thanks for the clarification.
Once I thought the reason of non-restartable is the side effects of
repeat execution, which may cause watchpoint matches twice or access
MMIO device twice.
>>> Yes. Conciser what happens when the insn is encoded with .long.
>>> Does the hardware trap an illegal instruction? Is the behavior
>>> simply unspecified? The manual could be improved to specify, akin
>>> to the Arm terms: UNDEFINED, CONSTRAINED UNPREDICTABLE,
>>> IMPLEMENTATION DEFINED, etc.
>>>
>>>
>> Thanks, I will fix the manual.
The manual has been fixed by Christopher. Thanks.
Best Regards,
Zhiwei
>
> Excellent, thanks.
>
>
> r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension
2023-01-24 20:44 ` Richard Henderson
2023-01-30 2:03 ` LIU Zhiwei
@ 2023-01-31 18:01 ` Christoph Müllner
1 sibling, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-01-31 18:01 UTC (permalink / raw)
To: Richard Henderson
Cc: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt, Nelson Chu,
Kito Cheng, Cooper Qu, Lifang Xia, Yunhai Shang, Zhiwei Liu
On Tue, Jan 24, 2023 at 9:44 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 1/24/23 09:59, Christoph Muellner wrote:
> > +static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
> > + int shamt)
> > +{
> > + TCGv rd1 = dest_gpr(ctx, a->rd1);
> > + TCGv rd2 = dest_gpr(ctx, a->rd2);
> > + TCGv addr1 = tcg_temp_new();
> > + TCGv addr2 = tcg_temp_new();
> > +
> > + addr1 = get_address(ctx, a->rs, a->sh2 << shamt);
> > + if ((memop & MO_SIZE) == MO_64) {
> > + addr2 = get_address(ctx, a->rs, 8 + (a->sh2 << shamt));
> > + } else {
> > + addr2 = get_address(ctx, a->rs, 4 + (a->sh2 << shamt));
> > + }
> > +
> > + tcg_gen_qemu_ld_tl(rd1, addr1, ctx->mem_idx, memop);
> > + tcg_gen_qemu_ld_tl(rd2, addr2, ctx->mem_idx, memop);
> > + gen_set_gpr(ctx, a->rd1, rd1);
> > + gen_set_gpr(ctx, a->rd2, rd2);
>
> Since dest_gpr may return cpu_gpr[n], this may update the rd1 before recognizing the
> exception that the second load may generate. Is that correct?
Solved in v4 by using temporaries.
>
> The manual says that rd1, rd2, and rs1 must not be the same, but you do not check this.
Fixed in v4.
Thank you!
>
>
> r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v3 09/14] RISC-V: Adding T-Head MemIdx extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (7 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 08/14] RISC-V: Adding T-Head MemPair extension Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 21:21 ` Richard Henderson
2023-01-24 19:59 ` [PATCH v3 10/14] RISC-V: Adding T-Head FMemIdx extension Christoph Muellner
` (4 subsequent siblings)
13 siblings, 1 reply; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the T-Head MemIdx instructions.
The patch uses the T-Head specific decoder and translation.
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Use single decoder for XThead extensions
- Avoid signed-bitfield-extraction by using signed immediate field imm5
- Use get_address() to calculate addresses
- Introduce helper get_th_address_indexed for rs1+(rs2<<imm2) calculation
- Introduce get_address_indexed() for register offsets (like get_address())
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 377 +++++++++++++++++++++
target/riscv/translate.c | 21 +-
target/riscv/xthead.decode | 54 +++
5 files changed, 454 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e3a10f782c..eb8bbfa436 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -115,6 +115,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xtheadcondmov, true, PRIV_VERSION_1_11_0, ext_xtheadcondmov),
ISA_EXT_DATA_ENTRY(xtheadmac, true, PRIV_VERSION_1_11_0, ext_xtheadmac),
+ ISA_EXT_DATA_ENTRY(xtheadmemidx, true, PRIV_VERSION_1_11_0, ext_xtheadmemidx),
ISA_EXT_DATA_ENTRY(xtheadmempair, true, PRIV_VERSION_1_11_0, ext_xtheadmempair),
ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
@@ -1085,6 +1086,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false),
DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false),
+ DEFINE_PROP_BOOL("xtheadmemidx", RISCVCPU, cfg.ext_xtheadmemidx, false),
DEFINE_PROP_BOOL("xtheadmempair", RISCVCPU, cfg.ext_xtheadmempair, 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 4f5f3b2c20..4882b9a9cc 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -479,6 +479,7 @@ struct RISCVCPUConfig {
bool ext_xtheadcmo;
bool ext_xtheadcondmov;
bool ext_xtheadmac;
+ bool ext_xtheadmemidx;
bool ext_xtheadmempair;
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 7ab2a7a48e..e41f3be9a6 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -52,6 +52,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADMEMIDX(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadmemidx) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADMEMPAIR(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadmempair) { \
return false; \
@@ -64,6 +70,30 @@
} \
} while (0)
+/*
+ * Calculate and return the address for indexed mem operations:
+ * If !zext_offs, then the address is rs1 + (rs2 << imm2).
+ * If zext_offs, then the address is rs1 + (zext(rs2[31:0]) << imm2).
+ */
+static TCGv get_th_address_indexed(DisasContext *ctx, int rs1, int rs2,
+ int imm2, bool zext_offs)
+{
+ TCGv src2 = get_gpr(ctx, rs2, EXT_NONE);
+ TCGv offs = tcg_temp_new();
+
+ if (zext_offs) {
+ tcg_gen_extract_tl(offs, src2, 0, 32);
+ tcg_gen_shli_tl(offs, offs, imm2);
+ } else {
+ tcg_gen_shli_tl(offs, src2, imm2);
+ }
+
+ TCGv addr = get_address_indexed(ctx, rs1, offs);
+
+ tcg_temp_free(offs);
+ return addr;
+}
+
/* XTheadBa */
/*
@@ -388,6 +418,353 @@ static bool trans_th_mulsw(DisasContext *ctx, arg_th_mulsw *a)
return gen_th_mac(ctx, a, tcg_gen_sub_tl, NULL);
}
+/* XTheadMemIdx */
+
+/*
+ * Load with memop from indexed address and add (imm5 << imm2) to rs1.
+ * If !preinc, then the load address is rs1.
+ * If preinc, then the load address is rs1 + (imm5) << imm2).
+ */
+static bool gen_load_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop,
+ bool preinc)
+{
+ TCGv rd = dest_gpr(ctx, a->rd);
+ TCGv addr = get_address(ctx, a->rs1, preinc ? a->imm5 << a->imm2 : 0);
+
+ tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
+ addr = get_address(ctx, a->rs1, !preinc ? a->imm5 << a->imm2 : 0);
+ gen_set_gpr(ctx, a->rd, rd);
+ gen_set_gpr(ctx, a->rs1, addr);
+
+ return true;
+}
+
+/*
+ * Store with memop to indexed address and add (imm5 << imm2) to rs1.
+ * If !preinc, then the store address is rs1.
+ * If preinc, then the store address is rs1 + (imm5) << imm2).
+ */
+static bool gen_store_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop,
+ bool preinc)
+{
+ TCGv data = get_gpr(ctx, a->rd, EXT_NONE);
+ TCGv addr = get_address(ctx, a->rs1, preinc ? a->imm5 << a->imm2 : 0);
+
+ tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop);
+ addr = get_address(ctx, a->rs1, !preinc ? a->imm5 << a->imm2 : 0);
+ gen_set_gpr(ctx, a->rs1, addr);
+
+ return true;
+}
+
+static bool trans_th_ldia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_load_inc(ctx, a, MO_TESQ, false);
+}
+
+static bool trans_th_ldib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_load_inc(ctx, a, MO_TESQ, true);
+}
+
+static bool trans_th_lwia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_TESL, false);
+}
+
+static bool trans_th_lwib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_TESL, true);
+}
+
+static bool trans_th_lwuia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_load_inc(ctx, a, MO_TEUL, false);
+}
+
+static bool trans_th_lwuib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_load_inc(ctx, a, MO_TEUL, true);
+}
+
+static bool trans_th_lhia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_TESW, false);
+}
+
+static bool trans_th_lhib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_TESW, true);
+}
+
+static bool trans_th_lhuia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_TEUW, false);
+}
+
+static bool trans_th_lhuib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_TEUW, true);
+}
+
+static bool trans_th_lbia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_SB, false);
+}
+
+static bool trans_th_lbib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_SB, true);
+}
+
+static bool trans_th_lbuia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_UB, false);
+}
+
+static bool trans_th_lbuib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_inc(ctx, a, MO_UB, true);
+}
+
+static bool trans_th_sdia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_store_inc(ctx, a, MO_TESQ, false);
+}
+
+static bool trans_th_sdib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_store_inc(ctx, a, MO_TESQ, true);
+}
+
+static bool trans_th_swia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_inc(ctx, a, MO_TESL, false);
+}
+
+static bool trans_th_swib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_inc(ctx, a, MO_TESL, true);
+}
+
+static bool trans_th_shia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_inc(ctx, a, MO_TESW, false);
+}
+
+static bool trans_th_shib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_inc(ctx, a, MO_TESW, true);
+}
+
+static bool trans_th_sbia(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_inc(ctx, a, MO_SB, false);
+}
+
+static bool trans_th_sbib(DisasContext *ctx, arg_th_meminc *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_inc(ctx, a, MO_SB, true);
+}
+
+/*
+ * Load with memop from indexed address.
+ * If !zext_offs, then address is rs1 + (rs2 << imm2).
+ * If zext_offs, then address is rs1 + (zext(rs2[31:0]) << imm2).
+ */
+static bool gen_load_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop,
+ bool zext_offs)
+{
+ TCGv rd = dest_gpr(ctx, a->rd);
+ TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs);
+
+ tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
+ gen_set_gpr(ctx, a->rd, rd);
+
+ return true;
+}
+
+/*
+ * Store with memop to indexed address.
+ * If !zext_offs, then address is rs1 + (rs2 << imm2).
+ * If zext_offs, then address is rs1 + (zext(rs2[31:0]) << imm2).
+ */
+static bool gen_store_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop,
+ bool zext_offs)
+{
+ TCGv data = get_gpr(ctx, a->rd, EXT_NONE);
+ TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs);
+
+ tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop);
+
+ return true;
+}
+
+static bool trans_th_lrd(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_load_idx(ctx, a, MO_TESQ, false);
+}
+
+static bool trans_th_lrw(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_TESL, false);
+}
+
+static bool trans_th_lrwu(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_load_idx(ctx, a, MO_TEUL, false);
+}
+
+static bool trans_th_lrh(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_TESW, false);
+}
+
+static bool trans_th_lrhu(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_TEUW, false);
+}
+
+static bool trans_th_lrb(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_SB, false);
+}
+
+static bool trans_th_lrbu(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_UB, false);
+}
+
+static bool trans_th_srd(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_store_idx(ctx, a, MO_TESQ, false);
+}
+
+static bool trans_th_srw(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_idx(ctx, a, MO_TESL, false);
+}
+
+static bool trans_th_srh(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_idx(ctx, a, MO_TESW, false);
+}
+
+static bool trans_th_srb(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_idx(ctx, a, MO_SB, false);
+}
+static bool trans_th_lurd(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_load_idx(ctx, a, MO_TESQ, true);
+}
+
+static bool trans_th_lurw(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_TESL, true);
+}
+
+static bool trans_th_lurwu(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_load_idx(ctx, a, MO_TEUL, true);
+}
+
+static bool trans_th_lurh(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_TESW, true);
+}
+
+static bool trans_th_lurhu(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_TEUW, true);
+}
+
+static bool trans_th_lurb(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_SB, true);
+}
+
+static bool trans_th_lurbu(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_load_idx(ctx, a, MO_UB, true);
+}
+
+static bool trans_th_surd(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ REQUIRE_64BIT(ctx);
+ return gen_store_idx(ctx, a, MO_TESQ, true);
+}
+
+static bool trans_th_surw(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_idx(ctx, a, MO_TESL, true);
+}
+
+static bool trans_th_surh(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_idx(ctx, a, MO_TESW, true);
+}
+
+static bool trans_th_surb(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADMEMIDX(ctx);
+ return gen_store_idx(ctx, a, MO_SB, true);
+}
+
/* XTheadMemPair */
static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 27bab07994..2461bcda0f 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -133,7 +133,8 @@ static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
ctx->cfg_ptr->ext_xtheadbs || ctx->cfg_ptr->ext_xtheadcmo ||
ctx->cfg_ptr->ext_xtheadcondmov || ctx->cfg_ptr->ext_xtheadmac ||
- ctx->cfg_ptr->ext_xtheadmempair || ctx->cfg_ptr->ext_xtheadsync;
+ ctx->cfg_ptr->ext_xtheadmemidx || ctx->cfg_ptr->ext_xtheadmempair ||
+ ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
@@ -595,6 +596,24 @@ static TCGv get_address(DisasContext *ctx, int rs1, int imm)
return addr;
}
+/* Compute a canonical address from a register plus reg offset. */
+static TCGv get_address_indexed(DisasContext *ctx, int rs1, TCGv offs)
+{
+ TCGv addr = temp_new(ctx);
+ TCGv src1 = get_gpr(ctx, rs1, EXT_NONE);
+
+ tcg_gen_add_tl(addr, src1, offs);
+ if (ctx->pm_mask_enabled) {
+ tcg_gen_andc_tl(addr, addr, pm_mask);
+ } else if (get_xl(ctx) == MXL_RV32) {
+ tcg_gen_ext32u_tl(addr, addr);
+ }
+ if (ctx->pm_base_enabled) {
+ tcg_gen_or_tl(addr, addr, pm_base);
+ }
+ return addr;
+}
+
#ifndef CONFIG_USER_ONLY
/* The states of mstatus_fs are:
* 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index ff2a83b56d..69e40f22dc 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -17,8 +17,10 @@
%rd2 20:5
%rs2 20:5
%sh5 20:5
+%imm5 20:s5
%sh6 20:6
%sh2 25:2
+%imm2 25:2
# Argument sets
&r rd rs1 rs2 !extern
@@ -26,6 +28,8 @@
&shift shamt rs1 rd !extern
&th_bfext msb lsb rs1 rd
&th_pair rd1 rs rd2 sh2
+&th_memidx rd rs1 rs2 imm2
+&th_meminc rd rs1 imm5 imm2
# Formats
@sfence_vm ....... ..... ..... ... ..... ....... %rs1
@@ -36,6 +40,8 @@
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
@sh6 ...... ...... ..... ... ..... ....... &shift shamt=%sh6 %rs1 %rd
@th_pair ..... .. ..... ..... ... ..... ....... &th_pair %rd1 %rs %rd2 %sh2
+@th_memidx ..... .. ..... ..... ... ..... ....... &th_memidx %rd %rs1 %rs2 %imm2
+@th_meminc ..... .. ..... ..... ... ..... ....... &th_meminc %rd %rs1 %imm5 %imm2
# XTheadBa
# Instead of defining a new encoding, we simply use the decoder to
@@ -102,6 +108,54 @@ th_muls 00100 01 ..... ..... 001 ..... 0001011 @r
th_mulsh 00101 01 ..... ..... 001 ..... 0001011 @r
th_mulsw 00100 11 ..... ..... 001 ..... 0001011 @r
+# XTheadMemIdx
+th_ldia 01111 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_ldib 01101 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lwia 01011 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lwib 01001 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lwuia 11011 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lwuib 11001 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lhia 00111 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lhib 00101 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lhuia 10111 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lhuib 10101 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lbia 00011 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lbib 00001 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lbuia 10011 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_lbuib 10001 .. ..... ..... 100 ..... 0001011 @th_meminc
+th_sdia 01111 .. ..... ..... 101 ..... 0001011 @th_meminc
+th_sdib 01101 .. ..... ..... 101 ..... 0001011 @th_meminc
+th_swia 01011 .. ..... ..... 101 ..... 0001011 @th_meminc
+th_swib 01001 .. ..... ..... 101 ..... 0001011 @th_meminc
+th_shia 00111 .. ..... ..... 101 ..... 0001011 @th_meminc
+th_shib 00101 .. ..... ..... 101 ..... 0001011 @th_meminc
+th_sbia 00011 .. ..... ..... 101 ..... 0001011 @th_meminc
+th_sbib 00001 .. ..... ..... 101 ..... 0001011 @th_meminc
+
+th_lrd 01100 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lrw 01000 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lrwu 11000 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lrh 00100 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lrhu 10100 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lrb 00000 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lrbu 10000 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_srd 01100 .. ..... ..... 101 ..... 0001011 @th_memidx
+th_srw 01000 .. ..... ..... 101 ..... 0001011 @th_memidx
+th_srh 00100 .. ..... ..... 101 ..... 0001011 @th_memidx
+th_srb 00000 .. ..... ..... 101 ..... 0001011 @th_memidx
+
+th_lurd 01110 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lurw 01010 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lurwu 11010 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lurh 00110 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lurhu 10110 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lurb 00010 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_lurbu 10010 .. ..... ..... 100 ..... 0001011 @th_memidx
+th_surd 01110 .. ..... ..... 101 ..... 0001011 @th_memidx
+th_surw 01010 .. ..... ..... 101 ..... 0001011 @th_memidx
+th_surh 00110 .. ..... ..... 101 ..... 0001011 @th_memidx
+th_surb 00010 .. ..... ..... 101 ..... 0001011 @th_memidx
+
# XTheadMemPair
th_ldd 11111 .. ..... ..... 100 ..... 0001011 @th_pair
th_lwd 11100 .. ..... ..... 100 ..... 0001011 @th_pair
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v3 09/14] RISC-V: Adding T-Head MemIdx extension
2023-01-24 19:59 ` [PATCH v3 09/14] RISC-V: Adding T-Head MemIdx extension Christoph Muellner
@ 2023-01-24 21:21 ` Richard Henderson
2023-01-30 9:04 ` LIU Zhiwei
2023-01-31 18:01 ` Christoph Müllner
0 siblings, 2 replies; 30+ messages in thread
From: Richard Henderson @ 2023-01-24 21:21 UTC (permalink / raw)
To: Christoph Muellner, qemu-riscv, qemu-devel, Alistair Francis,
Bin Meng, Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia, Yunhai Shang,
Zhiwei Liu
On 1/24/23 09:59, Christoph Muellner wrote:
> +/* XTheadMemIdx */
> +
> +/*
> + * Load with memop from indexed address and add (imm5 << imm2) to rs1.
> + * If !preinc, then the load address is rs1.
> + * If preinc, then the load address is rs1 + (imm5) << imm2).
> + */
> +static bool gen_load_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop,
> + bool preinc)
> +{
> + TCGv rd = dest_gpr(ctx, a->rd);
> + TCGv addr = get_address(ctx, a->rs1, preinc ? a->imm5 << a->imm2 : 0);
> +
> + tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
> + addr = get_address(ctx, a->rs1, !preinc ? a->imm5 << a->imm2 : 0);
First, you're leaking the previous 'addr' temporary.
Second, get_address may make modifications to 'addr' which you don't want to write back.
Third, you are not checking for rd != rs1.
I think what you want is
int imm = a->imm5 << a->imm2;
TCGv addr = get_address(ctx, a->rs1, preinc ? imm : 0);
TCGv rd = dest_gpr(ctx, a->rd);
TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE);
tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
tcg_gen_addi_tl(rs1, rs1, imm);
gen_set_gpr(ctx, a->rd, rd);
gen_set_gpr(ctx, a->rs1, rs1);
r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 09/14] RISC-V: Adding T-Head MemIdx extension
2023-01-24 21:21 ` Richard Henderson
@ 2023-01-30 9:04 ` LIU Zhiwei
2023-01-31 18:01 ` Christoph Müllner
1 sibling, 0 replies; 30+ messages in thread
From: LIU Zhiwei @ 2023-01-30 9:04 UTC (permalink / raw)
To: Richard Henderson, Christoph Muellner, qemu-riscv, qemu-devel,
Alistair Francis, Bin Meng, Philipp Tomsich, Heiko Stübner,
Palmer Dabbelt, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang
On 2023/1/25 5:21, Richard Henderson wrote:
> On 1/24/23 09:59, Christoph Muellner wrote:
>> +/* XTheadMemIdx */
>> +
>> +/*
>> + * Load with memop from indexed address and add (imm5 << imm2) to rs1.
>> + * If !preinc, then the load address is rs1.
>> + * If preinc, then the load address is rs1 + (imm5) << imm2).
>> + */
>> +static bool gen_load_inc(DisasContext *ctx, arg_th_meminc *a, MemOp
>> memop,
>> + bool preinc)
>> +{
>> + TCGv rd = dest_gpr(ctx, a->rd);
>> + TCGv addr = get_address(ctx, a->rs1, preinc ? a->imm5 << a->imm2
>> : 0);
>> +
>> + tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
>> + addr = get_address(ctx, a->rs1, !preinc ? a->imm5 << a->imm2 : 0);
>
> First, you're leaking the previous 'addr' temporary.
Although all temps allocated by temp_new() will be freed after the
instruction translation automatically, we can improve current
implementation.
> Second, get_address may make modifications to 'addr' which you don't
> want to write back.
Good catch.
> Third, you are not checking for rd != rs1.
Yes.
>
> I think what you want is
>
> int imm = a->imm5 << a->imm2;
> TCGv addr = get_address(ctx, a->rs1, preinc ? imm : 0);
> TCGv rd = dest_gpr(ctx, a->rd);
> TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE);
>
> tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
> tcg_gen_addi_tl(rs1, rs1, imm);
> gen_set_gpr(ctx, a->rd, rd);
> gen_set_gpr(ctx, a->rs1, rs1);
Yes, we should write back the 'addr' without modification.
Best Regards,
Zhiwei
>
>
> r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 09/14] RISC-V: Adding T-Head MemIdx extension
2023-01-24 21:21 ` Richard Henderson
2023-01-30 9:04 ` LIU Zhiwei
@ 2023-01-31 18:01 ` Christoph Müllner
1 sibling, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-01-31 18:01 UTC (permalink / raw)
To: Richard Henderson
Cc: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt, Nelson Chu,
Kito Cheng, Cooper Qu, Lifang Xia, Yunhai Shang, Zhiwei Liu
On Tue, Jan 24, 2023 at 10:21 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 1/24/23 09:59, Christoph Muellner wrote:
> > +/* XTheadMemIdx */
> > +
> > +/*
> > + * Load with memop from indexed address and add (imm5 << imm2) to rs1.
> > + * If !preinc, then the load address is rs1.
> > + * If preinc, then the load address is rs1 + (imm5) << imm2).
> > + */
> > +static bool gen_load_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop,
> > + bool preinc)
> > +{
> > + TCGv rd = dest_gpr(ctx, a->rd);
> > + TCGv addr = get_address(ctx, a->rs1, preinc ? a->imm5 << a->imm2 : 0);
> > +
> > + tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
> > + addr = get_address(ctx, a->rs1, !preinc ? a->imm5 << a->imm2 : 0);
>
> First, you're leaking the previous 'addr' temporary.
Indeed!
The real question is of course, why we call get_address() twice...
Fixed in v4.
> Second, get_address may make modifications to 'addr' which you don't want to write back.
Fixed in v4.
> Third, you are not checking for rd != rs1.
Fixed in v4.
>
> I think what you want is
>
> int imm = a->imm5 << a->imm2;
> TCGv addr = get_address(ctx, a->rs1, preinc ? imm : 0);
> TCGv rd = dest_gpr(ctx, a->rd);
> TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE);
>
> tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
> tcg_gen_addi_tl(rs1, rs1, imm);
> gen_set_gpr(ctx, a->rd, rd);
> gen_set_gpr(ctx, a->rs1, rs1);
Yes (plus the check for rd != rs1).
Fixed in v4.
Thank you!
>
>
> r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v3 10/14] RISC-V: Adding T-Head FMemIdx extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (8 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 09/14] RISC-V: Adding T-Head MemIdx extension Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 11/14] RISC-V: Set minimum priv version for Zfh to 1.11 Christoph Muellner
` (3 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the T-Head FMemIdx instructions.
The patch uses the T-Head specific decoder and translation.
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Use single decoder for XThead extensions
- Use get_th_address_indexed for address calculations
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 108 +++++++++++++++++++++
target/riscv/translate.c | 3 +-
target/riscv/xthead.decode | 10 ++
5 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb8bbfa436..6121a5e4ba 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -114,6 +114,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(xtheadbs, true, PRIV_VERSION_1_11_0, ext_xtheadbs),
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xtheadcondmov, true, PRIV_VERSION_1_11_0, ext_xtheadcondmov),
+ ISA_EXT_DATA_ENTRY(xtheadfmemidx, true, PRIV_VERSION_1_11_0, ext_xtheadfmemidx),
ISA_EXT_DATA_ENTRY(xtheadmac, true, PRIV_VERSION_1_11_0, ext_xtheadmac),
ISA_EXT_DATA_ENTRY(xtheadmemidx, true, PRIV_VERSION_1_11_0, ext_xtheadmemidx),
ISA_EXT_DATA_ENTRY(xtheadmempair, true, PRIV_VERSION_1_11_0, ext_xtheadmempair),
@@ -1085,6 +1086,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false),
DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false),
+ DEFINE_PROP_BOOL("xtheadfmemidx", RISCVCPU, cfg.ext_xtheadfmemidx, false),
DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false),
DEFINE_PROP_BOOL("xtheadmemidx", RISCVCPU, cfg.ext_xtheadmemidx, false),
DEFINE_PROP_BOOL("xtheadmempair", RISCVCPU, cfg.ext_xtheadmempair, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 4882b9a9cc..b0ec5fcf9e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -478,6 +478,7 @@ struct RISCVCPUConfig {
bool ext_xtheadbs;
bool ext_xtheadcmo;
bool ext_xtheadcondmov;
+ bool ext_xtheadfmemidx;
bool ext_xtheadmac;
bool ext_xtheadmemidx;
bool ext_xtheadmempair;
diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc
index e41f3be9a6..dc82a9fc03 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -46,6 +46,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADFMEMIDX(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadfmemidx) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADMAC(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadmac) { \
return false; \
@@ -341,6 +347,108 @@ static bool trans_th_mvnez(DisasContext *ctx, arg_th_mveqz *a)
return gen_th_condmove(ctx, a, TCG_COND_NE);
}
+/* XTheadFMem */
+
+/*
+ * Load 64-bit float from indexed address.
+ * If !zext_offs, then address is rs1 + (rs2 << imm2).
+ * If zext_offs, then address is rs1 + (zext(rs2[31:0]) << imm2).
+ */
+static bool gen_fload_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop,
+ bool zext_offs)
+{
+ TCGv_i64 rd = cpu_fpr[a->rd];
+ TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs);
+
+ tcg_gen_qemu_ld_i64(rd, addr, ctx->mem_idx, memop);
+ if ((memop & MO_SIZE) == MO_32) {
+ gen_nanbox_s(rd, rd);
+ }
+
+ mark_fs_dirty(ctx);
+ return true;
+}
+
+/*
+ * Store 64-bit float to indexed address.
+ * If !zext_offs, then address is rs1 + (rs2 << imm2).
+ * If zext_offs, then address is rs1 + (zext(rs2[31:0]) << imm2).
+ */
+static bool gen_fstore_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop,
+ bool zext_offs)
+{
+ TCGv_i64 rd = cpu_fpr[a->rd];
+ TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs);
+
+ tcg_gen_qemu_st_i64(rd, addr, ctx->mem_idx, memop);
+
+ return true;
+}
+
+static bool trans_th_flrd(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADFMEMIDX(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVD);
+ return gen_fload_idx(ctx, a, MO_TEUQ, false);
+}
+
+static bool trans_th_flrw(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADFMEMIDX(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVF);
+ return gen_fload_idx(ctx, a, MO_TEUL, false);
+}
+
+static bool trans_th_flurd(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADFMEMIDX(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVD);
+ return gen_fload_idx(ctx, a, MO_TEUQ, true);
+}
+
+static bool trans_th_flurw(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADFMEMIDX(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVF);
+ return gen_fload_idx(ctx, a, MO_TEUL, true);
+}
+
+static bool trans_th_fsrd(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADFMEMIDX(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVD);
+ return gen_fstore_idx(ctx, a, MO_TEUQ, false);
+}
+
+static bool trans_th_fsrw(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADFMEMIDX(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVF);
+ return gen_fstore_idx(ctx, a, MO_TEUL, false);
+}
+
+static bool trans_th_fsurd(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADFMEMIDX(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVD);
+ return gen_fstore_idx(ctx, a, MO_TEUQ, true);
+}
+
+static bool trans_th_fsurw(DisasContext *ctx, arg_th_memidx *a)
+{
+ REQUIRE_XTHEADFMEMIDX(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVF);
+ return gen_fstore_idx(ctx, a, MO_TEUL, true);
+}
+
/* XTheadMac */
static bool gen_th_mac(DisasContext *ctx, arg_r *a,
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 2461bcda0f..c52bc5e0af 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -132,7 +132,8 @@ static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
{
return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
ctx->cfg_ptr->ext_xtheadbs || ctx->cfg_ptr->ext_xtheadcmo ||
- ctx->cfg_ptr->ext_xtheadcondmov || ctx->cfg_ptr->ext_xtheadmac ||
+ ctx->cfg_ptr->ext_xtheadcondmov ||
+ ctx->cfg_ptr->ext_xtheadfmemidx || ctx->cfg_ptr->ext_xtheadmac ||
ctx->cfg_ptr->ext_xtheadmemidx || ctx->cfg_ptr->ext_xtheadmempair ||
ctx->cfg_ptr->ext_xtheadsync;
}
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index 69e40f22dc..81daf1d694 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -100,6 +100,16 @@ th_l2cache_iall 0000000 10110 00000 000 00000 0001011
th_mveqz 0100000 ..... ..... 001 ..... 0001011 @r
th_mvnez 0100001 ..... ..... 001 ..... 0001011 @r
+# XTheadFMemIdx
+th_flrd 01100 .. ..... ..... 110 ..... 0001011 @th_memidx
+th_flrw 01000 .. ..... ..... 110 ..... 0001011 @th_memidx
+th_flurd 01110 .. ..... ..... 110 ..... 0001011 @th_memidx
+th_flurw 01010 .. ..... ..... 110 ..... 0001011 @th_memidx
+th_fsrd 01100 .. ..... ..... 111 ..... 0001011 @th_memidx
+th_fsrw 01000 .. ..... ..... 111 ..... 0001011 @th_memidx
+th_fsurd 01110 .. ..... ..... 111 ..... 0001011 @th_memidx
+th_fsurw 01010 .. ..... ..... 111 ..... 0001011 @th_memidx
+
# XTheadMac
th_mula 00100 00 ..... ..... 001 ..... 0001011 @r
th_mulah 00101 00 ..... ..... 001 ..... 0001011 @r
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 11/14] RISC-V: Set minimum priv version for Zfh to 1.11
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (9 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 10/14] RISC-V: Adding T-Head FMemIdx extension Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 12/14] RISC-V: Add initial support for T-Head C906 Christoph Muellner
` (2 subsequent siblings)
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
There are no differences for floating point instructions in priv version 1.11
and 1.12. There is also no dependency for Zfh to priv version 1.12.
Therefore allow Zfh to be enabled for priv version 1.11.
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
target/riscv/cpu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6121a5e4ba..b18df9fa2a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -77,7 +77,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
ISA_EXT_DATA_ENTRY(zihintpause, true, PRIV_VERSION_1_10_0, ext_zihintpause),
ISA_EXT_DATA_ENTRY(zawrs, true, PRIV_VERSION_1_12_0, ext_zawrs),
- ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh),
+ ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_11_0, ext_zfh),
ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin),
ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx),
ISA_EXT_DATA_ENTRY(zdinx, true, PRIV_VERSION_1_12_0, ext_zdinx),
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 12/14] RISC-V: Add initial support for T-Head C906
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (10 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 11/14] RISC-V: Set minimum priv version for Zfh to 1.11 Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 21:26 ` Richard Henderson
2023-01-24 19:59 ` [PATCH v3 13/14] RISC-V: Adding XTheadFmv ISA extension Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 14/14] target/riscv: add a MAINTAINERS entry for XThead* extension support Christoph Muellner
13 siblings, 1 reply; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds the T-Head C906 to the list of known CPUs.
Selecting this CPUs will automatically enable the available
ISA extensions of the CPUs (incl. vendor extensions).
Co-developed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
Changes in v2:
- Drop C910 as it does not differ from C906
- Set priv version to 1.11 (new fmin/fmax behaviour)
Changes in v3:
- Removed setting dropped 'xtheadxmae' extension
target/riscv/cpu.c | 30 ++++++++++++++++++++++++++++++
target/riscv/cpu.h | 2 ++
target/riscv/cpu_vendorid.h | 6 ++++++
3 files changed, 38 insertions(+)
create mode 100644 target/riscv/cpu_vendorid.h
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b18df9fa2a..627512a184 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -279,6 +279,35 @@ static void rv64_sifive_e_cpu_init(Object *obj)
cpu->cfg.mmu = false;
}
+static void rv64_thead_c906_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ RISCVCPU *cpu = RISCV_CPU(obj);
+
+ set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ set_priv_version(env, PRIV_VERSION_1_11_0);
+
+ cpu->cfg.ext_g = true;
+ cpu->cfg.ext_c = true;
+ cpu->cfg.ext_u = true;
+ cpu->cfg.ext_s = true;
+ cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_zfh = true;
+ cpu->cfg.mmu = true;
+ cpu->cfg.ext_xtheadba = true;
+ cpu->cfg.ext_xtheadbb = true;
+ cpu->cfg.ext_xtheadbs = true;
+ cpu->cfg.ext_xtheadcmo = true;
+ cpu->cfg.ext_xtheadcondmov = true;
+ cpu->cfg.ext_xtheadfmemidx = true;
+ cpu->cfg.ext_xtheadmac = true;
+ cpu->cfg.ext_xtheadmemidx = true;
+ cpu->cfg.ext_xtheadmempair = true;
+ cpu->cfg.ext_xtheadsync = true;
+
+ cpu->cfg.mvendorid = THEAD_VENDOR_ID;
+}
+
static void rv128_base_cpu_init(Object *obj)
{
if (qemu_tcg_mttcg_enabled()) {
@@ -1320,6 +1349,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_THEAD_C906, rv64_thead_c906_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init),
#endif
};
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index b0ec5fcf9e..134dc29c6e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -27,6 +27,7 @@
#include "qom/object.h"
#include "qemu/int128.h"
#include "cpu_bits.h"
+#include "cpu_vendorid.h"
#define TCG_GUEST_DEFAULT_MO 0
@@ -53,6 +54,7 @@
#define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
#define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34")
#define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54")
+#define TYPE_RISCV_CPU_THEAD_C906 RISCV_CPU_TYPE_NAME("thead-c906")
#define TYPE_RISCV_CPU_HOST RISCV_CPU_TYPE_NAME("host")
#if defined(TARGET_RISCV32)
diff --git a/target/riscv/cpu_vendorid.h b/target/riscv/cpu_vendorid.h
new file mode 100644
index 0000000000..a5aa249bc9
--- /dev/null
+++ b/target/riscv/cpu_vendorid.h
@@ -0,0 +1,6 @@
+#ifndef TARGET_RISCV_CPU_VENDORID_H
+#define TARGET_RISCV_CPU_VENDORID_H
+
+#define THEAD_VENDOR_ID 0x5b7
+
+#endif /* TARGET_RISCV_CPU_VENDORID_H */
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v3 12/14] RISC-V: Add initial support for T-Head C906
2023-01-24 19:59 ` [PATCH v3 12/14] RISC-V: Add initial support for T-Head C906 Christoph Muellner
@ 2023-01-24 21:26 ` Richard Henderson
2023-01-30 9:06 ` LIU Zhiwei
2023-01-31 18:01 ` Christoph Müllner
0 siblings, 2 replies; 30+ messages in thread
From: Richard Henderson @ 2023-01-24 21:26 UTC (permalink / raw)
To: Christoph Muellner, qemu-riscv, qemu-devel, Alistair Francis,
Bin Meng, Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia, Yunhai Shang,
Zhiwei Liu
On 1/24/23 09:59, Christoph Muellner wrote:
> +++ b/target/riscv/cpu.h
> @@ -27,6 +27,7 @@
> #include "qom/object.h"
> #include "qemu/int128.h"
> #include "cpu_bits.h"
> +#include "cpu_vendorid.h"
I don't see that this ID is required for all users of riscv/cpu.h.
This include should be limited to cpu.c.
r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 12/14] RISC-V: Add initial support for T-Head C906
2023-01-24 21:26 ` Richard Henderson
@ 2023-01-30 9:06 ` LIU Zhiwei
2023-01-31 18:01 ` Christoph Müllner
1 sibling, 0 replies; 30+ messages in thread
From: LIU Zhiwei @ 2023-01-30 9:06 UTC (permalink / raw)
To: Richard Henderson, Christoph Muellner, qemu-riscv, qemu-devel,
Alistair Francis, Bin Meng, Philipp Tomsich, Heiko Stübner,
Palmer Dabbelt, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang
On 2023/1/25 5:26, Richard Henderson wrote:
> On 1/24/23 09:59, Christoph Muellner wrote:
>> +++ b/target/riscv/cpu.h
>> @@ -27,6 +27,7 @@
>> #include "qom/object.h"
>> #include "qemu/int128.h"
>> #include "cpu_bits.h"
>> +#include "cpu_vendorid.h"
>
> I don't see that this ID is required for all users of riscv/cpu.h.
> This include should be limited to cpu.c.
>
OK. We can move it to cpu.c
Best Regards,
Zhiwei
>
> r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 12/14] RISC-V: Add initial support for T-Head C906
2023-01-24 21:26 ` Richard Henderson
2023-01-30 9:06 ` LIU Zhiwei
@ 2023-01-31 18:01 ` Christoph Müllner
1 sibling, 0 replies; 30+ messages in thread
From: Christoph Müllner @ 2023-01-31 18:01 UTC (permalink / raw)
To: Richard Henderson
Cc: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt, Nelson Chu,
Kito Cheng, Cooper Qu, Lifang Xia, Yunhai Shang, Zhiwei Liu
On Tue, Jan 24, 2023 at 10:26 PM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 1/24/23 09:59, Christoph Muellner wrote:
> > +++ b/target/riscv/cpu.h
> > @@ -27,6 +27,7 @@
> > #include "qom/object.h"
> > #include "qemu/int128.h"
> > #include "cpu_bits.h"
> > +#include "cpu_vendorid.h"
>
> I don't see that this ID is required for all users of riscv/cpu.h.
> This include should be limited to cpu.c.
Fixed in v4.
Thank you!
>
>
> r~
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v3 13/14] RISC-V: Adding XTheadFmv ISA extension
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (11 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 12/14] RISC-V: Add initial support for T-Head C906 Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
2023-01-24 19:59 ` [PATCH v3 14/14] target/riscv: add a MAINTAINERS entry for XThead* extension support Christoph Muellner
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
This patch adds support for the XTheadFmv ISA extension.
The patch uses the T-Head specific decoder and translation.
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 45 ++++++++++++++++++++++
target/riscv/translate.c | 6 +--
target/riscv/xthead.decode | 4 ++
5 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 627512a184..1878c17a59 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -115,6 +115,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
ISA_EXT_DATA_ENTRY(xtheadcondmov, true, PRIV_VERSION_1_11_0, ext_xtheadcondmov),
ISA_EXT_DATA_ENTRY(xtheadfmemidx, true, PRIV_VERSION_1_11_0, ext_xtheadfmemidx),
+ ISA_EXT_DATA_ENTRY(xtheadfmv, true, PRIV_VERSION_1_11_0, ext_xtheadfmv),
ISA_EXT_DATA_ENTRY(xtheadmac, true, PRIV_VERSION_1_11_0, ext_xtheadmac),
ISA_EXT_DATA_ENTRY(xtheadmemidx, true, PRIV_VERSION_1_11_0, ext_xtheadmemidx),
ISA_EXT_DATA_ENTRY(xtheadmempair, true, PRIV_VERSION_1_11_0, ext_xtheadmempair),
@@ -1116,6 +1117,7 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false),
DEFINE_PROP_BOOL("xtheadfmemidx", RISCVCPU, cfg.ext_xtheadfmemidx, false),
+ DEFINE_PROP_BOOL("xtheadfmv", RISCVCPU, cfg.ext_xtheadfmv, false),
DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false),
DEFINE_PROP_BOOL("xtheadmemidx", RISCVCPU, cfg.ext_xtheadmemidx, false),
DEFINE_PROP_BOOL("xtheadmempair", RISCVCPU, cfg.ext_xtheadmempair, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 134dc29c6e..04630f3b79 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -481,6 +481,7 @@ struct RISCVCPUConfig {
bool ext_xtheadcmo;
bool ext_xtheadcondmov;
bool ext_xtheadfmemidx;
+ bool ext_xtheadfmv;
bool ext_xtheadmac;
bool ext_xtheadmemidx;
bool ext_xtheadmempair;
diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc
index dc82a9fc03..0403e90d7a 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -52,6 +52,12 @@
} \
} while (0)
+#define REQUIRE_XTHEADFMV(ctx) do { \
+ if (!ctx->cfg_ptr->ext_xtheadfmv) { \
+ return false; \
+ } \
+} while (0)
+
#define REQUIRE_XTHEADMAC(ctx) do { \
if (!ctx->cfg_ptr->ext_xtheadmac) { \
return false; \
@@ -449,6 +455,45 @@ static bool trans_th_fsurw(DisasContext *ctx, arg_th_memidx *a)
return gen_fstore_idx(ctx, a, MO_TEUL, true);
}
+/* XTheadFmv */
+
+static bool trans_th_fmv_hw_x(DisasContext *ctx, arg_th_fmv_hw_x *a)
+{
+ REQUIRE_XTHEADFMV(ctx);
+ REQUIRE_32BIT(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVD);
+
+ TCGv src1 = get_gpr(ctx, a->rs1, EXT_ZERO);
+ TCGv_i64 t1 = tcg_temp_new_i64();
+
+ tcg_gen_extu_tl_i64(t1, src1);
+ tcg_gen_deposit_i64(cpu_fpr[a->rd], cpu_fpr[a->rd], t1, 32, 32);
+ tcg_temp_free_i64(t1);
+ mark_fs_dirty(ctx);
+ return true;
+}
+
+static bool trans_th_fmv_x_hw(DisasContext *ctx, arg_th_fmv_x_hw *a)
+{
+ REQUIRE_XTHEADFMV(ctx);
+ REQUIRE_32BIT(ctx);
+ REQUIRE_FPU;
+ REQUIRE_EXT(ctx, RVD);
+ TCGv dst;
+ TCGv_i64 t1;
+
+ dst = dest_gpr(ctx, a->rd);
+ t1 = tcg_temp_new_i64();
+
+ tcg_gen_extract_i64(t1, cpu_fpr[a->rs1], 32, 32);
+ tcg_gen_trunc_i64_tl(dst, t1);
+ gen_set_gpr(ctx, a->rd, dst);
+ tcg_temp_free_i64(t1);
+ mark_fs_dirty(ctx);
+ return true;
+}
+
/* XTheadMac */
static bool gen_th_mac(DisasContext *ctx, arg_r *a,
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index c52bc5e0af..d6163daeb2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -133,9 +133,9 @@ static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
ctx->cfg_ptr->ext_xtheadbs || ctx->cfg_ptr->ext_xtheadcmo ||
ctx->cfg_ptr->ext_xtheadcondmov ||
- ctx->cfg_ptr->ext_xtheadfmemidx || ctx->cfg_ptr->ext_xtheadmac ||
- ctx->cfg_ptr->ext_xtheadmemidx || ctx->cfg_ptr->ext_xtheadmempair ||
- ctx->cfg_ptr->ext_xtheadsync;
+ ctx->cfg_ptr->ext_xtheadfmemidx || ctx->cfg_ptr->ext_xtheadfmv ||
+ ctx->cfg_ptr->ext_xtheadmac || ctx->cfg_ptr->ext_xtheadmemidx ||
+ ctx->cfg_ptr->ext_xtheadmempair || ctx->cfg_ptr->ext_xtheadsync;
}
#define MATERIALISE_EXT_PREDICATE(ext) \
diff --git a/target/riscv/xthead.decode b/target/riscv/xthead.decode
index 81daf1d694..d1d104bcf2 100644
--- a/target/riscv/xthead.decode
+++ b/target/riscv/xthead.decode
@@ -110,6 +110,10 @@ th_fsrw 01000 .. ..... ..... 111 ..... 0001011 @th_memidx
th_fsurd 01110 .. ..... ..... 111 ..... 0001011 @th_memidx
th_fsurw 01010 .. ..... ..... 111 ..... 0001011 @th_memidx
+# XTheadFmv
+th_fmv_hw_x 1010000 00000 ..... 001 ..... 0001011 @r2
+th_fmv_x_hw 1100000 00000 ..... 001 ..... 0001011 @r2
+
# XTheadMac
th_mula 00100 00 ..... ..... 001 ..... 0001011 @r
th_mulah 00101 00 ..... ..... 001 ..... 0001011 @r
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 14/14] target/riscv: add a MAINTAINERS entry for XThead* extension support
2023-01-24 19:59 [PATCH v3 00/14] Add support for the T-Head vendor extensions Christoph Muellner
` (12 preceding siblings ...)
2023-01-24 19:59 ` [PATCH v3 13/14] RISC-V: Adding XTheadFmv ISA extension Christoph Muellner
@ 2023-01-24 19:59 ` Christoph Muellner
13 siblings, 0 replies; 30+ messages in thread
From: Christoph Muellner @ 2023-01-24 19:59 UTC (permalink / raw)
To: qemu-riscv, qemu-devel, Alistair Francis, Bin Meng,
Philipp Tomsich, Heiko Stübner, Palmer Dabbelt,
Richard Henderson, Nelson Chu, Kito Cheng, Cooper Qu, Lifang Xia,
Yunhai Shang, Zhiwei Liu
Cc: Christoph Müllner
From: Christoph Müllner <christoph.muellner@vrull.eu>
The XThead* extensions are maintained by T-Head and VRULL.
Adding a point of contact from both companies.
Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6982be48c6..f16916fd07 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -295,6 +295,14 @@ F: include/hw/riscv/
F: linux-user/host/riscv32/
F: linux-user/host/riscv64/
+RISC-V XThead* extensions
+M: Christoph Muellner <christoph.muellner@vrull.eu>
+M: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
+L: qemu-riscv@nongnu.org
+S: Supported
+F: target/riscv/insn_trans/trans_xthead.c.inc
+F: target/riscv/xthead*.decode
+
RISC-V XVentanaCondOps extension
M: Philipp Tomsich <philipp.tomsich@vrull.eu>
L: qemu-riscv@nongnu.org
--
2.39.0
^ permalink raw reply related [flat|nested] 30+ messages in thread