target/riscv/cpu.c | 5 ++--
target/riscv/cpu.h | 8 +++++++
target/riscv/cpu_bits.h | 2 ++
target/riscv/machine.c | 19 +++++++++++++++
target/riscv/tcg/csr.c | 39 +++++++++++++++++++++++++++++--
target/riscv/tcg/tcg-cpu.c | 48 ++++++++++++++++++++++++++++++++++++++
6 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5a82e6563bf..c9e6c83a491 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -46,7 +46,7 @@
/* RISC-V CPU definitions */
static const char riscv_single_letter_exts[] = "IEMAFDQCBPVH";
const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
- RVC, RVS, RVU, RVH, RVG, RVB, 0};
+ RVC, RVS, RVU, RVH, RVG, RVB, RVP, 0};
#define RISCV_CPU_MVENDORID 0
#define RISCV_CPU_MIMPID 0
/*
@@ -1489,7 +1489,8 @@ static const MISAExtInfo misa_ext_info_arr[] = {
MISA_EXT_INFO(RVH, "h", "Hypervisor"),
MISA_EXT_INFO(RVV, "v", "Vector operations"),
MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
- MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
+ MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)"),
+ MISA_EXT_INFO(RVP, "x-p", "Packed-SIMD instructions")
};
static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c9dfa7daff2..75cfb16d846 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -70,6 +70,7 @@ typedef struct CPUArchState CPURISCVState;
#define RVG RV('G')
#define RVB RV('B')
#define RVX RV('X')
+#define RVP RV('P')
extern const uint32_t misa_bits[];
const char *riscv_get_misa_ext_name(uint32_t bit);
@@ -742,6 +743,13 @@ FIELD(TB_FLAGS, PM_SIGNEXTEND, 31, 1)
FIELD(EXT_TB_FLAGS, MISA_EXT, 0, 32)
FIELD(EXT_TB_FLAGS, ALTFMT, 32, 1)
FIELD(EXT_TB_FLAGS, BIG_ENDIAN, 33, 1)
+FIELD(EXT_TB_FLAGS, P_VXSAT_EXCP, 34, 2)
+
+enum {
+ P_VXSAT_EXCP_NONE,
+ P_VXSAT_EXCP_ILLEGAL,
+ P_VXSAT_EXCP_VIRTUAL,
+};
#ifdef TARGET_RISCV32
#define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 3f146a43fe4..fa7bf60f4fc 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -355,6 +355,8 @@
#define SMSTATEEN0_CS (1ULL << 0)
#define SMSTATEEN0_FCSR (1ULL << 1)
#define SMSTATEEN0_JVT (1ULL << 2)
+/* Packed-SIMD draft: enable access to vxsat when misa.V = 0. */
+#define SMSTATEEN0_VXSAT (1ULL << 3)
#define SMSTATEEN0_CTR (1ULL << 54)
#define SMSTATEEN0_P1P13 (1ULL << 56)
#define SMSTATEEN0_HSCONTXT (1ULL << 57)
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 0ab613a2980..a9cd7e4c1cc 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -158,6 +158,24 @@ static const VMStateDescription vmstate_vector = {
}
};
+static bool p_vxsat_needed(void *opaque)
+{
+ RISCVCPU *cpu = opaque;
+
+ return riscv_has_ext(&cpu->env, RVP) && !cpu->cfg.ext_zve32x;
+}
+
+static const VMStateDescription vmstate_p_vxsat = {
+ .name = "cpu/p-vxsat",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = p_vxsat_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT8(env.vxsat, RISCVCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool pointermasking_needed(void *opaque)
{
return false;
@@ -518,6 +536,7 @@ const VMStateDescription vmstate_riscv_cpu = {
&vmstate_pmp,
&vmstate_hyper,
&vmstate_vector,
+ &vmstate_p_vxsat,
&vmstate_pointermasking,
&vmstate_rv128,
#ifdef CONFIG_KVM
diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index 36f2004bc56..e809997f52e 100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -109,6 +109,24 @@ static RISCVException vs(CPURISCVState *env, int csrno)
return RISCV_EXCP_ILLEGAL_INST;
}
+/* vxsat is also architectural state when P is implemented without Zve*. */
+static RISCVException vxsat(CPURISCVState *env, int csrno)
+{
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
+ return vs(env, csrno);
+ }
+
+ if (riscv_has_ext(env, RVP)) {
+#if !defined(CONFIG_USER_ONLY)
+ return smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
+#else
+ return RISCV_EXCP_NONE;
+#endif
+ }
+
+ return RISCV_EXCP_ILLEGAL_INST;
+}
+
static RISCVException ctr(CPURISCVState *env, int csrno)
{
#if !defined(CONFIG_USER_ONLY)
@@ -1013,7 +1031,12 @@ static RISCVException write_vxsat(CPURISCVState *env,
int csrno,
target_ulong val, uintptr_t ra)
{
#if !defined(CONFIG_USER_ONLY)
- env->mstatus |= MSTATUS_VS;
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
+ env->mstatus |= MSTATUS_VS;
+ if (env->virt_enabled) {
+ env->mstatus_hs |= MSTATUS_VS;
+ }
+ }
#endif
env->vxsat = val & BIT(0);
return RISCV_EXCP_NONE;
@@ -3494,6 +3517,10 @@ static RISCVException write_mstateen0(CPURISCVState
*env, int csrno,
target_ulong new_val, uintptr_t ra)
{
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
+
+ if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
+ wr_mask |= SMSTATEEN0_VXSAT;
+ }
if (!riscv_has_ext(env, RVF)) {
wr_mask |= SMSTATEEN0_FCSR;
}
@@ -3617,6 +3644,10 @@ static RISCVException write_hstateen0(CPURISCVState
*env, int csrno,
{
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
+ if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
+ wr_mask |= SMSTATEEN0_VXSAT;
+ }
+
if (!riscv_has_ext(env, RVF)) {
wr_mask |= SMSTATEEN0_FCSR;
}
@@ -3746,6 +3777,10 @@ static RISCVException write_sstateen0(CPURISCVState
*env, int csrno,
{
uint64_t wr_mask = 0;
+ if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
+ wr_mask |= SMSTATEEN0_VXSAT;
+ }
+
if (!riscv_has_ext(env, RVF)) {
wr_mask |= SMSTATEEN0_FCSR;
}
@@ -5916,7 +5951,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr },
/* Vector CSRs */
[CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart },
- [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat },
+ [CSR_VXSAT] = { "vxsat", vxsat, read_vxsat, write_vxsat },
[CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm },
[CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr },
[CSR_VL] = { "vl", vs, read_vl },
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 4af5cd9c731..1665583accf 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -160,6 +160,8 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
fs = EXT_STATUS_DIRTY;
vs = EXT_STATUS_DIRTY;
#else
+ RISCVException p_vxsat_excp;
+
flags = FIELD_DP32(flags, TB_FLAGS, PRIV, env->priv);
flags |= riscv_env_mmu_index(env, 0);
@@ -182,6 +184,23 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
}
+ /*
+ * Without Zve*, all P instructions in the OP-32 and OP-IMM-32
+ * spaces are controlled by stateen0.VXSAT. Preserve the exception
+ * class in the TB flags so translated code can distinguish an illegal
+ * instruction from a virtual-instruction exception.
+ */
+ p_vxsat_excp = smstateen_acc_ok(env, 0, SMSTATEEN0_VXSAT);
+ if (riscv_has_ext(env, RVP) && !riscv_cpu_cfg(env)->ext_zve32x) {
+ if (p_vxsat_excp == RISCV_EXCP_VIRT_INSTRUCTION_FAULT) {
+ ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
+ P_VXSAT_EXCP_VIRTUAL);
+ } else if (p_vxsat_excp != RISCV_EXCP_NONE) {
+ ext_flags = FIELD_DP64(ext_flags, EXT_TB_FLAGS, P_VXSAT_EXCP,
+ P_VXSAT_EXCP_ILLEGAL);
+ }
+ }
+
if (cpu->cfg.debug && !icount_enabled()) {
flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
}
@@ -530,6 +549,28 @@ static void riscv_cpu_validate_b(RISCVCPU *cpu)
}
}
+static void riscv_cpu_validate_p(RISCVCPU *cpu, Error **errp)
+{
+ CPURISCVState *env = &cpu->env;
+
+ if (!riscv_has_ext(env, RVP)) {
+ return;
+ }
+
+ if (riscv_cpu_mxl(env) != MXL_RV32 &&
+ riscv_cpu_mxl(env) != MXL_RV64) {
+ error_setg(errp, "P extension requires RV32 or RV64");
+ return;
+ }
+
+ if (!(cpu->cfg.ext_zmmul && cpu->cfg.ext_zba && cpu->cfg.ext_zbb &&
+ cpu->cfg.ext_zbkb)) {
+ error_setg(errp, "P extension requires zmmul, zba, zbb and zbkb "
+ "extensions");
+ return;
+ }
+}
+
/*
* Check consistency between chosen extensions while setting
* cpu->cfg accordingly.
@@ -612,6 +653,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu,
Error **errp)
return;
}
+ riscv_cpu_validate_p(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
@@ -1414,6 +1461,7 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
MISA_CFG(RVV, false),
MISA_CFG(RVG, false),
MISA_CFG(RVB, false),
+ MISA_CFG(RVP, false),
};
/*