Fifth RISC-V PR for QEMU 8.0
* Experimantal support for writable misa. * Support for Svadu extension. * Support for the Zicond extension. * Fixes to gdbstub, CSR accesses, dependencies between the various floating-point exceptions, and XTheadMemPair. * Many cleanups. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAmQBrrUTHHBhbG1lckBk YWJiZWx0LmNvbQAKCRAuExnzX7sYicHrD/9dHBDOYNwyT/C2Q31NHMcEsVN6J0kW 0sVyDb2/TUFoXmClMwS6jZYQQwWD7tjjB7BDcvPJ0QKLblDoZFX5JyxpQypIKWcs It/E6mk7aG0epH1GoB/mbHFDbeCm4tbo7Vf6cQGpV/vGWBUaOS67c5nenUK7Tlqw NTr9qak+9NYVswvMHZ0lUKtO12W1g/1EVkict2/90P2snWbPZ+foWomifGNljmhy 5WtCNp27uBKF/uuD9xubLOxSEcqtZFTuKJy7U3azV4I0IKfd6Is83Kd0IwBOrTgT MYkFdtQE1jgbkXYVZjft6ymLuqJrcLFYwD8C2zdNAXJLk1Y+MCtGafgW6f6SkT6B FrNaSOqQ9xXiaNStF2FwYdmZ476zcY+eEg2rH1grTwCMewZ9r7m3+H8iat/tR0pt 9scYAre1oaL33LB6DGZi3JkssNYyj42sutcNao2hQXRHcsh+vv1dLR+Di2mO6Ji5 MNfvEgCrWWZjNVSwvhwCXdJPqqpyTbkRf8HJEp0gWvjk6VoF8sWidDw/8oMLj+wW qZur7GNe+piJNvly85aFSL9J3SX7RyNeDzX/yK3b4k+g6I/ZziQaNgQtB9gYcm6w mj3snCwRbEMEhdhPH0+Chm0Wb97knHJS14Vq9wCe2xh16o3HM5FspboLFkGZMjDV tRDPFb7pitwdlA== =FMkl -----END PGP SIGNATURE----- Merge tag 'pull-riscv-to-apply-20230303' of https://gitlab.com/palmer-dabbelt/qemu into staging Fifth RISC-V PR for QEMU 8.0 * Experimantal support for writable misa. * Support for Svadu extension. * Support for the Zicond extension. * Fixes to gdbstub, CSR accesses, dependencies between the various floating-point exceptions, and XTheadMemPair. * Many cleanups. # -----BEGIN PGP SIGNATURE----- # # iQJHBAABCAAxFiEEKzw3R0RoQ7JKlDp6LhMZ81+7GIkFAmQBrrUTHHBhbG1lckBk # YWJiZWx0LmNvbQAKCRAuExnzX7sYicHrD/9dHBDOYNwyT/C2Q31NHMcEsVN6J0kW # 0sVyDb2/TUFoXmClMwS6jZYQQwWD7tjjB7BDcvPJ0QKLblDoZFX5JyxpQypIKWcs # It/E6mk7aG0epH1GoB/mbHFDbeCm4tbo7Vf6cQGpV/vGWBUaOS67c5nenUK7Tlqw # NTr9qak+9NYVswvMHZ0lUKtO12W1g/1EVkict2/90P2snWbPZ+foWomifGNljmhy # 5WtCNp27uBKF/uuD9xubLOxSEcqtZFTuKJy7U3azV4I0IKfd6Is83Kd0IwBOrTgT # MYkFdtQE1jgbkXYVZjft6ymLuqJrcLFYwD8C2zdNAXJLk1Y+MCtGafgW6f6SkT6B # FrNaSOqQ9xXiaNStF2FwYdmZ476zcY+eEg2rH1grTwCMewZ9r7m3+H8iat/tR0pt # 9scYAre1oaL33LB6DGZi3JkssNYyj42sutcNao2hQXRHcsh+vv1dLR+Di2mO6Ji5 # MNfvEgCrWWZjNVSwvhwCXdJPqqpyTbkRf8HJEp0gWvjk6VoF8sWidDw/8oMLj+wW # qZur7GNe+piJNvly85aFSL9J3SX7RyNeDzX/yK3b4k+g6I/ZziQaNgQtB9gYcm6w # mj3snCwRbEMEhdhPH0+Chm0Wb97knHJS14Vq9wCe2xh16o3HM5FspboLFkGZMjDV # tRDPFb7pitwdlA== # =FMkl # -----END PGP SIGNATURE----- # gpg: Signature made Fri 03 Mar 2023 08:24:21 GMT # gpg: using RSA key 2B3C3747446843B24A943A7A2E1319F35FBB1889 # gpg: issuer "palmer@dabbelt.com" # gpg: Good signature from "Palmer Dabbelt <palmer@dabbelt.com>" [unknown] # gpg: aka "Palmer Dabbelt <palmerdabbelt@google.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 # Subkey fingerprint: 2B3C 3747 4468 43B2 4A94 3A7A 2E13 19F3 5FBB 1889 * tag 'pull-riscv-to-apply-20230303' of https://gitlab.com/palmer-dabbelt/qemu: (59 commits) target/riscv/vector_helper.c: avoid env_archcpu() when reading RISCVCPUConfig target/riscv/vector_helper.c: create vext_set_tail_elems_1s() target/riscv/csr.c: avoid env_archcpu() usages when reading RISCVCPUConfig target/riscv/csr.c: use riscv_cpu_cfg() to avoid env_cpu() pointers target/riscv/csr.c: simplify mctr() target/riscv/csr.c: use env_archcpu() in ctr() target/riscv: Export Svadu property target/riscv: Add *envcfg.HADE related check in address translation target/riscv: Add *envcfg.PBMTE related check in address translation target/riscv: Add csr support for svadu target/riscv: Fix the relationship of PBMTE/STCE fields between menvcfg and henvcfg target/riscv: Fix the relationship between menvcfg.PBMTE/STCE and Svpbmt/Sstc extensions hw/riscv: Move the dtb load bits outside of create_fdt() hw/riscv: Skip re-generating DT nodes for a given DTB target/riscv: Add support for Zicond extension RISC-V: XTheadMemPair: Remove register restrictions for store-pair target/riscv: Fix checking of whether instruciton at 'pc_next' spans pages target/riscv: Group all predicate() routines together target/riscv: Drop priv level check in mseccfg predicate() target/riscv: Allow debugger to access sstc CSRs ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
76116e28e1
@ -99,7 +99,7 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
|
||||
MachineState *ms = MACHINE(s);
|
||||
uint64_t mem_size = ms->ram_size;
|
||||
void *fdt;
|
||||
int cpu, fdt_size;
|
||||
int cpu;
|
||||
uint32_t *cells;
|
||||
char *nodename;
|
||||
uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
|
||||
@ -112,18 +112,10 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
|
||||
"sifive,plic-1.0.0", "riscv,plic0"
|
||||
};
|
||||
|
||||
if (ms->dtb) {
|
||||
fdt = ms->fdt = load_device_tree(ms->dtb, &fdt_size);
|
||||
if (!fdt) {
|
||||
error_report("load_device_tree() failed");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
fdt = ms->fdt = create_device_tree(&fdt_size);
|
||||
if (!fdt) {
|
||||
error_report("create_device_tree() failed");
|
||||
exit(1);
|
||||
}
|
||||
fdt = ms->fdt = create_device_tree(&s->fdt_size);
|
||||
if (!fdt) {
|
||||
error_report("create_device_tree() failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
qemu_fdt_setprop_string(fdt, "/", "model", "SiFive HiFive Unleashed A00");
|
||||
@ -560,8 +552,16 @@ static void sifive_u_machine_init(MachineState *machine)
|
||||
qdev_connect_gpio_out(DEVICE(&(s->soc.gpio)), 10,
|
||||
qemu_allocate_irq(sifive_u_machine_reset, NULL, 0));
|
||||
|
||||
/* create device tree */
|
||||
create_fdt(s, memmap, riscv_is_32bit(&s->soc.u_cpus));
|
||||
/* load/create device tree */
|
||||
if (machine->dtb) {
|
||||
machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
|
||||
if (!machine->fdt) {
|
||||
error_report("load_device_tree() failed");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
create_fdt(s, memmap, riscv_is_32bit(&s->soc.u_cpus));
|
||||
}
|
||||
|
||||
if (s->start_in_flash) {
|
||||
/*
|
||||
|
@ -232,20 +232,21 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
|
||||
bool is_32_bit = riscv_is_32bit(&s->soc[0]);
|
||||
|
||||
for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
|
||||
RISCVCPU *cpu_ptr = &s->soc[socket].harts[cpu];
|
||||
|
||||
cpu_phandle = (*phandle)++;
|
||||
|
||||
cpu_name = g_strdup_printf("/cpus/cpu@%d",
|
||||
s->soc[socket].hartid_base + cpu);
|
||||
qemu_fdt_add_subnode(ms->fdt, cpu_name);
|
||||
if (riscv_feature(&s->soc[socket].harts[cpu].env,
|
||||
RISCV_FEATURE_MMU)) {
|
||||
if (cpu_ptr->cfg.mmu) {
|
||||
qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type",
|
||||
(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
|
||||
} else {
|
||||
qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type",
|
||||
"riscv,none");
|
||||
}
|
||||
name = riscv_isa_string(&s->soc[socket].harts[cpu]);
|
||||
name = riscv_isa_string(cpu_ptr);
|
||||
qemu_fdt_setprop_string(ms->fdt, cpu_name, "riscv,isa", name);
|
||||
g_free(name);
|
||||
qemu_fdt_setprop_string(ms->fdt, cpu_name, "compatible", "riscv");
|
||||
@ -1008,18 +1009,10 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap)
|
||||
uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
|
||||
uint8_t rng_seed[32];
|
||||
|
||||
if (ms->dtb) {
|
||||
ms->fdt = load_device_tree(ms->dtb, &s->fdt_size);
|
||||
if (!ms->fdt) {
|
||||
error_report("load_device_tree() failed");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
ms->fdt = create_device_tree(&s->fdt_size);
|
||||
if (!ms->fdt) {
|
||||
error_report("create_device_tree() failed");
|
||||
exit(1);
|
||||
}
|
||||
ms->fdt = create_device_tree(&s->fdt_size);
|
||||
if (!ms->fdt) {
|
||||
error_report("create_device_tree() failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
qemu_fdt_setprop_string(ms->fdt, "/", "model", "riscv-virtio,qemu");
|
||||
@ -1504,8 +1497,16 @@ static void virt_machine_init(MachineState *machine)
|
||||
}
|
||||
virt_flash_map(s, system_memory);
|
||||
|
||||
/* create device tree */
|
||||
create_fdt(s, memmap);
|
||||
/* load/create device tree */
|
||||
if (machine->dtb) {
|
||||
machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
|
||||
if (!machine->fdt) {
|
||||
error_report("load_device_tree() failed");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
create_fdt(s, memmap);
|
||||
}
|
||||
|
||||
s->machine_done.notify = virt_machine_done;
|
||||
qemu_add_machine_init_done_notifier(&s->machine_done);
|
||||
|
@ -68,6 +68,7 @@ typedef struct SiFiveUState {
|
||||
|
||||
/*< public >*/
|
||||
SiFiveUSoCState soc;
|
||||
int fdt_size;
|
||||
|
||||
bool start_in_flash;
|
||||
uint32_t msel;
|
||||
|
@ -75,6 +75,7 @@ struct isa_ext_data {
|
||||
static const struct isa_ext_data isa_edata_arr[] = {
|
||||
ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
|
||||
ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_10_0, ext_v),
|
||||
ISA_EXT_DATA_ENTRY(zicond, true, PRIV_VERSION_1_12_0, ext_zicond),
|
||||
ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
|
||||
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),
|
||||
@ -102,12 +103,16 @@ static const struct isa_ext_data isa_edata_arr[] = {
|
||||
ISA_EXT_DATA_ENTRY(zkt, true, PRIV_VERSION_1_12_0, ext_zkt),
|
||||
ISA_EXT_DATA_ENTRY(zve32f, true, PRIV_VERSION_1_12_0, ext_zve32f),
|
||||
ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
|
||||
ISA_EXT_DATA_ENTRY(zve64d, true, PRIV_VERSION_1_12_0, ext_zve64d),
|
||||
ISA_EXT_DATA_ENTRY(zvfh, true, PRIV_VERSION_1_12_0, ext_zvfh),
|
||||
ISA_EXT_DATA_ENTRY(zvfhmin, true, PRIV_VERSION_1_12_0, ext_zvfhmin),
|
||||
ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
|
||||
ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
|
||||
ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
|
||||
ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
|
||||
ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
|
||||
ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
|
||||
ISA_EXT_DATA_ENTRY(svadu, true, PRIV_VERSION_1_12_0, ext_svadu),
|
||||
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),
|
||||
@ -616,6 +621,11 @@ static void riscv_cpu_reset_hold(Object *obj)
|
||||
env->bins = 0;
|
||||
env->two_stage_lookup = false;
|
||||
|
||||
env->menvcfg = (cpu->cfg.ext_svpbmt ? MENVCFG_PBMTE : 0) |
|
||||
(cpu->cfg.ext_svadu ? MENVCFG_HADE : 0);
|
||||
env->henvcfg = (cpu->cfg.ext_svpbmt ? HENVCFG_PBMTE : 0) |
|
||||
(cpu->cfg.ext_svadu ? HENVCFG_HADE : 0);
|
||||
|
||||
/* Initialized default priorities of local interrupts. */
|
||||
for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
|
||||
iprio = riscv_cpu_default_priority(i);
|
||||
@ -640,7 +650,7 @@ static void riscv_cpu_reset_hold(Object *obj)
|
||||
set_default_nan_mode(1, &env->fp_status);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (riscv_feature(env, RISCV_FEATURE_DEBUG)) {
|
||||
if (cpu->cfg.debug) {
|
||||
riscv_trigger_init(env);
|
||||
}
|
||||
|
||||
@ -732,7 +742,11 @@ static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cpu->cfg.ext_zfh || cpu->cfg.ext_zfhmin) && !cpu->cfg.ext_f) {
|
||||
if (cpu->cfg.ext_zfh) {
|
||||
cpu->cfg.ext_zfhmin = true;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_zfhmin && !cpu->cfg.ext_f) {
|
||||
error_setg(errp, "Zfh/Zfhmin extensions require F extension");
|
||||
return;
|
||||
}
|
||||
@ -742,19 +756,51 @@ static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_v && !cpu->cfg.ext_d) {
|
||||
error_setg(errp, "V extension requires D extension");
|
||||
/* The V vector extension depends on the Zve64d extension */
|
||||
if (cpu->cfg.ext_v) {
|
||||
cpu->cfg.ext_zve64d = true;
|
||||
}
|
||||
|
||||
/* The Zve64d extension depends on the Zve64f extension */
|
||||
if (cpu->cfg.ext_zve64d) {
|
||||
cpu->cfg.ext_zve64f = true;
|
||||
}
|
||||
|
||||
/* The Zve64f extension depends on the Zve32f extension */
|
||||
if (cpu->cfg.ext_zve64f) {
|
||||
cpu->cfg.ext_zve32f = true;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_zve64d && !cpu->cfg.ext_d) {
|
||||
error_setg(errp, "Zve64d/V extensions require D extension");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) && !cpu->cfg.ext_f) {
|
||||
if (cpu->cfg.ext_zve32f && !cpu->cfg.ext_f) {
|
||||
error_setg(errp, "Zve32f/Zve64f extensions require F extension");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_zvfh) {
|
||||
cpu->cfg.ext_zvfhmin = true;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
|
||||
error_setg(errp, "Zvfh/Zvfhmin extensions require Zve32f extension");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_zvfh && !cpu->cfg.ext_zfhmin) {
|
||||
error_setg(errp, "Zvfh extensions requires Zfhmin extension");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the ISA extensions, checks should have happened above */
|
||||
if (cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinx ||
|
||||
cpu->cfg.ext_zhinxmin) {
|
||||
if (cpu->cfg.ext_zhinx) {
|
||||
cpu->cfg.ext_zhinxmin = true;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) {
|
||||
cpu->cfg.ext_zfinx = true;
|
||||
}
|
||||
|
||||
@ -765,7 +811,7 @@ static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
||||
}
|
||||
if (cpu->cfg.ext_f) {
|
||||
error_setg(errp,
|
||||
"Zfinx cannot be supported together with F extension");
|
||||
"Zfinx cannot be supported together with F extension");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -828,40 +874,40 @@ static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
||||
ext |= RVV;
|
||||
if (!is_power_of_2(cpu->cfg.vlen)) {
|
||||
error_setg(errp,
|
||||
"Vector extension VLEN must be power of 2");
|
||||
"Vector extension VLEN must be power of 2");
|
||||
return;
|
||||
}
|
||||
if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 128) {
|
||||
error_setg(errp,
|
||||
"Vector extension implementation only supports VLEN "
|
||||
"in the range [128, %d]", RV_VLEN_MAX);
|
||||
"Vector extension implementation only supports VLEN "
|
||||
"in the range [128, %d]", RV_VLEN_MAX);
|
||||
return;
|
||||
}
|
||||
if (!is_power_of_2(cpu->cfg.elen)) {
|
||||
error_setg(errp,
|
||||
"Vector extension ELEN must be power of 2");
|
||||
"Vector extension ELEN must be power of 2");
|
||||
return;
|
||||
}
|
||||
if (cpu->cfg.elen > 64 || cpu->cfg.elen < 8) {
|
||||
error_setg(errp,
|
||||
"Vector extension implementation only supports ELEN "
|
||||
"in the range [8, 64]");
|
||||
return;
|
||||
}
|
||||
if (cpu->cfg.vext_spec) {
|
||||
if (!g_strcmp0(cpu->cfg.vext_spec, "v1.0")) {
|
||||
vext_version = VEXT_VERSION_1_00_0;
|
||||
} else {
|
||||
if (cpu->cfg.elen > 64 || cpu->cfg.elen < 8) {
|
||||
error_setg(errp,
|
||||
"Unsupported vector spec version '%s'",
|
||||
cpu->cfg.vext_spec);
|
||||
"Vector extension implementation only supports ELEN "
|
||||
"in the range [8, 64]");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qemu_log("vector version is not specified, "
|
||||
"use the default value v1.0\n");
|
||||
}
|
||||
set_vext_version(env, vext_version);
|
||||
if (cpu->cfg.vext_spec) {
|
||||
if (!g_strcmp0(cpu->cfg.vext_spec, "v1.0")) {
|
||||
vext_version = VEXT_VERSION_1_00_0;
|
||||
} else {
|
||||
error_setg(errp,
|
||||
"Unsupported vector spec version '%s'",
|
||||
cpu->cfg.vext_spec);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qemu_log("vector version is not specified, "
|
||||
"use the default value v1.0\n");
|
||||
}
|
||||
set_vext_version(env, vext_version);
|
||||
}
|
||||
if (cpu->cfg.ext_j) {
|
||||
ext |= RVJ;
|
||||
@ -922,24 +968,13 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->cfg.mmu) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_MMU);
|
||||
}
|
||||
|
||||
if (cpu->cfg.pmp) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_PMP);
|
||||
|
||||
if (cpu->cfg.epmp && !cpu->cfg.pmp) {
|
||||
/*
|
||||
* Enhanced PMP should only be available
|
||||
* on harts with PMP support
|
||||
*/
|
||||
if (cpu->cfg.epmp) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_EPMP);
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->cfg.debug) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_DEBUG);
|
||||
error_setg(errp, "Invalid configuration: EPMP requires PMP support");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1093,6 +1128,7 @@ static Property riscv_cpu_extensions[] = {
|
||||
DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false),
|
||||
DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false),
|
||||
DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false),
|
||||
DEFINE_PROP_BOOL("Zve64d", RISCVCPU, cfg.ext_zve64d, false),
|
||||
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
|
||||
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
|
||||
DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true),
|
||||
@ -1102,6 +1138,8 @@ static Property riscv_cpu_extensions[] = {
|
||||
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
|
||||
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
|
||||
|
||||
DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
|
||||
|
||||
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
|
||||
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
|
||||
DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
|
||||
@ -1146,12 +1184,16 @@ static Property riscv_cpu_extensions[] = {
|
||||
DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
|
||||
|
||||
/* These are experimental so mark with 'x-' */
|
||||
DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
|
||||
DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
|
||||
/* ePMP 0.9.3 */
|
||||
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
|
||||
DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
|
||||
DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
|
||||
|
||||
DEFINE_PROP_BOOL("x-zvfh", RISCVCPU, cfg.ext_zvfh, false),
|
||||
DEFINE_PROP_BOOL("x-zvfhmin", RISCVCPU, cfg.ext_zvfhmin, false),
|
||||
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@ -1213,6 +1255,12 @@ static Property riscv_cpu_properties[] = {
|
||||
|
||||
DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false),
|
||||
DEFINE_PROP_BOOL("rvv_ma_all_1s", RISCVCPU, cfg.rvv_ma_all_1s, false),
|
||||
|
||||
/*
|
||||
* write_misa() is marked as experimental for now so mark
|
||||
* it with -x and default to 'false'.
|
||||
*/
|
||||
DEFINE_PROP_BOOL("x-misa-w", RISCVCPU, cfg.misa_w, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -81,17 +81,6 @@
|
||||
#define RVH RV('H')
|
||||
#define RVJ RV('J')
|
||||
|
||||
/* S extension denotes that Supervisor mode exists, however it is possible
|
||||
to have a core that support S mode but does not have an MMU and there
|
||||
is currently no bit in misa to indicate whether an MMU exists or not
|
||||
so a cpu features bitfield is required, likewise for optional PMP support */
|
||||
enum {
|
||||
RISCV_FEATURE_MMU,
|
||||
RISCV_FEATURE_PMP,
|
||||
RISCV_FEATURE_EPMP,
|
||||
RISCV_FEATURE_MISA,
|
||||
RISCV_FEATURE_DEBUG
|
||||
};
|
||||
|
||||
/* Privileged specification version */
|
||||
enum {
|
||||
@ -186,8 +175,6 @@ struct CPUArchState {
|
||||
/* 128-bit helpers upper part return value */
|
||||
target_ulong retxh;
|
||||
|
||||
uint32_t features;
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
uint32_t elf_flags;
|
||||
#endif
|
||||
@ -447,9 +434,11 @@ struct RISCVCPUConfig {
|
||||
bool ext_zkt;
|
||||
bool ext_ifencei;
|
||||
bool ext_icsr;
|
||||
bool ext_zicond;
|
||||
bool ext_zihintpause;
|
||||
bool ext_smstateen;
|
||||
bool ext_sstc;
|
||||
bool ext_svadu;
|
||||
bool ext_svinval;
|
||||
bool ext_svnapot;
|
||||
bool ext_svpbmt;
|
||||
@ -462,7 +451,10 @@ struct RISCVCPUConfig {
|
||||
bool ext_zhinxmin;
|
||||
bool ext_zve32f;
|
||||
bool ext_zve64f;
|
||||
bool ext_zve64d;
|
||||
bool ext_zmmul;
|
||||
bool ext_zvfh;
|
||||
bool ext_zvfhmin;
|
||||
bool ext_smaia;
|
||||
bool ext_ssaia;
|
||||
bool ext_sscofpmf;
|
||||
@ -498,6 +490,7 @@ struct RISCVCPUConfig {
|
||||
bool pmp;
|
||||
bool epmp;
|
||||
bool debug;
|
||||
bool misa_w;
|
||||
|
||||
bool short_isa_string;
|
||||
};
|
||||
@ -535,16 +528,6 @@ static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
|
||||
return (env->misa_ext & ext) != 0;
|
||||
}
|
||||
|
||||
static inline bool riscv_feature(CPURISCVState *env, int feature)
|
||||
{
|
||||
return env->features & (1ULL << feature);
|
||||
}
|
||||
|
||||
static inline void riscv_set_feature(CPURISCVState *env, int feature)
|
||||
{
|
||||
env->features |= (1ULL << feature);
|
||||
}
|
||||
|
||||
#include "cpu_user.h"
|
||||
|
||||
extern const char * const riscv_int_regnames[];
|
||||
@ -654,6 +637,11 @@ static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
|
||||
#endif
|
||||
#define riscv_cpu_mxl_bits(env) (1UL << (4 + riscv_cpu_mxl(env)))
|
||||
|
||||
static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env)
|
||||
{
|
||||
return &env_archcpu(env)->cfg;
|
||||
}
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
#define cpu_recompute_xl(env) ((void)(env), MXL_RV32)
|
||||
#else
|
||||
|
@ -747,10 +747,12 @@ typedef enum RISCVException {
|
||||
#define MENVCFG_CBIE (3UL << 4)
|
||||
#define MENVCFG_CBCFE BIT(6)
|
||||
#define MENVCFG_CBZE BIT(7)
|
||||
#define MENVCFG_HADE (1ULL << 61)
|
||||
#define MENVCFG_PBMTE (1ULL << 62)
|
||||
#define MENVCFG_STCE (1ULL << 63)
|
||||
|
||||
/* For RV32 */
|
||||
#define MENVCFGH_HADE BIT(29)
|
||||
#define MENVCFGH_PBMTE BIT(30)
|
||||
#define MENVCFGH_STCE BIT(31)
|
||||
|
||||
@ -763,10 +765,12 @@ typedef enum RISCVException {
|
||||
#define HENVCFG_CBIE MENVCFG_CBIE
|
||||
#define HENVCFG_CBCFE MENVCFG_CBCFE
|
||||
#define HENVCFG_CBZE MENVCFG_CBZE
|
||||
#define HENVCFG_HADE MENVCFG_HADE
|
||||
#define HENVCFG_PBMTE MENVCFG_PBMTE
|
||||
#define HENVCFG_STCE MENVCFG_STCE
|
||||
|
||||
/* For RV32 */
|
||||
#define HENVCFGH_HADE MENVCFGH_HADE
|
||||
#define HENVCFGH_PBMTE MENVCFGH_PBMTE
|
||||
#define HENVCFGH_STCE MENVCFGH_STCE
|
||||
|
||||
|
@ -51,7 +51,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
|
||||
*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
|
||||
*cs_base = 0;
|
||||
|
||||
if (riscv_has_ext(env, RVV) || cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) {
|
||||
if (cpu->cfg.ext_zve32f) {
|
||||
/*
|
||||
* If env->vl equals to VLMAX, we can use generic vector operation
|
||||
* expanders (GVEC) to accerlate the vector operations.
|
||||
@ -105,7 +105,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS,
|
||||
get_field(env->mstatus_hs, MSTATUS_VS));
|
||||
}
|
||||
if (riscv_feature(env, RISCV_FEATURE_DEBUG) && !icount_enabled()) {
|
||||
if (cpu->cfg.debug && !icount_enabled()) {
|
||||
flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
|
||||
}
|
||||
#endif
|
||||
@ -706,7 +706,7 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot,
|
||||
pmp_priv_t pmp_priv;
|
||||
int pmp_index = -1;
|
||||
|
||||
if (!riscv_feature(env, RISCV_FEATURE_PMP)) {
|
||||
if (!riscv_cpu_cfg(env)->pmp) {
|
||||
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
return TRANSLATE_SUCCESS;
|
||||
}
|
||||
@ -796,7 +796,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
|
||||
mode = PRV_U;
|
||||
}
|
||||
|
||||
if (mode == PRV_M || !riscv_feature(env, RISCV_FEATURE_MMU)) {
|
||||
if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
|
||||
*physical = addr;
|
||||
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
return TRANSLATE_SUCCESS;
|
||||
@ -936,9 +936,17 @@ restart:
|
||||
return TRANSLATE_FAIL;
|
||||
}
|
||||
|
||||
bool pbmte = env->menvcfg & MENVCFG_PBMTE;
|
||||
bool hade = env->menvcfg & MENVCFG_HADE;
|
||||
|
||||
if (first_stage && two_stage && riscv_cpu_virt_enabled(env)) {
|
||||
pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
|
||||
hade = hade && (env->henvcfg & HENVCFG_HADE);
|
||||
}
|
||||
|
||||
if (riscv_cpu_sxl(env) == MXL_RV32) {
|
||||
ppn = pte >> PTE_PPN_SHIFT;
|
||||
} else if (cpu->cfg.ext_svpbmt || cpu->cfg.ext_svnapot) {
|
||||
} else if (pbmte || cpu->cfg.ext_svnapot) {
|
||||
ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
|
||||
} else {
|
||||
ppn = pte >> PTE_PPN_SHIFT;
|
||||
@ -950,7 +958,7 @@ restart:
|
||||
if (!(pte & PTE_V)) {
|
||||
/* Invalid PTE */
|
||||
return TRANSLATE_FAIL;
|
||||
} else if (!cpu->cfg.ext_svpbmt && (pte & PTE_PBMT)) {
|
||||
} else if (!pbmte && (pte & PTE_PBMT)) {
|
||||
return TRANSLATE_FAIL;
|
||||
} else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
|
||||
/* Inner PTE, continue walking */
|
||||
@ -992,6 +1000,10 @@ restart:
|
||||
|
||||
/* Page table updates need to be atomic with MTTCG enabled */
|
||||
if (updated_pte != pte) {
|
||||
if (!hade) {
|
||||
return TRANSLATE_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* - if accessed or dirty bits need updating, and the PTE is
|
||||
* in RAM, then we do so atomically with a compare and swap.
|
||||
|
@ -46,10 +46,8 @@ static RISCVException smstateen_acc_ok(CPURISCVState *env, int index,
|
||||
uint64_t bit)
|
||||
{
|
||||
bool virt = riscv_cpu_virt_enabled(env);
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
|
||||
if (env->priv == PRV_M || !cpu->cfg.ext_smstateen) {
|
||||
if (env->priv == PRV_M || !riscv_cpu_cfg(env)->ext_smstateen) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -81,7 +79,7 @@ static RISCVException fs(CPURISCVState *env, int csrno)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (!env->debugger && !riscv_cpu_fp_enabled(env) &&
|
||||
!RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) {
|
||||
!riscv_cpu_cfg(env)->ext_zfinx) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
#endif
|
||||
@ -90,11 +88,9 @@ static RISCVException fs(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException vs(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (env->misa_ext & RVV ||
|
||||
cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) {
|
||||
if (cpu->cfg.ext_zve32f) {
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (!env->debugger && !riscv_cpu_vector_enabled(env)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
@ -108,8 +104,7 @@ static RISCVException vs(CPURISCVState *env, int csrno)
|
||||
static RISCVException ctr(CPURISCVState *env, int csrno)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
int ctr_index;
|
||||
target_ulong ctr_mask;
|
||||
int base_csrno = CSR_CYCLE;
|
||||
@ -134,6 +129,10 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
|
||||
|
||||
skip_ext_pmu_check:
|
||||
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (env->priv < PRV_M && !get_field(env->mcounteren, ctr_mask)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
@ -166,8 +165,7 @@ static RISCVException ctr32(CPURISCVState *env, int csrno)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
static RISCVException mctr(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
int pmu_num = riscv_cpu_cfg(env)->pmu_num;
|
||||
int ctr_index;
|
||||
int base_csrno = CSR_MHPMCOUNTER3;
|
||||
|
||||
@ -176,7 +174,7 @@ static RISCVException mctr(CPURISCVState *env, int csrno)
|
||||
base_csrno += 0x80;
|
||||
}
|
||||
ctr_index = csrno - base_csrno;
|
||||
if (!cpu->cfg.pmu_num || ctr_index >= cpu->cfg.pmu_num) {
|
||||
if (!pmu_num || ctr_index >= pmu_num) {
|
||||
/* The PMU is not enabled or counter is out of range*/
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
@ -195,8 +193,7 @@ static RISCVException mctr32(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException sscofpmf(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_sscofpmf) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
@ -222,9 +219,7 @@ static RISCVException any32(CPURISCVState *env, int csrno)
|
||||
|
||||
static int aia_any(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_smaia) {
|
||||
if (!riscv_cpu_cfg(env)->ext_smaia) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
@ -233,9 +228,7 @@ static int aia_any(CPURISCVState *env, int csrno)
|
||||
|
||||
static int aia_any32(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_smaia) {
|
||||
if (!riscv_cpu_cfg(env)->ext_smaia) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
@ -262,9 +255,7 @@ static int smode32(CPURISCVState *env, int csrno)
|
||||
|
||||
static int aia_smode(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_ssaia) {
|
||||
if (!riscv_cpu_cfg(env)->ext_ssaia) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
@ -273,9 +264,7 @@ static int aia_smode(CPURISCVState *env, int csrno)
|
||||
|
||||
static int aia_smode32(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_ssaia) {
|
||||
if (!riscv_cpu_cfg(env)->ext_ssaia) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
@ -321,8 +310,7 @@ static RISCVException umode32(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException mstateen(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_smstateen) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
@ -333,20 +321,28 @@ static RISCVException mstateen(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException hstateen_pred(CPURISCVState *env, int csrno, int base)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_smstateen) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
RISCVException ret = hmode(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (env->priv < PRV_M) {
|
||||
if (!(env->mstateen[csrno - base] & SMSTATEEN_STATEEN)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
}
|
||||
|
||||
return hmode(env, csrno);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException hstateen(CPURISCVState *env, int csrno)
|
||||
@ -363,13 +359,20 @@ static RISCVException sstateen(CPURISCVState *env, int csrno)
|
||||
{
|
||||
bool virt = riscv_cpu_virt_enabled(env);
|
||||
int index = csrno - CSR_SSTATEEN0;
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
|
||||
if (!cpu->cfg.ext_smstateen) {
|
||||
if (!riscv_cpu_cfg(env)->ext_smstateen) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
RISCVException ret = smode(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (env->priv < PRV_M) {
|
||||
if (!(env->mstateen[index] & SMSTATEEN_STATEEN)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
@ -382,7 +385,61 @@ static RISCVException sstateen(CPURISCVState *env, int csrno)
|
||||
}
|
||||
}
|
||||
|
||||
return smode(env, csrno);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException sstc(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
bool hmode_check = false;
|
||||
|
||||
if (!cpu->cfg.ext_sstc || !env->rdtime_fn) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) {
|
||||
hmode_check = true;
|
||||
}
|
||||
|
||||
RISCVException ret = hmode_check ? hmode(env, csrno) : smode(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
if (env->priv == PRV_M) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* No need of separate function for rv32 as menvcfg stores both menvcfg
|
||||
* menvcfgh for RV32.
|
||||
*/
|
||||
if (!(get_field(env->mcounteren, COUNTEREN_TM) &&
|
||||
get_field(env->menvcfg, MENVCFG_STCE))) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (riscv_cpu_virt_enabled(env)) {
|
||||
if (!(get_field(env->hcounteren, COUNTEREN_TM) &&
|
||||
get_field(env->henvcfg, HENVCFG_STCE))) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException sstc_32(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (riscv_cpu_mxl(env) != MXL_RV32) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
return sstc(env, csrno);
|
||||
}
|
||||
|
||||
/* Checks if PointerMasking registers could be accessed */
|
||||
@ -397,9 +454,7 @@ static RISCVException pointer_masking(CPURISCVState *env, int csrno)
|
||||
|
||||
static int aia_hmode(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_ssaia) {
|
||||
if (!riscv_cpu_cfg(env)->ext_ssaia) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
@ -408,9 +463,7 @@ static int aia_hmode(CPURISCVState *env, int csrno)
|
||||
|
||||
static int aia_hmode32(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_ssaia) {
|
||||
if (!riscv_cpu_cfg(env)->ext_ssaia) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
@ -419,7 +472,16 @@ static int aia_hmode32(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException pmp(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (riscv_feature(env, RISCV_FEATURE_PMP)) {
|
||||
if (riscv_cpu_cfg(env)->pmp) {
|
||||
if (csrno <= CSR_PMPCFG3) {
|
||||
uint32_t reg_index = csrno - CSR_PMPCFG0;
|
||||
|
||||
/* TODO: RV128 restriction check */
|
||||
if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -428,7 +490,7 @@ static RISCVException pmp(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException epmp(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (env->priv == PRV_M && riscv_feature(env, RISCV_FEATURE_EPMP)) {
|
||||
if (riscv_cpu_cfg(env)->epmp) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -437,7 +499,7 @@ static RISCVException epmp(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException debug(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (riscv_feature(env, RISCV_FEATURE_DEBUG)) {
|
||||
if (riscv_cpu_cfg(env)->debug) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -447,13 +509,15 @@ static RISCVException debug(CPURISCVState *env, int csrno)
|
||||
|
||||
static RISCVException seed(CPURISCVState *env, int csrno)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
if (!cpu->cfg.ext_zkr) {
|
||||
if (!riscv_cpu_cfg(env)->ext_zkr) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (env->debugger) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* With a CSR read-write instruction:
|
||||
* 1) The seed CSR is always available in machine mode as normal.
|
||||
@ -572,7 +636,7 @@ static RISCVException read_vl(CPURISCVState *env, int csrno,
|
||||
|
||||
static int read_vlenb(CPURISCVState *env, int csrno, target_ulong *val)
|
||||
{
|
||||
*val = env_archcpu(env)->cfg.vlen >> 3;
|
||||
*val = riscv_cpu_cfg(env)->vlen >> 3;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -627,7 +691,7 @@ static RISCVException write_vstart(CPURISCVState *env, int csrno,
|
||||
* The vstart CSR is defined to have only enough writable bits
|
||||
* to hold the largest element index, i.e. lg2(VLEN) bits.
|
||||
*/
|
||||
env->vstart = val & ~(~0ULL << ctzl(env_archcpu(env)->cfg.vlen));
|
||||
env->vstart = val & ~(~0ULL << ctzl(riscv_cpu_cfg(env)->vlen));
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -916,54 +980,8 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException sstc(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
bool hmode_check = false;
|
||||
|
||||
if (!cpu->cfg.ext_sstc || !env->rdtime_fn) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (env->priv == PRV_M) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* No need of separate function for rv32 as menvcfg stores both menvcfg
|
||||
* menvcfgh for RV32.
|
||||
*/
|
||||
if (!(get_field(env->mcounteren, COUNTEREN_TM) &&
|
||||
get_field(env->menvcfg, MENVCFG_STCE))) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (riscv_cpu_virt_enabled(env)) {
|
||||
if (!(get_field(env->hcounteren, COUNTEREN_TM) &&
|
||||
get_field(env->henvcfg, HENVCFG_STCE))) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) {
|
||||
hmode_check = true;
|
||||
}
|
||||
|
||||
return hmode_check ? hmode(env, csrno) : smode(env, csrno);
|
||||
}
|
||||
|
||||
static RISCVException sstc_32(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (riscv_cpu_mxl(env) != MXL_RV32) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
return sstc(env, csrno);
|
||||
}
|
||||
|
||||
static RISCVException read_vstimecmp(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->vstimecmp;
|
||||
|
||||
@ -971,7 +989,7 @@ static RISCVException read_vstimecmp(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_vstimecmph(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->vstimecmp >> 32;
|
||||
|
||||
@ -979,7 +997,7 @@ static RISCVException read_vstimecmph(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_vstimecmp(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -996,7 +1014,7 @@ static RISCVException write_vstimecmp(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_vstimecmph(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -1020,7 +1038,7 @@ static RISCVException read_stimecmp(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_stimecmph(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
if (riscv_cpu_virt_enabled(env)) {
|
||||
*val = env->vstimecmp >> 32;
|
||||
@ -1032,7 +1050,7 @@ static RISCVException read_stimecmph(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_stimecmp(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -1055,7 +1073,7 @@ static RISCVException write_stimecmp(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_stimecmph(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -1152,8 +1170,7 @@ static RISCVException write_ignore(CPURISCVState *env, int csrno,
|
||||
static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
*val = cpu->cfg.mvendorid;
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1162,8 +1179,7 @@ static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
|
||||
static RISCVException read_marchid(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
*val = cpu->cfg.marchid;
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1172,8 +1188,7 @@ static RISCVException read_marchid(CPURISCVState *env, int csrno,
|
||||
static RISCVException read_mimpid(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
RISCVCPU *cpu = env_archcpu(env);
|
||||
|
||||
*val = cpu->cfg.mimpid;
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1329,7 +1344,7 @@ static RISCVException read_misa(CPURISCVState *env, int csrno,
|
||||
static RISCVException write_misa(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
{
|
||||
if (!riscv_feature(env, RISCV_FEATURE_MISA)) {
|
||||
if (!riscv_cpu_cfg(env)->misa_w) {
|
||||
/* drop write to misa */
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
@ -1342,7 +1357,8 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
|
||||
|
||||
/* 'E' excludes all other extensions */
|
||||
if (val & RVE) {
|
||||
/* when we support 'E' we can do "val = RVE;" however
|
||||
/*
|
||||
* when we support 'E' we can do "val = RVE;" however
|
||||
* for now we just drop writes if 'E' is present.
|
||||
*/
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1356,15 +1372,13 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
|
||||
/* Mask extensions that are not supported by this hart */
|
||||
val &= env->misa_ext_mask;
|
||||
|
||||
/* Mask extensions that are not supported by QEMU */
|
||||
val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU | RVV);
|
||||
|
||||
/* 'D' depends on 'F', so clear 'D' if 'F' is not present */
|
||||
if ((val & RVD) && !(val & RVF)) {
|
||||
val &= ~RVD;
|
||||
}
|
||||
|
||||
/* Suppress 'C' if next instruction is not aligned
|
||||
/*
|
||||
* Suppress 'C' if next instruction is not aligned
|
||||
* TODO: this should check next_pc
|
||||
*/
|
||||
if ((val & RVC) && (GETPC() & ~3) != 0) {
|
||||
@ -1833,28 +1847,28 @@ static RISCVException write_mscratch(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_mepc(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->mepc;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_mepc(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
env->mepc = val;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException read_mcause(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->mcause;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_mcause(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
env->mcause = val;
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -1876,19 +1890,22 @@ static RISCVException write_mtval(CPURISCVState *env, int csrno,
|
||||
|
||||
/* Execution environment configuration setup */
|
||||
static RISCVException read_menvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->menvcfg;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
RISCVCPUConfig *cfg = &env_archcpu(env)->cfg;
|
||||
uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE;
|
||||
|
||||
if (riscv_cpu_mxl(env) == MXL_RV64) {
|
||||
mask |= MENVCFG_PBMTE | MENVCFG_STCE;
|
||||
mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
|
||||
(cfg->ext_sstc ? MENVCFG_STCE : 0) |
|
||||
(cfg->ext_svadu ? MENVCFG_HADE : 0);
|
||||
}
|
||||
env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
|
||||
|
||||
@ -1896,16 +1913,19 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_menvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->menvcfg >> 32;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = MENVCFG_PBMTE | MENVCFG_STCE;
|
||||
RISCVCPUConfig *cfg = &env_archcpu(env)->cfg;
|
||||
uint64_t mask = (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
|
||||
(cfg->ext_sstc ? MENVCFG_STCE : 0) |
|
||||
(cfg->ext_svadu ? MENVCFG_HADE : 0);
|
||||
uint64_t valh = (uint64_t)val << 32;
|
||||
|
||||
env->menvcfg = (env->menvcfg & ~mask) | (valh & mask);
|
||||
@ -1914,7 +1934,7 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
RISCVException ret;
|
||||
|
||||
@ -1928,7 +1948,7 @@ static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE;
|
||||
RISCVException ret;
|
||||
@ -1943,7 +1963,7 @@ static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
RISCVException ret;
|
||||
|
||||
@ -1952,12 +1972,18 @@ static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = env->henvcfg;
|
||||
/*
|
||||
* henvcfg.pbmte is read_only 0 when menvcfg.pbmte = 0
|
||||
* henvcfg.stce is read_only 0 when menvcfg.stce = 0
|
||||
* henvcfg.hade is read_only 0 when menvcfg.hade = 0
|
||||
*/
|
||||
*val = env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE) |
|
||||
env->menvcfg);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE;
|
||||
RISCVException ret;
|
||||
@ -1968,7 +1994,7 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
if (riscv_cpu_mxl(env) == MXL_RV64) {
|
||||
mask |= HENVCFG_PBMTE | HENVCFG_STCE;
|
||||
mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE);
|
||||
}
|
||||
|
||||
env->henvcfg = (env->henvcfg & ~mask) | (val & mask);
|
||||
@ -1977,7 +2003,7 @@ static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
RISCVException ret;
|
||||
|
||||
@ -1986,14 +2012,16 @@ static RISCVException read_henvcfgh(CPURISCVState *env, int csrno,
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = env->henvcfg >> 32;
|
||||
*val = (env->henvcfg & (~(HENVCFG_PBMTE | HENVCFG_STCE | HENVCFG_HADE) |
|
||||
env->menvcfg)) >> 32;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_henvcfgh(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
uint64_t mask = HENVCFG_PBMTE | HENVCFG_STCE;
|
||||
uint64_t mask = env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE |
|
||||
HENVCFG_HADE);
|
||||
uint64_t valh = (uint64_t)val << 32;
|
||||
RISCVException ret;
|
||||
|
||||
@ -2034,13 +2062,13 @@ static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_mstateen_1_3(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
|
||||
}
|
||||
|
||||
static RISCVException read_mstateenh(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
target_ulong *val)
|
||||
{
|
||||
*val = env->mstateen[csrno - CSR_MSTATEEN0H] >> 32;
|
||||
|
||||
@ -2061,7 +2089,7 @@ static RISCVException write_mstateenh(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
|
||||
|
||||
@ -2069,7 +2097,7 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_mstateenh_1_3(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
|
||||
}
|
||||
@ -2106,7 +2134,7 @@ static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_hstateen_1_3(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
|
||||
}
|
||||
@ -2145,7 +2173,7 @@ static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_hstateenh_1_3(CPURISCVState *env, int csrno,
|
||||
target_ulong new_val)
|
||||
target_ulong new_val)
|
||||
{
|
||||
return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
|
||||
}
|
||||
@ -2624,7 +2652,7 @@ static RISCVException rmw_siph(CPURISCVState *env, int csrno,
|
||||
static RISCVException read_satp(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
|
||||
if (!riscv_cpu_cfg(env)->mmu) {
|
||||
*val = 0;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
@ -2643,7 +2671,7 @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
|
||||
{
|
||||
target_ulong vm, mask;
|
||||
|
||||
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
|
||||
if (!riscv_cpu_cfg(env)->mmu) {
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -3338,30 +3366,18 @@ static RISCVException read_mseccfg(CPURISCVState *env, int csrno,
|
||||
}
|
||||
|
||||
static RISCVException write_mseccfg(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
target_ulong val)
|
||||
{
|
||||
mseccfg_csr_write(env, val);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static bool check_pmp_reg_index(CPURISCVState *env, uint32_t reg_index)
|
||||
{
|
||||
/* TODO: RV128 restriction check */
|
||||
if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static RISCVException read_pmpcfg(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
uint32_t reg_index = csrno - CSR_PMPCFG0;
|
||||
|
||||
if (!check_pmp_reg_index(env, reg_index)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
*val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0);
|
||||
*val = pmpcfg_csr_read(env, reg_index);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -3370,10 +3386,7 @@ static RISCVException write_pmpcfg(CPURISCVState *env, int csrno,
|
||||
{
|
||||
uint32_t reg_index = csrno - CSR_PMPCFG0;
|
||||
|
||||
if (!check_pmp_reg_index(env, reg_index)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val);
|
||||
pmpcfg_csr_write(env, reg_index, val);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
@ -3776,27 +3789,32 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
|
||||
RISCVCPU *cpu)
|
||||
{
|
||||
/* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
|
||||
int read_only = get_field(csrno, 0xC00) == 3;
|
||||
bool read_only = get_field(csrno, 0xC00) == 3;
|
||||
int csr_min_priv = csr_ops[csrno].min_priv_ver;
|
||||
|
||||
/* ensure the CSR extension is enabled. */
|
||||
/* ensure the CSR extension is enabled */
|
||||
if (!cpu->cfg.ext_icsr) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/* privileged spec version check */
|
||||
if (env->priv_ver < csr_min_priv) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/* check predicate */
|
||||
if (!csr_ops[csrno].predicate) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/* read / write check */
|
||||
if (write_mask && read_only) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
/*
|
||||
* The predicate() not only does existence check but also does some
|
||||
* access control check which triggers for example virtual instruction
|
||||
* exception in some cases. When writing read-only CSRs in those cases
|
||||
* illegal instruction exception should be triggered instead of virtual
|
||||
* instruction exception. Hence this comes after the read / write check.
|
||||
*/
|
||||
g_assert(csr_ops[csrno].predicate != NULL);
|
||||
RISCVException ret = csr_ops[csrno].predicate(env, csrno);
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
return ret;
|
||||
|
@ -127,40 +127,6 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert register index number passed by GDB to the correspond
|
||||
* vector CSR number. Vector CSRs are defined after vector registers
|
||||
* in dynamic generated riscv-vector.xml, thus the starting register index
|
||||
* of vector CSRs is 32.
|
||||
* Return 0 if register index number is out of range.
|
||||
*/
|
||||
static int riscv_gdb_vector_csrno(int num_regs)
|
||||
{
|
||||
/*
|
||||
* The order of vector CSRs in the switch case
|
||||
* should match with the order defined in csr_ops[].
|
||||
*/
|
||||
switch (num_regs) {
|
||||
case 32:
|
||||
return CSR_VSTART;
|
||||
case 33:
|
||||
return CSR_VXSAT;
|
||||
case 34:
|
||||
return CSR_VXRM;
|
||||
case 35:
|
||||
return CSR_VCSR;
|
||||
case 36:
|
||||
return CSR_VL;
|
||||
case 37:
|
||||
return CSR_VTYPE;
|
||||
case 38:
|
||||
return CSR_VLENB;
|
||||
default:
|
||||
/* Unknown register. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
|
||||
{
|
||||
uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||
@ -174,19 +140,6 @@ static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int csrno = riscv_gdb_vector_csrno(n);
|
||||
|
||||
if (!csrno) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
target_ulong val = 0;
|
||||
int result = riscv_csrrw_debug(env, csrno, &val, 0, 0);
|
||||
|
||||
if (result == RISCV_EXCP_NONE) {
|
||||
return gdb_get_regl(buf, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -201,19 +154,6 @@ static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||
return vlenb;
|
||||
}
|
||||
|
||||
int csrno = riscv_gdb_vector_csrno(n);
|
||||
|
||||
if (!csrno) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
target_ulong val = ldtul_p(mem_buf);
|
||||
int result = riscv_csrrw_debug(env, csrno, NULL, val, -1);
|
||||
|
||||
if (result == RISCV_EXCP_NONE) {
|
||||
return sizeof(target_ulong);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -280,6 +220,10 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
|
||||
int bitsize = 16 << env->misa_mxl_max;
|
||||
int i;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
env->debugger = true;
|
||||
#endif
|
||||
|
||||
/* Until gdb knows about 128-bit registers */
|
||||
if (bitsize > 64) {
|
||||
bitsize = 64;
|
||||
@ -290,6 +234,9 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
|
||||
g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.csr\">");
|
||||
|
||||
for (i = 0; i < CSR_TABLE_SIZE; i++) {
|
||||
if (env->priv_ver < csr_ops[i].min_priv_ver) {
|
||||
continue;
|
||||
}
|
||||
predicate = csr_ops[i].predicate;
|
||||
if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
|
||||
if (csr_ops[i].name) {
|
||||
@ -305,6 +252,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
|
||||
g_string_append_printf(s, "</feature>");
|
||||
|
||||
cpu->dyn_csr_xml = g_string_free(s, false);
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
env->debugger = false;
|
||||
#endif
|
||||
|
||||
return CSR_TABLE_SIZE;
|
||||
}
|
||||
|
||||
@ -349,21 +301,6 @@ static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
|
||||
num_regs++;
|
||||
}
|
||||
|
||||
/* Define vector CSRs */
|
||||
const char *vector_csrs[7] = {
|
||||
"vstart", "vxsat", "vxrm", "vcsr",
|
||||
"vl", "vtype", "vlenb"
|
||||
};
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
g_string_append_printf(s,
|
||||
"<reg name=\"%s\" bitsize=\"%d\""
|
||||
" regnum=\"%d\" group=\"vector\""
|
||||
" type=\"int\"/>",
|
||||
vector_csrs[i], TARGET_LONG_BITS, base_reg++);
|
||||
num_regs++;
|
||||
}
|
||||
|
||||
g_string_append_printf(s, "</feature>");
|
||||
|
||||
cpu->dyn_vreg_xml = g_string_free(s, false);
|
||||
@ -382,9 +319,9 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
|
||||
32, "riscv-32bit-fpu.xml", 0);
|
||||
}
|
||||
if (env->misa_ext & RVV) {
|
||||
int base_reg = cs->gdb_num_regs;
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_vector, riscv_gdb_set_vector,
|
||||
ricsv_gen_dynamic_vector_xml(cs,
|
||||
cs->gdb_num_regs),
|
||||
ricsv_gen_dynamic_vector_xml(cs, base_reg),
|
||||
"riscv-vector.xml", 0);
|
||||
}
|
||||
switch (env->misa_mxl_max) {
|
||||
@ -403,7 +340,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
|
||||
riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs),
|
||||
"riscv-csr.xml", 0);
|
||||
if (cpu->cfg.ext_icsr) {
|
||||
int base_reg = cs->gdb_num_regs;
|
||||
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
|
||||
riscv_gen_dynamic_csr_xml(cs, base_reg),
|
||||
"riscv-csr.xml", 0);
|
||||
}
|
||||
}
|
||||
|
@ -890,3 +890,7 @@ sm3p1 00 01000 01001 ..... 001 ..... 0010011 @r2
|
||||
# *** RV32 Zksed Standard Extension ***
|
||||
sm4ed .. 11000 ..... ..... 000 ..... 0110011 @k_aes
|
||||
sm4ks .. 11010 ..... ..... 000 ..... 0110011 @k_aes
|
||||
|
||||
# *** RV32 Zicond Standard Extension ***
|
||||
czero_eqz 0000111 ..... ..... 101 ..... 0110011 @r
|
||||
czero_nez 0000111 ..... ..... 111 ..... 0110011 @r
|
||||
|
@ -40,10 +40,11 @@ static bool require_rvf(DisasContext *s)
|
||||
|
||||
switch (s->sew) {
|
||||
case MO_16:
|
||||
return s->cfg_ptr->ext_zvfh;
|
||||
case MO_32:
|
||||
return has_ext(s, RVF);
|
||||
return s->cfg_ptr->ext_zve32f;
|
||||
case MO_64:
|
||||
return has_ext(s, RVD);
|
||||
return s->cfg_ptr->ext_zve64d;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -57,57 +58,32 @@ static bool require_scale_rvf(DisasContext *s)
|
||||
|
||||
switch (s->sew) {
|
||||
case MO_8:
|
||||
return s->cfg_ptr->ext_zvfh;
|
||||
case MO_16:
|
||||
return has_ext(s, RVF);
|
||||
return s->cfg_ptr->ext_zve32f;
|
||||
case MO_32:
|
||||
return has_ext(s, RVD);
|
||||
return s->cfg_ptr->ext_zve64d;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool require_zve32f(DisasContext *s)
|
||||
static bool require_scale_rvfmin(DisasContext *s)
|
||||
{
|
||||
/* RVV + Zve32f = RVV. */
|
||||
if (has_ext(s, RVV)) {
|
||||
return true;
|
||||
if (s->mstatus_fs == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Zve32f doesn't support FP64. (Section 18.2) */
|
||||
return s->cfg_ptr->ext_zve32f ? s->sew <= MO_32 : true;
|
||||
}
|
||||
|
||||
static bool require_scale_zve32f(DisasContext *s)
|
||||
{
|
||||
/* RVV + Zve32f = RVV. */
|
||||
if (has_ext(s, RVV)) {
|
||||
return true;
|
||||
switch (s->sew) {
|
||||
case MO_8:
|
||||
return s->cfg_ptr->ext_zvfhmin;
|
||||
case MO_16:
|
||||
return s->cfg_ptr->ext_zve32f;
|
||||
case MO_32:
|
||||
return s->cfg_ptr->ext_zve64d;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Zve32f doesn't support FP64. (Section 18.2) */
|
||||
return s->cfg_ptr->ext_zve64f ? s->sew <= MO_16 : true;
|
||||
}
|
||||
|
||||
static bool require_zve64f(DisasContext *s)
|
||||
{
|
||||
/* RVV + Zve64f = RVV. */
|
||||
if (has_ext(s, RVV)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Zve64f doesn't support FP64. (Section 18.2) */
|
||||
return s->cfg_ptr->ext_zve64f ? s->sew <= MO_32 : true;
|
||||
}
|
||||
|
||||
static bool require_scale_zve64f(DisasContext *s)
|
||||
{
|
||||
/* RVV + Zve64f = RVV. */
|
||||
if (has_ext(s, RVV)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Zve64f doesn't support FP64. (Section 18.2) */
|
||||
return s->cfg_ptr->ext_zve64f ? s->sew <= MO_16 : true;
|
||||
}
|
||||
|
||||
/* Destination vector register group cannot overlap source mask register. */
|
||||
@ -173,9 +149,7 @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2)
|
||||
{
|
||||
TCGv s1, dst;
|
||||
|
||||
if (!require_rvv(s) ||
|
||||
!(has_ext(s, RVV) || s->cfg_ptr->ext_zve32f ||
|
||||
s->cfg_ptr->ext_zve64f)) {
|
||||
if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -210,9 +184,7 @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2)
|
||||
{
|
||||
TCGv dst;
|
||||
|
||||
if (!require_rvv(s) ||
|
||||
!(has_ext(s, RVV) || s->cfg_ptr->ext_zve32f ||
|
||||
s->cfg_ptr->ext_zve64f)) {
|
||||
if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -315,13 +287,12 @@ static bool vext_check_st_index(DisasContext *s, int vd, int vs2, int nf,
|
||||
require_nf(vd, nf, s->lmul);
|
||||
|
||||
/*
|
||||
* All Zve* extensions support all vector load and store instructions,
|
||||
* except Zve64* extensions do not support EEW=64 for index values
|
||||
* when XLEN=32. (Section 18.2)
|
||||
* V extension supports all vector load and store instructions,
|
||||
* except V extension does not support EEW=64 for index values
|
||||
* when XLEN=32. (Section 18.3)
|
||||
*/
|
||||
if (get_xl(s) == MXL_RV32) {
|
||||
ret &= (!has_ext(s, RVV) &&
|
||||
s->cfg_ptr->ext_zve64f ? eew != MO_64 : true);
|
||||
ret &= (eew != MO_64);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -2027,8 +1998,7 @@ static bool vmulh_vv_check(DisasContext *s, arg_rmrr *a)
|
||||
* are not included for EEW=64 in Zve64*. (Section 18.2)
|
||||
*/
|
||||
return opivv_check(s, a) &&
|
||||
(!has_ext(s, RVV) &&
|
||||
s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
|
||||
(!has_ext(s, RVV) ? s->sew != MO_64 : true);
|
||||
}
|
||||
|
||||
static bool vmulh_vx_check(DisasContext *s, arg_rmrr *a)
|
||||
@ -2041,8 +2011,7 @@ static bool vmulh_vx_check(DisasContext *s, arg_rmrr *a)
|
||||
* are not included for EEW=64 in Zve64*. (Section 18.2)
|
||||
*/
|
||||
return opivx_check(s, a) &&
|
||||
(!has_ext(s, RVV) &&
|
||||
s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
|
||||
(!has_ext(s, RVV) ? s->sew != MO_64 : true);
|
||||
}
|
||||
|
||||
GEN_OPIVV_GVEC_TRANS(vmul_vv, mul)
|
||||
@ -2259,8 +2228,7 @@ static bool vsmul_vv_check(DisasContext *s, arg_rmrr *a)
|
||||
* for EEW=64 in Zve64*. (Section 18.2)
|
||||
*/
|
||||
return opivv_check(s, a) &&
|
||||
(!has_ext(s, RVV) &&
|
||||
s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
|
||||
(!has_ext(s, RVV) ? s->sew != MO_64 : true);
|
||||
}
|
||||
|
||||
static bool vsmul_vx_check(DisasContext *s, arg_rmrr *a)
|
||||
@ -2271,8 +2239,7 @@ static bool vsmul_vx_check(DisasContext *s, arg_rmrr *a)
|
||||
* for EEW=64 in Zve64*. (Section 18.2)
|
||||
*/
|
||||
return opivx_check(s, a) &&
|
||||
(!has_ext(s, RVV) &&
|
||||
s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
|
||||
(!has_ext(s, RVV) ? s->sew != MO_64 : true);
|
||||
}
|
||||
|
||||
GEN_OPIVV_TRANS(vsmul_vv, vsmul_vv_check)
|
||||
@ -2335,9 +2302,7 @@ static bool opfvv_check(DisasContext *s, arg_rmrr *a)
|
||||
return require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
/* OPFVV without GVEC IR */
|
||||
@ -2425,9 +2390,7 @@ static bool opfvf_check(DisasContext *s, arg_rmrr *a)
|
||||
return require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_ss(s, a->rd, a->rs2, a->vm) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
vext_check_ss(s, a->rd, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
/* OPFVF without GVEC IR */
|
||||
@ -2465,9 +2428,7 @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
require_scale_rvf(s) &&
|
||||
(s->sew != MO_8) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm) &&
|
||||
require_scale_zve32f(s) &&
|
||||
require_scale_zve64f(s);
|
||||
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
/* OPFVV with WIDEN */
|
||||
@ -2510,9 +2471,7 @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
require_scale_rvf(s) &&
|
||||
(s->sew != MO_8) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_ds(s, a->rd, a->rs2, a->vm) &&
|
||||
require_scale_zve32f(s) &&
|
||||
require_scale_zve64f(s);
|
||||
vext_check_ds(s, a->rd, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
/* OPFVF with WIDEN */
|
||||
@ -2544,9 +2503,7 @@ static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
require_scale_rvf(s) &&
|
||||
(s->sew != MO_8) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm) &&
|
||||
require_scale_zve32f(s) &&
|
||||
require_scale_zve64f(s);
|
||||
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
/* WIDEN OPFVV with WIDEN */
|
||||
@ -2589,9 +2546,7 @@ static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
require_scale_rvf(s) &&
|
||||
(s->sew != MO_8) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_dd(s, a->rd, a->rs2, a->vm) &&
|
||||
require_scale_zve32f(s) &&
|
||||
require_scale_zve64f(s);
|
||||
vext_check_dd(s, a->rd, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
/* WIDEN OPFVF with WIDEN */
|
||||
@ -2668,9 +2623,7 @@ static bool opfv_check(DisasContext *s, arg_rmr *a)
|
||||
require_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
/* OPFV instructions ignore vs1 check */
|
||||
vext_check_ss(s, a->rd, a->rs2, a->vm) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
vext_check_ss(s, a->rd, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
static bool do_opfv(DisasContext *s, arg_rmr *a,
|
||||
@ -2735,9 +2688,7 @@ static bool opfvv_cmp_check(DisasContext *s, arg_rmrr *a)
|
||||
return require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_mss(s, a->rd, a->rs1, a->rs2) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
vext_check_mss(s, a->rd, a->rs1, a->rs2);
|
||||
}
|
||||
|
||||
GEN_OPFVV_TRANS(vmfeq_vv, opfvv_cmp_check)
|
||||
@ -2750,9 +2701,7 @@ static bool opfvf_cmp_check(DisasContext *s, arg_rmrr *a)
|
||||
return require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_ms(s, a->rd, a->rs2) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
vext_check_ms(s, a->rd, a->rs2);
|
||||
}
|
||||
|
||||
GEN_OPFVF_TRANS(vmfeq_vf, opfvf_cmp_check)
|
||||
@ -2773,9 +2722,7 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
|
||||
if (require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
require_align(a->rd, s->lmul) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s)) {
|
||||
require_align(a->rd, s->lmul)) {
|
||||
gen_set_rm(s, RISCV_FRM_DYN);
|
||||
|
||||
TCGv_i64 t1;
|
||||
@ -2860,18 +2807,14 @@ static bool opfv_widen_check(DisasContext *s, arg_rmr *a)
|
||||
static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
|
||||
{
|
||||
return opfv_widen_check(s, a) &&
|
||||
require_rvf(s) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
require_rvf(s);
|
||||
}
|
||||
|
||||
static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
|
||||
{
|
||||
return opfv_widen_check(s, a) &&
|
||||
require_scale_rvf(s) &&
|
||||
(s->sew != MO_8) &&
|
||||
require_scale_zve32f(s) &&
|
||||
require_scale_zve64f(s);
|
||||
require_scale_rvfmin(s) &&
|
||||
(s->sew != MO_8);
|
||||
}
|
||||
|
||||
#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \
|
||||
@ -2922,9 +2865,7 @@ static bool opfxv_widen_check(DisasContext *s, arg_rmr *a)
|
||||
require_scale_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
/* OPFV widening instructions ignore vs1 check */
|
||||
vext_check_ds(s, a->rd, a->rs2, a->vm) &&
|
||||
require_scale_zve32f(s) &&
|
||||
require_scale_zve64f(s);
|
||||
vext_check_ds(s, a->rd, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
#define GEN_OPFXV_WIDEN_TRANS(NAME) \
|
||||
@ -2979,18 +2920,21 @@ static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
|
||||
{
|
||||
return opfv_narrow_check(s, a) &&
|
||||
require_rvf(s) &&
|
||||
(s->sew != MO_64) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
(s->sew != MO_64);
|
||||
}
|
||||
|
||||
static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
|
||||
{
|
||||
return opfv_narrow_check(s, a) &&
|
||||
require_scale_rvfmin(s) &&
|
||||
(s->sew != MO_8);
|
||||
}
|
||||
|
||||
static bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
|
||||
{
|
||||
return opfv_narrow_check(s, a) &&
|
||||
require_scale_rvf(s) &&
|
||||
(s->sew != MO_8) &&
|
||||
require_scale_zve32f(s) &&
|
||||
require_scale_zve64f(s);
|
||||
(s->sew != MO_8);
|
||||
}
|
||||
|
||||
#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM) \
|
||||
@ -3030,7 +2974,7 @@ GEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, opfxv_narrow_check, vfncvt_f_x_w,
|
||||
GEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
|
||||
RISCV_FRM_DYN)
|
||||
/* Reuse the helper function from vfncvt.f.f.w */
|
||||
GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
|
||||
GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, opffv_rod_narrow_check, vfncvt_f_f_w,
|
||||
RISCV_FRM_ROD)
|
||||
|
||||
static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a)
|
||||
@ -3039,9 +2983,7 @@ static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a)
|
||||
require_scale_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
/* OPFV narrowing instructions ignore vs1 check */
|
||||
vext_check_sd(s, a->rd, a->rs2, a->vm) &&
|
||||
require_scale_zve32f(s) &&
|
||||
require_scale_zve64f(s);
|
||||
vext_check_sd(s, a->rd, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
#define GEN_OPXFV_NARROW_TRANS(NAME, HELPER, FRM) \
|
||||
@ -3115,9 +3057,7 @@ GEN_OPIVV_WIDEN_TRANS(vwredsumu_vs, reduction_widen_check)
|
||||
static bool freduction_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return reduction_check(s, a) &&
|
||||
require_rvf(s) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
require_rvf(s);
|
||||
}
|
||||
|
||||
GEN_OPFVV_TRANS(vfredusum_vs, freduction_check)
|
||||
@ -3544,9 +3484,7 @@ static bool trans_vfmv_f_s(DisasContext *s, arg_vfmv_f_s *a)
|
||||
{
|
||||
if (require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s)) {
|
||||
vext_check_isa_ill(s)) {
|
||||
gen_set_rm(s, RISCV_FRM_DYN);
|
||||
|
||||
unsigned int ofs = (8 << s->sew);
|
||||
@ -3572,9 +3510,7 @@ static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a)
|
||||
{
|
||||
if (require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s)) {
|
||||
vext_check_isa_ill(s)) {
|
||||
gen_set_rm(s, RISCV_FRM_DYN);
|
||||
|
||||
/* The instructions ignore LMUL and vector register group. */
|
||||
@ -3625,17 +3561,13 @@ GEN_OPIVI_TRANS(vslidedown_vi, IMM_ZX, vslidedown_vx, slidedown_check)
|
||||
static bool fslideup_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return slideup_check(s, a) &&
|
||||
require_rvf(s) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
require_rvf(s);
|
||||
}
|
||||
|
||||
static bool fslidedown_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return slidedown_check(s, a) &&
|
||||
require_rvf(s) &&
|
||||
require_zve32f(s) &&
|
||||
require_zve64f(s);
|
||||
require_rvf(s);
|
||||
}
|
||||
|
||||
GEN_OPFVF_TRANS(vfslide1up_vf, fslideup_check)
|
||||
|
@ -28,15 +28,14 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define REQUIRE_ZFH_OR_ZFHMIN(ctx) do { \
|
||||
if (!(ctx->cfg_ptr->ext_zfh || ctx->cfg_ptr->ext_zfhmin)) { \
|
||||
#define REQUIRE_ZFHMIN(ctx) do { \
|
||||
if (!ctx->cfg_ptr->ext_zfhmin) { \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx) do { \
|
||||
if (!(ctx->cfg_ptr->ext_zfh || ctx->cfg_ptr->ext_zfhmin || \
|
||||
ctx->cfg_ptr->ext_zhinx || ctx->cfg_ptr->ext_zhinxmin)) { \
|
||||
#define REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx) do { \
|
||||
if (!(ctx->cfg_ptr->ext_zfhmin || ctx->cfg_ptr->ext_zhinxmin)) { \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
@ -47,7 +46,7 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a)
|
||||
TCGv t0;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFH_OR_ZFHMIN(ctx);
|
||||
REQUIRE_ZFHMIN(ctx);
|
||||
|
||||
decode_save_opc(ctx);
|
||||
t0 = get_gpr(ctx, a->rs1, EXT_NONE);
|
||||
@ -70,7 +69,7 @@ static bool trans_fsh(DisasContext *ctx, arg_fsh *a)
|
||||
TCGv t0;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFH_OR_ZFHMIN(ctx);
|
||||
REQUIRE_ZFHMIN(ctx);
|
||||
|
||||
decode_save_opc(ctx);
|
||||
t0 = get_gpr(ctx, a->rs1, EXT_NONE);
|
||||
@ -401,7 +400,7 @@ static bool trans_fmax_h(DisasContext *ctx, arg_fmax_h *a)
|
||||
static bool trans_fcvt_s_h(DisasContext *ctx, arg_fcvt_s_h *a)
|
||||
{
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx);
|
||||
REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
|
||||
|
||||
TCGv_i64 dest = dest_fpr(ctx, a->rd);
|
||||
TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
|
||||
@ -418,7 +417,7 @@ static bool trans_fcvt_s_h(DisasContext *ctx, arg_fcvt_s_h *a)
|
||||
static bool trans_fcvt_d_h(DisasContext *ctx, arg_fcvt_d_h *a)
|
||||
{
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx);
|
||||
REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
|
||||
REQUIRE_ZDINX_OR_D(ctx);
|
||||
|
||||
TCGv_i64 dest = dest_fpr(ctx, a->rd);
|
||||
@ -436,7 +435,7 @@ static bool trans_fcvt_d_h(DisasContext *ctx, arg_fcvt_d_h *a)
|
||||
static bool trans_fcvt_h_s(DisasContext *ctx, arg_fcvt_h_s *a)
|
||||
{
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx);
|
||||
REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
|
||||
|
||||
TCGv_i64 dest = dest_fpr(ctx, a->rd);
|
||||
TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
|
||||
@ -452,7 +451,7 @@ static bool trans_fcvt_h_s(DisasContext *ctx, arg_fcvt_h_s *a)
|
||||
static bool trans_fcvt_h_d(DisasContext *ctx, arg_fcvt_h_d *a)
|
||||
{
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx);
|
||||
REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
|
||||
REQUIRE_ZDINX_OR_D(ctx);
|
||||
|
||||
TCGv_i64 dest = dest_fpr(ctx, a->rd);
|
||||
@ -585,7 +584,7 @@ static bool trans_fcvt_h_wu(DisasContext *ctx, arg_fcvt_h_wu *a)
|
||||
static bool trans_fmv_x_h(DisasContext *ctx, arg_fmv_x_h *a)
|
||||
{
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFH_OR_ZFHMIN(ctx);
|
||||
REQUIRE_ZFHMIN(ctx);
|
||||
|
||||
TCGv dest = dest_gpr(ctx, a->rd);
|
||||
|
||||
@ -605,7 +604,7 @@ static bool trans_fmv_x_h(DisasContext *ctx, arg_fmv_x_h *a)
|
||||
static bool trans_fmv_h_x(DisasContext *ctx, arg_fmv_h_x *a)
|
||||
{
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFH_OR_ZFHMIN(ctx);
|
||||
REQUIRE_ZFHMIN(ctx);
|
||||
|
||||
TCGv t0 = get_gpr(ctx, a->rs1, EXT_ZERO);
|
||||
|
||||
|
49
target/riscv/insn_trans/trans_rvzicond.c.inc
Normal file
49
target/riscv/insn_trans/trans_rvzicond.c.inc
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* RISC-V translation routines for the Zicond Standard Extension.
|
||||
*
|
||||
* Copyright (c) 2020-2023 PLCT Lab
|
||||
*
|
||||
* 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_ZICOND(ctx) do { \
|
||||
if (!ctx->cfg_ptr->ext_zicond) { \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static bool trans_czero_eqz(DisasContext *ctx, arg_czero_eqz *a)
|
||||
{
|
||||
REQUIRE_ZICOND(ctx);
|
||||
|
||||
TCGv dest = dest_gpr(ctx, a->rd);
|
||||
TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
|
||||
TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
|
||||
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, ctx->zero, ctx->zero, src1);
|
||||
gen_set_gpr(ctx, a->rd, dest);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_czero_nez(DisasContext *ctx, arg_czero_nez *a)
|
||||
{
|
||||
REQUIRE_ZICOND(ctx);
|
||||
|
||||
TCGv dest = dest_gpr(ctx, a->rd);
|
||||
TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
|
||||
TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
|
||||
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, ctx->zero, ctx->zero, src1);
|
||||
gen_set_gpr(ctx, a->rd, dest);
|
||||
return true;
|
||||
}
|
@ -980,10 +980,6 @@ static bool trans_th_lwud(DisasContext *ctx, arg_th_pair *a)
|
||||
static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
|
||||
int shamt)
|
||||
{
|
||||
if (a->rs == a->rd1 || a->rs == a->rd2 || a->rd1 == a->rd2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TCGv data1 = get_gpr(ctx, a->rd1, EXT_NONE);
|
||||
TCGv data2 = get_gpr(ctx, a->rd2, EXT_NONE);
|
||||
TCGv addr1 = tcg_temp_new();
|
||||
|
@ -27,9 +27,8 @@
|
||||
static bool pmp_needed(void *opaque)
|
||||
{
|
||||
RISCVCPU *cpu = opaque;
|
||||
CPURISCVState *env = &cpu->env;
|
||||
|
||||
return riscv_feature(env, RISCV_FEATURE_PMP);
|
||||
return cpu->cfg.pmp;
|
||||
}
|
||||
|
||||
static int pmp_post_load(void *opaque, int version_id)
|
||||
@ -226,9 +225,8 @@ static const VMStateDescription vmstate_kvmtimer = {
|
||||
static bool debug_needed(void *opaque)
|
||||
{
|
||||
RISCVCPU *cpu = opaque;
|
||||
CPURISCVState *env = &cpu->env;
|
||||
|
||||
return riscv_feature(env, RISCV_FEATURE_DEBUG);
|
||||
return cpu->cfg.debug;
|
||||
}
|
||||
|
||||
static int debug_post_load(void *opaque, int version_id)
|
||||
@ -333,8 +331,8 @@ static const VMStateDescription vmstate_pmu_ctr_state = {
|
||||
|
||||
const VMStateDescription vmstate_riscv_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 6,
|
||||
.minimum_version_id = 6,
|
||||
.version_id = 7,
|
||||
.minimum_version_id = 7,
|
||||
.post_load = riscv_cpu_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
|
||||
@ -353,7 +351,6 @@ const VMStateDescription vmstate_riscv_cpu = {
|
||||
VMSTATE_UINT32(env.misa_ext, RISCVCPU),
|
||||
VMSTATE_UINT32(env.misa_mxl_max, RISCVCPU),
|
||||
VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU),
|
||||
VMSTATE_UINT32(env.features, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.priv, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.virt, RISCVCPU),
|
||||
VMSTATE_UINT64(env.resetvec, RISCVCPU),
|
||||
|
@ -218,7 +218,7 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
|
||||
if (!riscv_cpu_cfg(env)->mmu) {
|
||||
monitor_printf(mon, "S-mode MMU unavailable\n");
|
||||
return;
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ target_ulong helper_mret(CPURISCVState *env)
|
||||
uint64_t mstatus = env->mstatus;
|
||||
target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
|
||||
|
||||
if (riscv_feature(env, RISCV_FEATURE_PMP) &&
|
||||
if (riscv_cpu_cfg(env)->pmp &&
|
||||
!pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
|
||||
riscv_raise_exception(env, RISCV_EXCP_INST_ACCESS_FAULT, GETPC());
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ static void pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
|
||||
if (pmp_index < MAX_RISCV_PMPS) {
|
||||
bool locked = true;
|
||||
|
||||
if (riscv_feature(env, RISCV_FEATURE_EPMP)) {
|
||||
if (riscv_cpu_cfg(env)->epmp) {
|
||||
/* mseccfg.RLB is set */
|
||||
if (MSECCFG_RLB_ISSET(env)) {
|
||||
locked = false;
|
||||
@ -239,7 +239,7 @@ static bool pmp_hart_has_privs_default(CPURISCVState *env, target_ulong addr,
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (riscv_feature(env, RISCV_FEATURE_EPMP)) {
|
||||
if (riscv_cpu_cfg(env)->epmp) {
|
||||
if (MSECCFG_MMWP_ISSET(env)) {
|
||||
/*
|
||||
* The Machine Mode Whitelist Policy (mseccfg.MMWP) is set
|
||||
@ -265,7 +265,7 @@ static bool pmp_hart_has_privs_default(CPURISCVState *env, target_ulong addr,
|
||||
}
|
||||
}
|
||||
|
||||
if ((!riscv_feature(env, RISCV_FEATURE_PMP)) || (mode == PRV_M)) {
|
||||
if (!riscv_cpu_cfg(env)->pmp || (mode == PRV_M)) {
|
||||
/*
|
||||
* Privileged spec v1.10 states if HW doesn't implement any PMP entry
|
||||
* or no PMP entry matches an M-Mode access, the access succeeds.
|
||||
@ -315,7 +315,7 @@ int pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
if (riscv_feature(env, RISCV_FEATURE_MMU)) {
|
||||
if (riscv_cpu_cfg(env)->mmu) {
|
||||
/*
|
||||
* If size is unknown (0), assume that all bytes
|
||||
* from addr to the end of the page will be accessed.
|
||||
|
@ -1103,6 +1103,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
|
||||
#include "insn_trans/trans_rvh.c.inc"
|
||||
#include "insn_trans/trans_rvv.c.inc"
|
||||
#include "insn_trans/trans_rvb.c.inc"
|
||||
#include "insn_trans/trans_rvzicond.c.inc"
|
||||
#include "insn_trans/trans_rvzawrs.c.inc"
|
||||
#include "insn_trans/trans_rvzfh.c.inc"
|
||||
#include "insn_trans/trans_rvk.c.inc"
|
||||
@ -1261,7 +1262,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||
uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
|
||||
int len = insn_len(next_insn);
|
||||
|
||||
if (!is_same_page(&ctx->base, ctx->base.pc_next + len)) {
|
||||
if (!is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
|
||||
ctx->base.is_jmp = DISAS_TOO_MANY;
|
||||
}
|
||||
}
|
||||
|
@ -267,6 +267,28 @@ GEN_VEXT_ST_ELEM(ste_h, int16_t, H2, stw)
|
||||
GEN_VEXT_ST_ELEM(ste_w, int32_t, H4, stl)
|
||||
GEN_VEXT_ST_ELEM(ste_d, int64_t, H8, stq)
|
||||
|
||||
static void vext_set_tail_elems_1s(CPURISCVState *env, target_ulong vl,
|
||||
void *vd, uint32_t desc, uint32_t nf,
|
||||
uint32_t esz, uint32_t max_elems)
|
||||
{
|
||||
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
|
||||
uint32_t vlenb = riscv_cpu_cfg(env)->vlen >> 3;
|
||||
uint32_t vta = vext_vta(desc);
|
||||
uint32_t registers_used;
|
||||
int k;
|
||||
|
||||
for (k = 0; k < nf; ++k) {
|
||||
vext_set_elems_1s(vd, vta, (k * max_elems + vl) * esz,
|
||||
(k * max_elems + max_elems) * esz);
|
||||
}
|
||||
|
||||
if (nf * max_elems % total_elems != 0) {
|
||||
registers_used = ((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
|
||||
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
|
||||
registers_used * vlenb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*** stride: access vector element from strided memory
|
||||
*/
|
||||
@ -281,8 +303,6 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
|
||||
uint32_t nf = vext_nf(desc);
|
||||
uint32_t max_elems = vext_max_elems(desc, log2_esz);
|
||||
uint32_t esz = 1 << log2_esz;
|
||||
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
|
||||
uint32_t vta = vext_vta(desc);
|
||||
uint32_t vma = vext_vma(desc);
|
||||
|
||||
for (i = env->vstart; i < env->vl; i++, env->vstart++) {
|
||||
@ -301,18 +321,8 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
|
||||
}
|
||||
}
|
||||
env->vstart = 0;
|
||||
/* set tail elements to 1s */
|
||||
for (k = 0; k < nf; ++k) {
|
||||
vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
|
||||
(k * max_elems + max_elems) * esz);
|
||||
}
|
||||
if (nf * max_elems % total_elems != 0) {
|
||||
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||
uint32_t registers_used =
|
||||
((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
|
||||
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
|
||||
registers_used * vlenb);
|
||||
}
|
||||
|
||||
vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
|
||||
}
|
||||
|
||||
#define GEN_VEXT_LD_STRIDE(NAME, ETYPE, LOAD_FN) \
|
||||
@ -359,8 +369,6 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
|
||||
uint32_t nf = vext_nf(desc);
|
||||
uint32_t max_elems = vext_max_elems(desc, log2_esz);
|
||||
uint32_t esz = 1 << log2_esz;
|
||||
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
|
||||
uint32_t vta = vext_vta(desc);
|
||||
|
||||
/* load bytes from guest memory */
|
||||
for (i = env->vstart; i < evl; i++, env->vstart++) {
|
||||
@ -372,18 +380,8 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
|
||||
}
|
||||
}
|
||||
env->vstart = 0;
|
||||
/* set tail elements to 1s */
|
||||
for (k = 0; k < nf; ++k) {
|
||||
vext_set_elems_1s(vd, vta, (k * max_elems + evl) * esz,
|
||||
(k * max_elems + max_elems) * esz);
|
||||
}
|
||||
if (nf * max_elems % total_elems != 0) {
|
||||
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||
uint32_t registers_used =
|
||||
((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
|
||||
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
|
||||
registers_used * vlenb);
|
||||
}
|
||||
|
||||
vext_set_tail_elems_1s(env, evl, vd, desc, nf, esz, max_elems);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -484,8 +482,6 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
|
||||
uint32_t vm = vext_vm(desc);
|
||||
uint32_t max_elems = vext_max_elems(desc, log2_esz);
|
||||
uint32_t esz = 1 << log2_esz;
|
||||
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
|
||||
uint32_t vta = vext_vta(desc);
|
||||
uint32_t vma = vext_vma(desc);
|
||||
|
||||
/* load bytes from guest memory */
|
||||
@ -505,18 +501,8 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
|
||||
}
|
||||
}
|
||||
env->vstart = 0;
|
||||
/* set tail elements to 1s */
|
||||
for (k = 0; k < nf; ++k) {
|
||||
vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
|
||||
(k * max_elems + max_elems) * esz);
|
||||
}
|
||||
if (nf * max_elems % total_elems != 0) {
|
||||
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||
uint32_t registers_used =
|
||||
((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
|
||||
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
|
||||
registers_used * vlenb);
|
||||
}
|
||||
|
||||
vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
|
||||
}
|
||||
|
||||
#define GEN_VEXT_LD_INDEX(NAME, ETYPE, INDEX_FN, LOAD_FN) \
|
||||
@ -585,8 +571,6 @@ vext_ldff(void *vd, void *v0, target_ulong base,
|
||||
uint32_t vm = vext_vm(desc);
|
||||
uint32_t max_elems = vext_max_elems(desc, log2_esz);
|
||||
uint32_t esz = 1 << log2_esz;
|
||||
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
|
||||
uint32_t vta = vext_vta(desc);
|
||||
uint32_t vma = vext_vma(desc);
|
||||
target_ulong addr, offset, remain;
|
||||
|
||||
@ -647,18 +631,8 @@ ProbeSuccess:
|
||||
}
|
||||
}
|
||||
env->vstart = 0;
|
||||
/* set tail elements to 1s */
|
||||
for (k = 0; k < nf; ++k) {
|
||||
vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
|
||||
(k * max_elems + max_elems) * esz);
|
||||
}
|
||||
if (nf * max_elems % total_elems != 0) {
|
||||
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||
uint32_t registers_used =
|
||||
((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
|
||||
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
|
||||
registers_used * vlenb);
|
||||
}
|
||||
|
||||
vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
|
||||
}
|
||||
|
||||
#define GEN_VEXT_LDFF(NAME, ETYPE, LOAD_FN) \
|
||||
@ -697,7 +671,7 @@ vext_ldst_whole(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
|
||||
{
|
||||
uint32_t i, k, off, pos;
|
||||
uint32_t nf = vext_nf(desc);
|
||||
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||
uint32_t vlenb = riscv_cpu_cfg(env)->vlen >> 3;
|
||||
uint32_t max_elems = vlenb >> log2_esz;
|
||||
|
||||
k = env->vstart / max_elems;
|
||||
@ -1167,7 +1141,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
|
||||
{ \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t vm = vext_vm(desc); \
|
||||
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
|
||||
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
|
||||
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
|
||||
uint32_t i; \
|
||||
\
|
||||
@ -1203,7 +1177,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
|
||||
{ \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t vm = vext_vm(desc); \
|
||||
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
|
||||
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
|
||||
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
|
||||
uint32_t i; \
|
||||
\
|
||||
@ -1402,7 +1376,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
|
||||
{ \
|
||||
uint32_t vm = vext_vm(desc); \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
|
||||
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
|
||||
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
|
||||
uint32_t vma = vext_vma(desc); \
|
||||
uint32_t i; \
|
||||
@ -1465,7 +1439,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
|
||||
{ \
|
||||
uint32_t vm = vext_vm(desc); \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
|
||||
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
|
||||
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
|
||||
uint32_t vma = vext_vma(desc); \
|
||||
uint32_t i; \
|
||||
@ -4178,7 +4152,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
|
||||
{ \
|
||||
uint32_t vm = vext_vm(desc); \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
|
||||
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
|
||||
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
|
||||
uint32_t vma = vext_vma(desc); \
|
||||
uint32_t i; \
|
||||
@ -4216,7 +4190,7 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
|
||||
{ \
|
||||
uint32_t vm = vext_vm(desc); \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
|
||||
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
|
||||
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
|
||||
uint32_t vma = vext_vma(desc); \
|
||||
uint32_t i; \
|
||||
@ -4747,7 +4721,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \
|
||||
uint32_t desc) \
|
||||
{ \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
|
||||
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
|
||||
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
|
||||
uint32_t i; \
|
||||
int a, b; \
|
||||
@ -4834,7 +4808,7 @@ static void vmsetm(void *vd, void *v0, void *vs2, CPURISCVState *env,
|
||||
{
|
||||
uint32_t vm = vext_vm(desc);
|
||||
uint32_t vl = env->vl;
|
||||
uint32_t total_elems = env_archcpu(env)->cfg.vlen;
|
||||
uint32_t total_elems = riscv_cpu_cfg(env)->vlen;
|
||||
uint32_t vta_all_1s = vext_vta_all_1s(desc);
|
||||
uint32_t vma = vext_vma(desc);
|
||||
int i;
|
||||
|
Loading…
Reference in New Issue
Block a user