aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-05-28 11:52:53 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-05-28 11:52:53 +0100
commit4bade28288b12a6268d2e1fc2e4fa1f77ccb1d89 (patch)
tree768cd3b7fa0540172f102a06be60a84d45c444ee /target
parent2b01c1b3821788417ac63392839eccb85feadc3f (diff)
parent1e0d985fa9136a563168a3da66f3d17820404ee2 (diff)
downloadqemu-4bade28288b12a6268d2e1fc2e4fa1f77ccb1d89.zip
qemu-4bade28288b12a6268d2e1fc2e4fa1f77ccb1d89.tar.gz
qemu-4bade28288b12a6268d2e1fc2e4fa1f77ccb1d89.tar.bz2
Merge remote-tracking branch 'remotes/palmer/tags/riscv-for-master-4.1-sf0' into staging
RISC-V Patches for the 4.1 Soft Freeze, Part 1 This tag contains a handful of patches that I'd like to target for 4.1: * An emulation for SiFive's GPIO device. * A fix to disallow sfence.vma from userspace. * Additional decodetree cleanups that should have no functional impact. * C extension emulation fidelity fixes that were noticed as part of that cleanup process. * A new "spike" target, along with the deprecation of a handful of old targets and CPUs. * Some initial infastructure related to the hypervisor extension. * An emulation fidelity fix that prevents prevents arbitrary bits in the SIP CSR from being set. * A small performance improvement that avoids excessive TLB flushing when the ASID does not change. This time I've used a new testing workflow: I've tested on both 32-bit and 64-bit builds of OpenEmbedded, via the default OpenSBI-based boot flow. # gpg: Signature made Sat 25 May 2019 01:05:57 BST # gpg: using RSA key 00CE76D1834960DFCE886DF8EF4CA1502CCBAB41 # gpg: issuer "palmer@dabbelt.com" # gpg: Good signature from "Palmer Dabbelt <palmer@dabbelt.com>" [unknown] # gpg: aka "Palmer Dabbelt <palmer@sifive.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 00CE 76D1 8349 60DF CE88 6DF8 EF4C A150 2CCB AB41 * remotes/palmer/tags/riscv-for-master-4.1-sf0: (29 commits) target/riscv: Only flush TLB if SATP.ASID changes target/riscv: More accurate handling of `sip` CSR target/riscv: Add checks for several RVC reserved operands target/riscv: Add the HGATP register masks target/riscv: Add the HSTATUS register masks target/riscv: Add Hypervisor CSR macros target/riscv: Allow setting mstatus virtulisation bits target/riscv: Add the MPV and MTL mstatus bits target/riscv: Improve the scause logic target/riscv: Trigger interrupt on MIP update asynchronously target/riscv: Mark privilege level 2 as reserved riscv: spike: Add a generic spike machine target/riscv: Deprecate the generic no MMU CPUs target/riscv: Add a base 32 and 64 bit CPU target/riscv: Create settable CPU properties riscv: virt: Allow specifying a CPU via commandline linux-user/riscv: Add the CPU type as a comment target/riscv: Remove unused include of riscv_htif.h for virt board riscv target/riscv: Remove spaces from register names target/riscv: Split gen_arith_imm into functional and temp ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/riscv/Makefile.objs15
-rw-r--r--target/riscv/cpu.c79
-rw-r--r--target/riscv/cpu.h10
-rw-r--r--target/riscv/cpu_bits.h45
-rw-r--r--target/riscv/cpu_helper.c35
-rw-r--r--target/riscv/csr.c30
-rw-r--r--target/riscv/insn16-32.decode28
-rw-r--r--target/riscv/insn16-64.decode36
-rw-r--r--target/riscv/insn16.decode173
-rw-r--r--target/riscv/insn32.decode10
-rw-r--r--target/riscv/insn_trans/trans_privileged.inc.c8
-rw-r--r--target/riscv/insn_trans/trans_rvc.inc.c347
-rw-r--r--target/riscv/insn_trans/trans_rvi.inc.c26
-rw-r--r--target/riscv/op_helper.c7
-rw-r--r--target/riscv/translate.c77
15 files changed, 421 insertions, 505 deletions
diff --git a/target/riscv/Makefile.objs b/target/riscv/Makefile.objs
index 9c6c109..b1c79bc 100644
--- a/target/riscv/Makefile.objs
+++ b/target/riscv/Makefile.objs
@@ -5,16 +5,19 @@ DECODETREE = $(SRC_PATH)/scripts/decodetree.py
decode32-y = $(SRC_PATH)/target/riscv/insn32.decode
decode32-$(TARGET_RISCV64) += $(SRC_PATH)/target/riscv/insn32-64.decode
+decode16-y = $(SRC_PATH)/target/riscv/insn16.decode
+decode16-$(TARGET_RISCV32) += $(SRC_PATH)/target/riscv/insn16-32.decode
+decode16-$(TARGET_RISCV64) += $(SRC_PATH)/target/riscv/insn16-64.decode
+
target/riscv/decode_insn32.inc.c: $(decode32-y) $(DECODETREE)
$(call quiet-command, \
- $(PYTHON) $(DECODETREE) -o $@ --decode decode_insn32 $(decode32-y), \
- "GEN", $(TARGET_DIR)$@)
+ $(PYTHON) $(DECODETREE) -o $@ --static-decode decode_insn32 \
+ $(decode32-y), "GEN", $(TARGET_DIR)$@)
-target/riscv/decode_insn16.inc.c: \
- $(SRC_PATH)/target/riscv/insn16.decode $(DECODETREE)
+target/riscv/decode_insn16.inc.c: $(decode16-y) $(DECODETREE)
$(call quiet-command, \
- $(PYTHON) $(DECODETREE) -o $@ --decode decode_insn16 --insnwidth 16 $<, \
- "GEN", $(TARGET_DIR)$@)
+ $(PYTHON) $(DECODETREE) -o $@ --static-decode decode_insn16 \
+ --insnwidth 16 $(decode16-y), "GEN", $(TARGET_DIR)$@)
target/riscv/translate.o: target/riscv/decode_insn32.inc.c \
target/riscv/decode_insn16.inc.c
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b767570..e298799 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -23,6 +23,7 @@
#include "cpu.h"
#include "exec/exec-all.h"
#include "qapi/error.h"
+#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
/* RISC-V CPU definitions */
@@ -30,17 +31,17 @@
static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
const char * const riscv_int_regnames[] = {
- "zero", "ra ", "sp ", "gp ", "tp ", "t0 ", "t1 ", "t2 ",
- "s0 ", "s1 ", "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ",
- "a6 ", "a7 ", "s2 ", "s3 ", "s4 ", "s5 ", "s6 ", "s7 ",
- "s8 ", "s9 ", "s10 ", "s11 ", "t3 ", "t4 ", "t5 ", "t6 "
+ "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
+ "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
+ "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
+ "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
};
const char * const riscv_fpr_regnames[] = {
- "ft0 ", "ft1 ", "ft2 ", "ft3 ", "ft4 ", "ft5 ", "ft6 ", "ft7 ",
- "fs0 ", "fs1 ", "fa0 ", "fa1 ", "fa2 ", "fa3 ", "fa4 ", "fa5 ",
- "fa6 ", "fa7 ", "fs2 ", "fs3 ", "fs4 ", "fs5 ", "fs6 ", "fs7 ",
- "fs8 ", "fs9 ", "fs10", "fs11", "ft8 ", "ft9 ", "ft10", "ft11"
+ "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
+ "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
+ "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
+ "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
};
const char * const riscv_excp_names[] = {
@@ -114,6 +115,12 @@ static void riscv_any_cpu_init(Object *obj)
#if defined(TARGET_RISCV32)
+static void riscv_base32_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+}
+
static void rv32gcsu_priv1_09_1_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
@@ -145,6 +152,12 @@ static void rv32imacu_nommu_cpu_init(Object *obj)
#elif defined(TARGET_RISCV64)
+static void riscv_base64_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+}
+
static void rv64gcsu_priv1_09_1_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
@@ -296,7 +309,11 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
+ RISCVCPU *cpu = RISCV_CPU(dev);
+ CPURISCVState *env = &cpu->env;
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
+ int priv_version = PRIV_VERSION_1_10_0;
+ int user_version = USER_VERSION_2_02_0;
Error *local_err = NULL;
cpu_exec_realizefn(cs, &local_err);
@@ -305,6 +322,41 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
return;
}
+ if (cpu->cfg.priv_spec) {
+ if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
+ priv_version = PRIV_VERSION_1_10_0;
+ } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.9.1")) {
+ priv_version = PRIV_VERSION_1_09_1;
+ } else {
+ error_setg(errp,
+ "Unsupported privilege spec version '%s'",
+ cpu->cfg.priv_spec);
+ return;
+ }
+ }
+
+ if (cpu->cfg.user_spec) {
+ if (!g_strcmp0(cpu->cfg.user_spec, "v2.02.0")) {
+ user_version = USER_VERSION_2_02_0;
+ } else {
+ error_setg(errp,
+ "Unsupported user spec version '%s'",
+ cpu->cfg.user_spec);
+ return;
+ }
+ }
+
+ set_versions(env, user_version, priv_version);
+ set_resetvec(env, DEFAULT_RSTVEC);
+
+ if (cpu->cfg.mmu) {
+ set_feature(env, RISCV_FEATURE_MMU);
+ }
+
+ if (cpu->cfg.pmp) {
+ set_feature(env, RISCV_FEATURE_PMP);
+ }
+
riscv_cpu_register_gdb_regs_for_features(cs);
qemu_init_vcpu(cs);
@@ -326,6 +378,14 @@ static const VMStateDescription vmstate_riscv_cpu = {
.unmigratable = 1,
};
+static Property riscv_cpu_properties[] = {
+ DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
+ DEFINE_PROP_STRING("user_spec", RISCVCPU, cfg.user_spec),
+ DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
+ DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void riscv_cpu_class_init(ObjectClass *c, void *data)
{
RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
@@ -365,6 +425,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
#endif
/* For now, mark unmigratable: */
cc->vmsd = &vmstate_riscv_cpu;
+ dc->props = riscv_cpu_properties;
}
char *riscv_isa_string(RISCVCPU *cpu)
@@ -430,12 +491,14 @@ static const TypeInfo riscv_cpu_type_infos[] = {
},
DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
#if defined(TARGET_RISCV32)
+ DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_09_1, rv32gcsu_priv1_09_1_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_RV32GCSU_V1_10_0, rv32gcsu_priv1_10_0_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init)
#elif defined(TARGET_RISCV64)
+ DEFINE_CPU(TYPE_RISCV_CPU_BASE64, riscv_base64_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_09_1, rv64gcsu_priv1_09_1_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_RV64GCSU_V1_10_0, rv64gcsu_priv1_10_0_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_RV64IMACU_NOMMU, rv64imacu_nommu_cpu_init),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c17184f..74e726c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -48,6 +48,8 @@
#define CPU_RESOLVING_TYPE TYPE_RISCV_CPU
#define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any")
+#define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
+#define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
#define TYPE_RISCV_CPU_RV32GCSU_V1_09_1 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.9.1")
#define TYPE_RISCV_CPU_RV32GCSU_V1_10_0 RISCV_CPU_TYPE_NAME("rv32gcsu-v1.10.0")
#define TYPE_RISCV_CPU_RV32IMACU_NOMMU RISCV_CPU_TYPE_NAME("rv32imacu-nommu")
@@ -224,6 +226,14 @@ typedef struct RISCVCPU {
CPUState parent_obj;
/*< public >*/
CPURISCVState env;
+
+ /* Configuration Settings */
+ struct {
+ char *priv_spec;
+ char *user_spec;
+ bool mmu;
+ bool pmp;
+ } cfg;
} RISCVCPU;
static inline RISCVCPU *riscv_env_get_cpu(CPURISCVState *env)
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 7180fcc..dc9d53d 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -202,6 +202,23 @@
#define CSR_DPC 0x7b1
#define CSR_DSCRATCH 0x7b2
+/* Hpervisor CSRs */
+#define CSR_HSTATUS 0xa00
+#define CSR_HEDELEG 0xa02
+#define CSR_HIDELEG 0xa03
+#define CSR_HGATP 0xa80
+
+#if defined(TARGET_RISCV32)
+#define HGATP_MODE SATP32_MODE
+#define HGATP_ASID SATP32_ASID
+#define HGATP_PPN SATP32_PPN
+#endif
+#if defined(TARGET_RISCV64)
+#define HGATP_MODE SATP64_MODE
+#define HGATP_ASID SATP64_ASID
+#define HGATP_PPN SATP64_PPN
+#endif
+
/* Performance Counters */
#define CSR_MHPMCOUNTER3 0xb03
#define CSR_MHPMCOUNTER4 0xb04
@@ -292,9 +309,6 @@
#define CSR_MHPMCOUNTER31H 0xb9f
/* Legacy Hypervisor Trap Setup (priv v1.9.1) */
-#define CSR_HSTATUS 0x200
-#define CSR_HEDELEG 0x202
-#define CSR_HIDELEG 0x203
#define CSR_HIE 0x204
#define CSR_HTVEC 0x205
@@ -316,14 +330,11 @@
/* mstatus CSR bits */
#define MSTATUS_UIE 0x00000001
#define MSTATUS_SIE 0x00000002
-#define MSTATUS_HIE 0x00000004
#define MSTATUS_MIE 0x00000008
#define MSTATUS_UPIE 0x00000010
#define MSTATUS_SPIE 0x00000020
-#define MSTATUS_HPIE 0x00000040
#define MSTATUS_MPIE 0x00000080
#define MSTATUS_SPP 0x00000100
-#define MSTATUS_HPP 0x00000600
#define MSTATUS_MPP 0x00001800
#define MSTATUS_FS 0x00006000
#define MSTATUS_XS 0x00018000
@@ -335,6 +346,8 @@
#define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */
#define MSTATUS_TW 0x20000000 /* since: priv-1.10 */
#define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */
+#define MSTATUS_MTL 0x4000000000ULL
+#define MSTATUS_MPV 0x8000000000ULL
#define MSTATUS64_UXL 0x0000000300000000ULL
#define MSTATUS64_SXL 0x0000000C00000000ULL
@@ -380,10 +393,28 @@
#define SSTATUS_SD SSTATUS64_SD
#endif
+/* hstatus CSR bits */
+#define HSTATUS_SPRV 0x00000001
+#define HSTATUS_STL 0x00000040
+#define HSTATUS_SPV 0x00000080
+#define HSTATUS_SP2P 0x00000100
+#define HSTATUS_SP2V 0x00000200
+#define HSTATUS_VTVM 0x00100000
+#define HSTATUS_VTSR 0x00400000
+
+#define HSTATUS32_WPRI 0xFF8FF87E
+#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL
+
+#if defined(TARGET_RISCV32)
+#define HSTATUS_WPRI HSTATUS32_WPRI
+#elif defined(TARGET_RISCV64)
+#define HSTATUS_WPRI HSTATUS64_WPRI
+#endif
+
/* Privilege modes */
#define PRV_U 0
#define PRV_S 1
-#define PRV_H 2
+#define PRV_H 2 /* Reserved */
#define PRV_M 3
/* RV32 satp CSR field masks */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 41d6db4..c577a26 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -82,10 +82,31 @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
}
}
-/* iothread_mutex must be held */
+struct CpuAsyncInfo {
+ uint32_t new_mip;
+};
+
+static void riscv_cpu_update_mip_irqs_async(CPUState *target_cpu_state,
+ run_on_cpu_data data)
+{
+ CPURISCVState *env = &RISCV_CPU(target_cpu_state)->env;
+ RISCVCPU *cpu = riscv_env_get_cpu(env);
+ struct CpuAsyncInfo *info = (struct CpuAsyncInfo *) data.host_ptr;
+
+ if (info->new_mip) {
+ cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+ }
+
+ g_free(info);
+}
+
uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
{
CPURISCVState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+ struct CpuAsyncInfo *info;
uint32_t old, new, cmp = atomic_read(&env->mip);
do {
@@ -94,11 +115,11 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
cmp = atomic_cmpxchg(&env->mip, old, new);
} while (old != cmp);
- if (new) {
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
- } else {
- cpu_reset_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
- }
+ info = g_new(struct CpuAsyncInfo, 1);
+ info->new_mip = new;
+
+ async_run_on_cpu(cs, riscv_cpu_update_mip_irqs_async,
+ RUN_ON_CPU_HOST_PTR(info));
return old;
}
@@ -494,7 +515,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
s = set_field(s, MSTATUS_SPP, env->priv);
s = set_field(s, MSTATUS_SIE, 0);
env->mstatus = s;
- env->scause = cause | ~(((target_ulong)-1) >> async);
+ env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
env->sepc = env->pc;
env->sbadaddr = tval;
env->pc = (env->stvec >> 2 << 2) +
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index e1d91b6..f9e2910 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -237,6 +237,7 @@ static const target_ulong sstatus_v1_9_mask = SSTATUS_SIE | SSTATUS_SPIE |
static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
+static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
#if defined(TARGET_RISCV32)
static const char valid_vm_1_09[16] = {
@@ -290,7 +291,6 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
{
target_ulong mstatus = env->mstatus;
target_ulong mask = 0;
- target_ulong mpp = get_field(val, MSTATUS_MPP);
/* flush tlb on mstatus fields that affect VM */
if (env->priv_ver <= PRIV_VERSION_1_09_1) {
@@ -305,7 +305,7 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
MSTATUS_VM : 0);
}
if (env->priv_ver >= PRIV_VERSION_1_10_0) {
- if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP |
+ if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
MSTATUS_MPRV | MSTATUS_SUM)) {
tlb_flush(CPU(riscv_env_get_cpu(env)));
}
@@ -313,13 +313,13 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
MSTATUS_TW;
- }
-
- /* silenty discard mstatus.mpp writes for unsupported modes */
- if (mpp == PRV_H ||
- (!riscv_has_ext(env, RVS) && mpp == PRV_S) ||
- (!riscv_has_ext(env, RVU) && mpp == PRV_U)) {
- mask &= ~MSTATUS_MPP;
+#if defined(TARGET_RISCV64)
+ /*
+ * RV32: MPV and MTL are not in mstatus. The current plan is to
+ * add them to mstatush. For now, we just don't support it.
+ */
+ mask |= MSTATUS_MPP | MSTATUS_MPV;
+#endif
}
mstatus = (mstatus & ~mask) | (val & mask);
@@ -555,9 +555,7 @@ static int rmw_mip(CPURISCVState *env, int csrno, target_ulong *ret_value,
uint32_t old_mip;
if (mask) {
- qemu_mutex_lock_iothread();
old_mip = riscv_cpu_update_mip(cpu, mask, (new_value & mask));
- qemu_mutex_unlock_iothread();
} else {
old_mip = atomic_read(&env->mip);
}
@@ -685,8 +683,10 @@ static int write_sbadaddr(CPURISCVState *env, int csrno, target_ulong val)
static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
{
- return rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
- write_mask & env->mideleg);
+ int ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
+ write_mask & env->mideleg & sip_writable_mask);
+ *ret_value &= env->mideleg;
+ return ret;
}
/* Supervisor Protection and Translation */
@@ -723,7 +723,9 @@ static int write_satp(CPURISCVState *env, int csrno, target_ulong val)
if (env->priv == PRV_S && get_field(env->mstatus, MSTATUS_TVM)) {
return -1;
} else {
- tlb_flush(CPU(riscv_env_get_cpu(env)));
+ if((val ^ env->satp) & SATP_ASID) {
+ tlb_flush(CPU(riscv_env_get_cpu(env)));
+ }
env->satp = val;
}
}
diff --git a/target/riscv/insn16-32.decode b/target/riscv/insn16-32.decode
new file mode 100644
index 0000000..0819b17
--- /dev/null
+++ b/target/riscv/insn16-32.decode
@@ -0,0 +1,28 @@
+#
+# RISC-V translation routines for the RVXI Base Integer Instruction Set.
+#
+# Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
+# Bastian Koppelmann, kbastian@mail.uni-paderborn.de
+#
+# 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/>.
+
+# *** RV32C Standard Extension (Quadrant 0) ***
+flw 011 ... ... .. ... 00 @cl_w
+fsw 111 ... ... .. ... 00 @cs_w
+
+# *** RV32C Standard Extension (Quadrant 1) ***
+jal 001 ........... 01 @cj rd=1 # C.JAL
+
+# *** RV32C Standard Extension (Quadrant 2) ***
+flw 011 . ..... ..... 10 @c_lwsp
+fsw 111 . ..... ..... 10 @c_swsp
diff --git a/target/riscv/insn16-64.decode b/target/riscv/insn16-64.decode
new file mode 100644
index 0000000..672e1e9
--- /dev/null
+++ b/target/riscv/insn16-64.decode
@@ -0,0 +1,36 @@
+#
+# RISC-V translation routines for the RVXI Base Integer Instruction Set.
+#
+# Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
+# Bastian Koppelmann, kbastian@mail.uni-paderborn.de
+#
+# 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/>.
+
+# *** RV64C Standard Extension (Quadrant 0) ***
+ld 011 ... ... .. ... 00 @cl_d
+sd 111 ... ... .. ... 00 @cs_d
+
+# *** RV64C Standard Extension (Quadrant 1) ***
+{
+ illegal 001 - 00000 ----- 01 # c.addiw, RES rd=0
+ addiw 001 . ..... ..... 01 @ci
+}
+subw 100 1 11 ... 00 ... 01 @cs_2
+addw 100 1 11 ... 01 ... 01 @cs_2
+
+# *** RV64C Standard Extension (Quadrant 2) ***
+{
+ illegal 011 - 00000 ----- 10 # c.ldsp, RES rd=0
+ ld 011 . ..... ..... 10 @c_ldsp
+}
+sd 111 . ..... ..... 10 @c_sdsp
diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index 17cc52c..1cb9387 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -30,7 +30,7 @@
%imm_cb 12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1
%imm_cj 12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1
-%nzuimm_6bit 12:1 2:5
+%shimm_6bit 12:1 2:5 !function=ex_rvc_shifti
%uimm_6bit_ld 2:3 12:1 5:2 !function=ex_shift_3
%uimm_6bit_lw 2:2 12:1 4:3 !function=ex_shift_2
%uimm_6bit_sd 7:3 10:3 !function=ex_shift_3
@@ -40,90 +40,93 @@
%imm_lui 12:s1 2:5 !function=ex_shift_12
+# Argument sets imported from insn32.decode:
+&empty !extern
+&r rd rs1 rs2 !extern
+&i imm rs1 rd !extern
+&s imm rs1 rs2 !extern
+&j imm rd !extern
+&b imm rs2 rs1 !extern
+&u imm rd !extern
+&shift shamt rs1 rd !extern
-# Argument sets:
-&cl rs1 rd
-&cl_dw uimm rs1 rd
-&ci imm rd
-&ciw nzuimm rd
-&cs rs1 rs2
-&cs_dw uimm rs1 rs2
-&cb imm rs1
-&cr rd rs2
-&cj imm
-&c_shift shamt rd
-
-&c_ld uimm rd
-&c_sd uimm rs2
-
-&caddi16sp_lui imm_lui imm_addi16sp rd
-&cflwsp_ldsp uimm_flwsp uimm_ldsp rd
-&cfswsp_sdsp uimm_fswsp uimm_sdsp rs2
# Formats 16:
-@cr .... ..... ..... .. &cr rs2=%rs2_5 %rd
-@ci ... . ..... ..... .. &ci imm=%imm_ci %rd
-@ciw ... ........ ... .. &ciw nzuimm=%nzuimm_ciw rd=%rs2_3
-@cl_d ... ... ... .. ... .. &cl_dw uimm=%uimm_cl_d rs1=%rs1_3 rd=%rs2_3
-@cl_w ... ... ... .. ... .. &cl_dw uimm=%uimm_cl_w rs1=%rs1_3 rd=%rs2_3
-@cl ... ... ... .. ... .. &cl rs1=%rs1_3 rd=%rs2_3
-@cs ... ... ... .. ... .. &cs rs1=%rs1_3 rs2=%rs2_3
-@cs_2 ... ... ... .. ... .. &cr rd=%rs1_3 rs2=%rs2_3
-@cs_d ... ... ... .. ... .. &cs_dw uimm=%uimm_cl_d rs1=%rs1_3 rs2=%rs2_3
-@cs_w ... ... ... .. ... .. &cs_dw uimm=%uimm_cl_w rs1=%rs1_3 rs2=%rs2_3
-@cb ... ... ... .. ... .. &cb imm=%imm_cb rs1=%rs1_3
-@cj ... ........... .. &cj imm=%imm_cj
-
-@c_ld ... . ..... ..... .. &c_ld uimm=%uimm_6bit_ld %rd
-@c_lw ... . ..... ..... .. &c_ld uimm=%uimm_6bit_lw %rd
-@c_sd ... . ..... ..... .. &c_sd uimm=%uimm_6bit_sd rs2=%rs2_5
-@c_sw ... . ..... ..... .. &c_sd uimm=%uimm_6bit_sw rs2=%rs2_5
-
-@c_addi16sp_lui ... . ..... ..... .. &caddi16sp_lui %imm_lui %imm_addi16sp %rd
-@c_flwsp_ldsp ... . ..... ..... .. &cflwsp_ldsp uimm_flwsp=%uimm_6bit_lw \
- uimm_ldsp=%uimm_6bit_ld %rd
-@c_fswsp_sdsp ... . ..... ..... .. &cfswsp_sdsp uimm_fswsp=%uimm_6bit_sw \
- uimm_sdsp=%uimm_6bit_sd rs2=%rs2_5
-
-@c_shift ... . .. ... ..... .. &c_shift rd=%rs1_3 shamt=%nzuimm_6bit
-@c_shift2 ... . .. ... ..... .. &c_shift rd=%rd shamt=%nzuimm_6bit
-
-@c_andi ... . .. ... ..... .. &ci imm=%imm_ci rd=%rs1_3
-
-# *** RV64C Standard Extension (Quadrant 0) ***
-c_addi4spn 000 ........ ... 00 @ciw
-c_fld 001 ... ... .. ... 00 @cl_d
-c_lw 010 ... ... .. ... 00 @cl_w
-c_flw_ld 011 --- ... -- ... 00 @cl #Note: Must parse uimm manually
-c_fsd 101 ... ... .. ... 00 @cs_d
-c_sw 110 ... ... .. ... 00 @cs_w
-c_fsw_sd 111 --- ... -- ... 00 @cs #Note: Must parse uimm manually
-
-# *** RV64C Standard Extension (Quadrant 1) ***
-c_addi 000 . ..... ..... 01 @ci
-c_jal_addiw 001 . ..... ..... 01 @ci #Note: parse rd and/or imm manually
-c_li 010 . ..... ..... 01 @ci
-c_addi16sp_lui 011 . ..... ..... 01 @c_addi16sp_lui # shares opc with C.LUI
-c_srli 100 . 00 ... ..... 01 @c_shift
-c_srai 100 . 01 ... ..... 01 @c_shift
-c_andi 100 . 10 ... ..... 01 @c_andi
-c_sub 100 0 11 ... 00 ... 01 @cs_2
-c_xor 100 0 11 ... 01 ... 01 @cs_2
-c_or 100 0 11 ... 10 ... 01 @cs_2
-c_and 100 0 11 ... 11 ... 01 @cs_2
-c_subw 100 1 11 ... 00 ... 01 @cs_2
-c_addw 100 1 11 ... 01 ... 01 @cs_2
-c_j 101 ........... 01 @cj
-c_beqz 110 ... ... ..... 01 @cb
-c_bnez 111 ... ... ..... 01 @cb
-
-# *** RV64C Standard Extension (Quadrant 2) ***
-c_slli 000 . ..... ..... 10 @c_shift2
-c_fldsp 001 . ..... ..... 10 @c_ld
-c_lwsp 010 . ..... ..... 10 @c_lw
-c_flwsp_ldsp 011 . ..... ..... 10 @c_flwsp_ldsp #C.LDSP:RV64;C.FLWSP:RV32
-c_jr_mv 100 0 ..... ..... 10 @cr
-c_ebreak_jalr_add 100 1 ..... ..... 10 @cr
-c_fsdsp 101 ...... ..... 10 @c_sd
-c_swsp 110 . ..... ..... 10 @c_sw
-c_fswsp_sdsp 111 . ..... ..... 10 @c_fswsp_sdsp #C.SDSP:RV64;C.FSWSP:RV32
+@cr .... ..... ..... .. &r rs2=%rs2_5 rs1=%rd %rd
+@ci ... . ..... ..... .. &i imm=%imm_ci rs1=%rd %rd
+@cl_d ... ... ... .. ... .. &i imm=%uimm_cl_d rs1=%rs1_3 rd=%rs2_3
+@cl_w ... ... ... .. ... .. &i imm=%uimm_cl_w rs1=%rs1_3 rd=%rs2_3
+@cs_2 ... ... ... .. ... .. &r rs2=%rs2_3 rs1=%rs1_3 rd=%rs1_3
+@cs_d ... ... ... .. ... .. &s imm=%uimm_cl_d rs1=%rs1_3 rs2=%rs2_3
+@cs_w ... ... ... .. ... .. &s imm=%uimm_cl_w rs1=%rs1_3 rs2=%rs2_3
+@cj ... ........... .. &j imm=%imm_cj
+@cb_z ... ... ... .. ... .. &b imm=%imm_cb rs1=%rs1_3 rs2=0
+
+@c_ldsp ... . ..... ..... .. &i imm=%uimm_6bit_ld rs1=2 %rd
+@c_lwsp ... . ..... ..... .. &i imm=%uimm_6bit_lw rs1=2 %rd
+@c_sdsp ... . ..... ..... .. &s imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5
+@c_swsp ... . ..... ..... .. &s imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5
+@c_li ... . ..... ..... .. &i imm=%imm_ci rs1=0 %rd
+@c_lui ... . ..... ..... .. &u imm=%imm_lui %rd
+@c_jalr ... . ..... ..... .. &i imm=0 rs1=%rd
+@c_mv ... . ..... ..... .. &i imm=0 rs1=%rs2_5 %rd
+
+@c_addi4spn ... . ..... ..... .. &i imm=%nzuimm_ciw rs1=2 rd=%rs2_3
+@c_addi16sp ... . ..... ..... .. &i imm=%imm_addi16sp rs1=2 rd=2
+
+@c_shift ... . .. ... ..... .. \
+ &shift rd=%rs1_3 rs1=%rs1_3 shamt=%shimm_6bit
+@c_shift2 ... . .. ... ..... .. \
+ &shift rd=%rd rs1=%rd shamt=%shimm_6bit
+
+@c_andi ... . .. ... ..... .. &i imm=%imm_ci rs1=%rs1_3 rd=%rs1_3
+
+# *** RV32/64C Standard Extension (Quadrant 0) ***
+{
+ # Opcode of all zeros is illegal; rd != 0, nzuimm == 0 is reserved.
+ illegal 000 000 000 00 --- 00
+ addi 000 ... ... .. ... 00 @c_addi4spn
+}
+fld 001 ... ... .. ... 00 @cl_d
+lw 010 ... ... .. ... 00 @cl_w
+fsd 101 ... ... .. ... 00 @cs_d
+sw 110 ... ... .. ... 00 @cs_w
+
+# *** RV32/64C Standard Extension (Quadrant 1) ***
+addi 000 . ..... ..... 01 @ci
+addi 010 . ..... ..... 01 @c_li
+{
+ illegal 011 0 ----- 00000 01 # c.addi16sp and c.lui, RES nzimm=0
+ addi 011 . 00010 ..... 01 @c_addi16sp
+ lui 011 . ..... ..... 01 @c_lui
+}
+srli 100 . 00 ... ..... 01 @c_shift
+srai 100 . 01 ... ..... 01 @c_shift
+andi 100 . 10 ... ..... 01 @c_andi
+sub 100 0 11 ... 00 ... 01 @cs_2
+xor 100 0 11 ... 01 ... 01 @cs_2
+or 100 0 11 ... 10 ... 01 @cs_2
+and 100 0 11 ... 11 ... 01 @cs_2
+jal 101 ........... 01 @cj rd=0 # C.J
+beq 110 ... ... ..... 01 @cb_z
+bne 111 ... ... ..... 01 @cb_z
+
+# *** RV32/64C Standard Extension (Quadrant 2) ***
+slli 000 . ..... ..... 10 @c_shift2
+fld 001 . ..... ..... 10 @c_ldsp
+{
+ illegal 010 - 00000 ----- 10 # c.lwsp, RES rd=0
+ lw 010 . ..... ..... 10 @c_lwsp
+}
+{
+ illegal 100 0 00000 00000 10 # c.jr, RES rs1=0
+ jalr 100 0 ..... 00000 10 @c_jalr rd=0 # C.JR
+ addi 100 0 ..... ..... 10 @c_mv
+}
+{
+ ebreak 100 1 00000 00000 10
+ jalr 100 1 ..... 00000 10 @c_jalr rd=1 # C.JALR
+ add 100 1 ..... ..... 10 @cr
+}
+fsd 101 ...... ..... 10 @c_sdsp
+sw 110 . ..... ..... 10 @c_swsp
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 6f3ab7a..77f794e 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -34,9 +34,13 @@
%imm_u 12:s20 !function=ex_shift_12
# Argument sets:
+&empty
&b imm rs2 rs1
&i imm rs1 rd
+&j imm rd
&r rd rs1 rs2
+&s imm rs1 rs2
+&u imm rd
&shift shamt rs1 rd
&atomic aq rl rs2 rs1 rd
@@ -44,9 +48,9 @@
@r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd
@i ............ ..... ... ..... ....... &i imm=%imm_i %rs1 %rd
@b ....... ..... ..... ... ..... ....... &b imm=%imm_b %rs2 %rs1
-@s ....... ..... ..... ... ..... ....... imm=%imm_s %rs2 %rs1
-@u .................... ..... ....... imm=%imm_u %rd
-@j .................... ..... ....... imm=%imm_j %rd
+@s ....... ..... ..... ... ..... ....... &s imm=%imm_s %rs2 %rs1
+@u .................... ..... ....... &u imm=%imm_u %rd
+@j .................... ..... ....... &j imm=%imm_j %rd
@sh ...... ...... ..... ... ..... ....... &shift shamt=%sh10 %rs1 %rd
@csr ............ ..... ... ..... ....... %csr %rs1 %rd
diff --git a/target/riscv/insn_trans/trans_privileged.inc.c b/target/riscv/insn_trans/trans_privileged.inc.c
index acb6059..664d6ba 100644
--- a/target/riscv/insn_trans/trans_privileged.inc.c
+++ b/target/riscv/insn_trans/trans_privileged.inc.c
@@ -22,7 +22,7 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
{
/* always generates U-level ECALL, fixed in do_interrupt handler */
generate_exception(ctx, RISCV_EXCP_U_ECALL);
- tcg_gen_exit_tb(NULL, 0); /* no chaining */
+ exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
return true;
}
@@ -30,7 +30,7 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
{
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
- tcg_gen_exit_tb(NULL, 0); /* no chaining */
+ exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
return true;
}
@@ -47,7 +47,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
if (has_ext(ctx, RVS)) {
gen_helper_sret(cpu_pc, cpu_env, cpu_pc);
- tcg_gen_exit_tb(NULL, 0); /* no chaining */
+ exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
} else {
return false;
@@ -68,7 +68,7 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
#ifndef CONFIG_USER_ONLY
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
gen_helper_mret(cpu_pc, cpu_env, cpu_pc);
- tcg_gen_exit_tb(NULL, 0); /* no chaining */
+ exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
return true;
#else
diff --git a/target/riscv/insn_trans/trans_rvc.inc.c b/target/riscv/insn_trans/trans_rvc.inc.c
deleted file mode 100644
index 3e5d6fd..0000000
--- a/target/riscv/insn_trans/trans_rvc.inc.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * RISC-V translation routines for the RVC Compressed Instruction Set.
- *
- * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
- * Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
- * Bastian Koppelmann, kbastian@mail.uni-paderborn.de
- *
- * 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/>.
- */
-
-static bool trans_c_addi4spn(DisasContext *ctx, arg_c_addi4spn *a)
-{
- if (a->nzuimm == 0) {
- /* Reserved in ISA */
- return false;
- }
- arg_addi arg = { .rd = a->rd, .rs1 = 2, .imm = a->nzuimm };
- return trans_addi(ctx, &arg);
-}
-
-static bool trans_c_fld(DisasContext *ctx, arg_c_fld *a)
-{
- arg_fld arg = { .rd = a->rd, .rs1 = a->rs1, .imm = a->uimm };
- return trans_fld(ctx, &arg);
-}
-
-static bool trans_c_lw(DisasContext *ctx, arg_c_lw *a)
-{
- arg_lw arg = { .rd = a->rd, .rs1 = a->rs1, .imm = a->uimm };
- return trans_lw(ctx, &arg);
-}
-
-static bool trans_c_flw_ld(DisasContext *ctx, arg_c_flw_ld *a)
-{
-#ifdef TARGET_RISCV32
- /* C.FLW ( RV32FC-only ) */
- REQUIRE_FPU;
- REQUIRE_EXT(ctx, RVF);
-
- arg_c_lw tmp;
- decode_insn16_extract_cl_w(ctx, &tmp, ctx->opcode);
- arg_flw arg = { .rd = tmp.rd, .rs1 = tmp.rs1, .imm = tmp.uimm };
- return trans_flw(ctx, &arg);
-#else
- /* C.LD ( RV64C/RV128C-only ) */
- arg_c_fld tmp;
- decode_insn16_extract_cl_d(ctx, &tmp, ctx->opcode);
- arg_ld arg = { .rd = tmp.rd, .rs1 = tmp.rs1, .imm = tmp.uimm };
- return trans_ld(ctx, &arg);
-#endif
-}
-
-static bool trans_c_fsd(DisasContext *ctx, arg_c_fsd *a)
-{
- arg_fsd arg = { .rs1 = a->rs1, .rs2 = a->rs2, .imm = a->uimm };
- return trans_fsd(ctx, &arg);
-}
-
-static bool trans_c_sw(DisasContext *ctx, arg_c_sw *a)
-{
- arg_sw arg = { .rs1 = a->rs1, .rs2 = a->rs2, .imm = a->uimm };
- return trans_sw(ctx, &arg);
-}
-
-static bool trans_c_fsw_sd(DisasContext *ctx, arg_c_fsw_sd *a)
-{
-#ifdef TARGET_RISCV32
- /* C.FSW ( RV32FC-only ) */
- REQUIRE_FPU;
- REQUIRE_EXT(ctx, RVF);
-
- arg_c_sw tmp;
- decode_insn16_extract_cs_w(ctx, &tmp, ctx->opcode);
- arg_fsw arg = { .rs1 = tmp.rs1, .rs2 = tmp.rs2, .imm = tmp.uimm };
- return trans_fsw(ctx, &arg);
-#else
- /* C.SD ( RV64C/RV128C-only ) */
- arg_c_fsd tmp;
- decode_insn16_extract_cs_d(ctx, &tmp, ctx->opcode);
- arg_sd arg = { .rs1 = tmp.rs1, .rs2 = tmp.rs2, .imm = tmp.uimm };
- return trans_sd(ctx, &arg);
-#endif
-}
-
-static bool trans_c_addi(DisasContext *ctx, arg_c_addi *a)
-{
- if (a->imm == 0) {
- /* Hint: insn is valid but does not affect state */
- return true;
- }
- arg_addi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
- return trans_addi(ctx, &arg);
-}
-
-static bool trans_c_jal_addiw(DisasContext *ctx, arg_c_jal_addiw *a)
-{
-#ifdef TARGET_RISCV32
- /* C.JAL */
- arg_c_j tmp;
- decode_insn16_extract_cj(ctx, &tmp, ctx->opcode);
- arg_jal arg = { .rd = 1, .imm = tmp.imm };
- return trans_jal(ctx, &arg);
-#else
- /* C.ADDIW */
- arg_addiw arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
- return trans_addiw(ctx, &arg);
-#endif
-}
-
-static bool trans_c_li(DisasContext *ctx, arg_c_li *a)
-{
- if (a->rd == 0) {
- /* Hint: insn is valid but does not affect state */
- return true;
- }
- arg_addi arg = { .rd = a->rd, .rs1 = 0, .imm = a->imm };
- return trans_addi(ctx, &arg);
-}
-
-static bool trans_c_addi16sp_lui(DisasContext *ctx, arg_c_addi16sp_lui *a)
-{
- if (a->rd == 2) {
- /* C.ADDI16SP */
- arg_addi arg = { .rd = 2, .rs1 = 2, .imm = a->imm_addi16sp };
- return trans_addi(ctx, &arg);
- } else if (a->imm_lui != 0) {
- /* C.LUI */
- if (a->rd == 0) {
- /* Hint: insn is valid but does not affect state */
- return true;
- }
- arg_lui arg = { .rd = a->rd, .imm = a->imm_lui };
- return trans_lui(ctx, &arg);
- }
- return false;
-}
-
-static bool trans_c_srli(DisasContext *ctx, arg_c_srli *a)
-{
- int shamt = a->shamt;
- if (shamt == 0) {
- /* For RV128 a shamt of 0 means a shift by 64 */
- shamt = 64;
- }
- /* Ensure, that shamt[5] is zero for RV32 */
- if (shamt >= TARGET_LONG_BITS) {
- return false;
- }
-
- arg_srli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
- return trans_srli(ctx, &arg);
-}
-
-static bool trans_c_srai(DisasContext *ctx, arg_c_srai *a)
-{
- int shamt = a->shamt;
- if (shamt == 0) {
- /* For RV128 a shamt of 0 means a shift by 64 */
- shamt = 64;
- }
- /* Ensure, that shamt[5] is zero for RV32 */
- if (shamt >= TARGET_LONG_BITS) {
- return false;
- }
-
- arg_srai arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
- return trans_srai(ctx, &arg);
-}
-
-static bool trans_c_andi(DisasContext *ctx, arg_c_andi *a)
-{
- arg_andi arg = { .rd = a->rd, .rs1 = a->rd, .imm = a->imm };
- return trans_andi(ctx, &arg);
-}
-
-static bool trans_c_sub(DisasContext *ctx, arg_c_sub *a)
-{
- arg_sub arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
- return trans_sub(ctx, &arg);
-}
-
-static bool trans_c_xor(DisasContext *ctx, arg_c_xor *a)
-{
- arg_xor arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
- return trans_xor(ctx, &arg);
-}
-
-static bool trans_c_or(DisasContext *ctx, arg_c_or *a)
-{
- arg_or arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
- return trans_or(ctx, &arg);
-}
-
-static bool trans_c_and(DisasContext *ctx, arg_c_and *a)
-{
- arg_and arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
- return trans_and(ctx, &arg);
-}
-
-static bool trans_c_subw(DisasContext *ctx, arg_c_subw *a)
-{
-#ifdef TARGET_RISCV64
- arg_subw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
- return trans_subw(ctx, &arg);
-#else
- return false;
-#endif
-}
-
-static bool trans_c_addw(DisasContext *ctx, arg_c_addw *a)
-{
-#ifdef TARGET_RISCV64
- arg_addw arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
- return trans_addw(ctx, &arg);
-#else
- return false;
-#endif
-}
-
-static bool trans_c_j(DisasContext *ctx, arg_c_j *a)
-{
- arg_jal arg = { .rd = 0, .imm = a->imm };
- return trans_jal(ctx, &arg);
-}
-
-static bool trans_c_beqz(DisasContext *ctx, arg_c_beqz *a)
-{
- arg_beq arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
- return trans_beq(ctx, &arg);
-}
-
-static bool trans_c_bnez(DisasContext *ctx, arg_c_bnez *a)
-{
- arg_bne arg = { .rs1 = a->rs1, .rs2 = 0, .imm = a->imm };
- return trans_bne(ctx, &arg);
-}
-
-static bool trans_c_slli(DisasContext *ctx, arg_c_slli *a)
-{
- int shamt = a->shamt;
- if (shamt == 0) {
- /* For RV128 a shamt of 0 means a shift by 64 */
- shamt = 64;
- }
- /* Ensure, that shamt[5] is zero for RV32 */
- if (shamt >= TARGET_LONG_BITS) {
- return false;
- }
-
- arg_slli arg = { .rd = a->rd, .rs1 = a->rd, .shamt = a->shamt };
- return trans_slli(ctx, &arg);
-}
-
-static bool trans_c_fldsp(DisasContext *ctx, arg_c_fldsp *a)
-{
- arg_fld arg = { .rd = a->rd, .rs1 = 2, .imm = a->uimm };
- return trans_fld(ctx, &arg);
-}
-
-static bool trans_c_lwsp(DisasContext *ctx, arg_c_lwsp *a)
-{
- arg_lw arg = { .rd = a->rd, .rs1 = 2, .imm = a->uimm };
- return trans_lw(ctx, &arg);
-}
-
-static bool trans_c_flwsp_ldsp(DisasContext *ctx, arg_c_flwsp_ldsp *a)
-{
-#ifdef TARGET_RISCV32
- /* C.FLWSP */
- arg_flw arg_flw = { .rd = a->rd, .rs1 = 2, .imm = a->uimm_flwsp };
- return trans_flw(ctx, &arg_flw);
-#else
- /* C.LDSP */
- arg_ld arg_ld = { .rd = a->rd, .rs1 = 2, .imm = a->uimm_ldsp };
- return trans_ld(ctx, &arg_ld);
-#endif
- return false;
-}
-
-static bool trans_c_jr_mv(DisasContext *ctx, arg_c_jr_mv *a)
-{
- if (a->rd != 0 && a->rs2 == 0) {
- /* C.JR */
- arg_jalr arg = { .rd = 0, .rs1 = a->rd, .imm = 0 };
- return trans_jalr(ctx, &arg);
- } else if (a->rd != 0 && a->rs2 != 0) {
- /* C.MV */
- arg_add arg = { .rd = a->rd, .rs1 = 0, .rs2 = a->rs2 };
- return trans_add(ctx, &arg);
- }
- return false;
-}
-
-static bool trans_c_ebreak_jalr_add(DisasContext *ctx, arg_c_ebreak_jalr_add *a)
-{
- if (a->rd == 0 && a->rs2 == 0) {
- /* C.EBREAK */
- arg_ebreak arg = { };
- return trans_ebreak(ctx, &arg);
- } else if (a->rd != 0) {
- if (a->rs2 == 0) {
- /* C.JALR */
- arg_jalr arg = { .rd = 1, .rs1 = a->rd, .imm = 0 };
- return trans_jalr(ctx, &arg);
- } else {
- /* C.ADD */
- arg_add arg = { .rd = a->rd, .rs1 = a->rd, .rs2 = a->rs2 };
- return trans_add(ctx, &arg);
- }
- }
- return false;
-}
-
-static bool trans_c_fsdsp(DisasContext *ctx, arg_c_fsdsp *a)
-{
- arg_fsd arg = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm };
- return trans_fsd(ctx, &arg);
-}
-
-static bool trans_c_swsp(DisasContext *ctx, arg_c_swsp *a)
-{
- arg_sw arg = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm };
- return trans_sw(ctx, &arg);
-}
-
-static bool trans_c_fswsp_sdsp(DisasContext *ctx, arg_c_fswsp_sdsp *a)
-{
-#ifdef TARGET_RISCV32
- /* C.FSWSP */
- arg_fsw a_fsw = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm_fswsp };
- return trans_fsw(ctx, &a_fsw);
-#else
- /* C.SDSP */
- arg_sd a_sd = { .rs1 = 2, .rs2 = a->rs2, .imm = a->uimm_sdsp };
- return trans_sd(ctx, &a_sd);
-#endif
-}
diff --git a/target/riscv/insn_trans/trans_rvi.inc.c b/target/riscv/insn_trans/trans_rvi.inc.c
index d420a4d..6cda078 100644
--- a/target/riscv/insn_trans/trans_rvi.inc.c
+++ b/target/riscv/insn_trans/trans_rvi.inc.c
@@ -18,6 +18,12 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+static bool trans_illegal(DisasContext *ctx, arg_empty *a)
+{
+ gen_exception_illegal(ctx);
+ return true;
+}
+
static bool trans_lui(DisasContext *ctx, arg_lui *a)
{
if (a->rd != 0) {
@@ -60,7 +66,7 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
if (a->rd != 0) {
tcg_gen_movi_tl(cpu_gpr[a->rd], ctx->pc_succ_insn);
}
- tcg_gen_lookup_and_goto_ptr();
+ lookup_and_goto_ptr(ctx);
if (misaligned) {
gen_set_label(misaligned);
@@ -217,7 +223,7 @@ static bool trans_sd(DisasContext *ctx, arg_sd *a)
static bool trans_addi(DisasContext *ctx, arg_addi *a)
{
- return gen_arith_imm(ctx, a, &tcg_gen_add_tl);
+ return gen_arith_imm_fn(ctx, a, &tcg_gen_addi_tl);
}
static void gen_slt(TCGv ret, TCGv s1, TCGv s2)
@@ -233,25 +239,25 @@ static void gen_sltu(TCGv ret, TCGv s1, TCGv s2)
static bool trans_slti(DisasContext *ctx, arg_slti *a)
{
- return gen_arith_imm(ctx, a, &gen_slt);
+ return gen_arith_imm_tl(ctx, a, &gen_slt);
}
static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
{
- return gen_arith_imm(ctx, a, &gen_sltu);
+ return gen_arith_imm_tl(ctx, a, &gen_sltu);
}
static bool trans_xori(DisasContext *ctx, arg_xori *a)
{
- return gen_arith_imm(ctx, a, &tcg_gen_xor_tl);
+ return gen_arith_imm_fn(ctx, a, &tcg_gen_xori_tl);
}
static bool trans_ori(DisasContext *ctx, arg_ori *a)
{
- return gen_arith_imm(ctx, a, &tcg_gen_or_tl);
+ return gen_arith_imm_fn(ctx, a, &tcg_gen_ori_tl);
}
static bool trans_andi(DisasContext *ctx, arg_andi *a)
{
- return gen_arith_imm(ctx, a, &tcg_gen_and_tl);
+ return gen_arith_imm_fn(ctx, a, &tcg_gen_andi_tl);
}
static bool trans_slli(DisasContext *ctx, arg_slli *a)
{
@@ -358,7 +364,7 @@ static bool trans_and(DisasContext *ctx, arg_and *a)
#ifdef TARGET_RISCV64
static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
{
- return gen_arith_imm(ctx, a, &gen_addw);
+ return gen_arith_imm_tl(ctx, a, &gen_addw);
}
static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
@@ -483,7 +489,7 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a)
* however we need to end the translation block
*/
tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
- tcg_gen_exit_tb(NULL, 0);
+ exit_tb(ctx);
ctx->base.is_jmp = DISAS_NORETURN;
return true;
}
@@ -504,7 +510,7 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a)
gen_io_end(); \
gen_set_gpr(a->rd, dest); \
tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); \
- tcg_gen_exit_tb(NULL, 0); \
+ exit_tb(ctx); \
ctx->base.is_jmp = DISAS_NORETURN; \
tcg_temp_free(source1); \
tcg_temp_free(csr_store); \
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index b7dc18a..644d0fb 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -145,9 +145,10 @@ void helper_tlb_flush(CPURISCVState *env)
{
RISCVCPU *cpu = riscv_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- if (env->priv == PRV_S &&
- env->priv_ver >= PRIV_VERSION_1_10_0 &&
- get_field(env->mstatus, MSTATUS_TVM)) {
+ if (!(env->priv >= PRV_S) ||
+ (env->priv == PRV_S &&
+ env->priv_ver >= PRIV_VERSION_1_10_0 &&
+ get_field(env->mstatus, MSTATUS_TVM))) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
} else {
tlb_flush(cs);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 2ff6b49..313c27b 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -109,6 +109,26 @@ static void gen_exception_debug(void)
tcg_temp_free_i32(helper_tmp);
}
+/* Wrapper around tcg_gen_exit_tb that handles single stepping */
+static void exit_tb(DisasContext *ctx)
+{
+ if (ctx->base.singlestep_enabled) {
+ gen_exception_debug();
+ } else {
+ tcg_gen_exit_tb(NULL, 0);
+ }
+}
+
+/* Wrapper around tcg_gen_lookup_and_goto_ptr that handles single stepping */
+static void lookup_and_goto_ptr(DisasContext *ctx)
+{
+ if (ctx->base.singlestep_enabled) {
+ gen_exception_debug();
+ } else {
+ tcg_gen_lookup_and_goto_ptr();
+ }
+}
+
static void gen_exception_illegal(DisasContext *ctx)
{
generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
@@ -138,14 +158,14 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
/* chaining is only allowed when the jump is to the same page */
tcg_gen_goto_tb(n);
tcg_gen_movi_tl(cpu_pc, dest);
+
+ /* No need to check for single stepping here as use_goto_tb() will
+ * return false in case of single stepping.
+ */
tcg_gen_exit_tb(ctx->base.tb, n);
} else {
tcg_gen_movi_tl(cpu_pc, dest);
- if (ctx->base.singlestep_enabled) {
- gen_exception_debug();
- } else {
- tcg_gen_lookup_and_goto_ptr();
- }
+ lookup_and_goto_ptr(ctx);
}
}
@@ -538,12 +558,32 @@ static int ex_rvc_register(DisasContext *ctx, int reg)
return 8 + reg;
}
-bool decode_insn32(DisasContext *ctx, uint32_t insn);
+static int ex_rvc_shifti(DisasContext *ctx, int imm)
+{
+ /* For RV128 a shamt of 0 means a shift by 64. */
+ return imm ? imm : 64;
+}
+
/* Include the auto-generated decoder for 32 bit insn */
#include "decode_insn32.inc.c"
-static bool gen_arith_imm(DisasContext *ctx, arg_i *a,
- void(*func)(TCGv, TCGv, TCGv))
+static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a,
+ void (*func)(TCGv, TCGv, target_long))
+{
+ TCGv source1;
+ source1 = tcg_temp_new();
+
+ gen_get_gpr(source1, a->rs1);
+
+ (*func)(source1, source1, a->imm);
+
+ gen_set_gpr(a->rd, source1);
+ tcg_temp_free(source1);
+ return true;
+}
+
+static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a,
+ void (*func)(TCGv, TCGv, TCGv))
{
TCGv source1, source2;
source1 = tcg_temp_new();
@@ -667,10 +707,25 @@ static bool gen_shift(DisasContext *ctx, arg_r *a,
#include "insn_trans/trans_rvd.inc.c"
#include "insn_trans/trans_privileged.inc.c"
-bool decode_insn16(DisasContext *ctx, uint16_t insn);
-/* auto-generated decoder*/
+/*
+ * Auto-generated decoder.
+ * Note that the 16-bit decoder reuses some of the trans_* functions
+ * initially declared by the 32-bit decoder, which results in duplicate
+ * declaration warnings. Suppress them.
+ */
+#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wredundant-decls"
+# ifdef __clang__
+# pragma GCC diagnostic ignored "-Wtypedef-redefinition"
+# endif
+#endif
+
#include "decode_insn16.inc.c"
-#include "insn_trans/trans_rvc.inc.c"
+
+#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
+# pragma GCC diagnostic pop
+#endif
static void decode_opc(DisasContext *ctx)
{