mirror of https://gitee.com/openkylin/qemu.git
The first RISC-V PR for the 5.2 window.
This includes: - NaNBox fixes - Vector extension improvements - a L2 cache controller - PMP fixes - Upgrade to OpenSBI v0.8 and the generic platform - Fixes for the Ibex PLIC -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAl9Ar0oACgkQIeENKd+X cFSxZQgAohfo4YEv8i74anCsArSMacyRcZj7gPb3CyHaJcKXgBjSvyWtAbtMVX6n sVXLPE1u7jSgLqEYDqZHgqnTY5CRIkEF1F8h8l+Sz9W7InDLfYchbkNHTQ2FYaXj MnGBCHlkoOXawWKmubQIpVSrb3qMw3lzO+sglAwyut+eqao4uGBf8C4aBDRBs9Ks FLq4cKajAnzH7LjkQuj4YH2N3bj2WsBm1yt/B8NaYHBYwoyV/NJGfK/3yjBnqfGb mZWLXncNiikoVR1cJXTz+mTfRs7UMtsSUkdBSsyMUTDPBqfQrR7ABxxu0SzKd3+N xF9DS9qPk9aQlsAvqNP4N14rnS1I+g== =RJ3z -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20200821-1' into staging The first RISC-V PR for the 5.2 window. This includes: - NaNBox fixes - Vector extension improvements - a L2 cache controller - PMP fixes - Upgrade to OpenSBI v0.8 and the generic platform - Fixes for the Ibex PLIC # gpg: Signature made Sat 22 Aug 2020 06:38:18 BST # gpg: using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [full] # Primary key fingerprint: F6C4 AC46 D493 4868 D3B8 CE8F 21E1 0D29 DF97 7054 * remotes/alistair/tags/pull-riscv-to-apply-20200821-1: hw/intc: ibex_plic: Honour source priorities hw/intc: ibex_plic: Don't allow repeat interrupts on claimed lines hw/intc: ibex_plic: Update the pending irqs target/riscv: Change the TLB page size depends on PMP entries. target/riscv: Fix the translation of physical address gitlab-ci/opensbi: Update GitLab CI to build generic platform hw/riscv: spike: Change the default bios to use generic platform image hw/riscv: Use pre-built bios image of generic platform for virt & sifive_u roms/Makefile: Build the generic platform for RISC-V OpenSBI firmware roms/opensbi: Upgrade from v0.7 to v0.8 configure: Create symbolic links for pc-bios/*.elf files riscv: Fix bug in setting pmpcfg CSR for RISCV64 hw/riscv: sifive_u: Add a dummy L2 cache controller device target/riscv: check before allocating TCG temps target/riscv: Clean up fmv.w.x target/riscv: Check nanboxed inputs in trans_rvf.inc.c target/riscv: Check nanboxed inputs to fp helpers target/riscv: Generate nanboxed results from trans_rvf.inc.c target/riscv: Generalize gen_nanbox_fpr to gen_nanbox_s target/riscv: Generate nanboxed results from fp helpers Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
152be6de91
|
@ -35,18 +35,14 @@ build-opensbi:
|
|||
when: always
|
||||
artifacts:
|
||||
paths: # 'artifacts.zip' will contains the following files:
|
||||
- pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin
|
||||
- pc-bios/opensbi-riscv32-virt-fw_jump.bin
|
||||
- pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin
|
||||
- pc-bios/opensbi-riscv64-virt-fw_jump.bin
|
||||
- opensbi32-virt-stdout.log
|
||||
- opensbi32-virt-stderr.log
|
||||
- opensbi64-virt-stdout.log
|
||||
- opensbi64-virt-stderr.log
|
||||
- opensbi32-sifive_u-stdout.log
|
||||
- opensbi32-sifive_u-stderr.log
|
||||
- opensbi64-sifive_u-stdout.log
|
||||
- opensbi64-sifive_u-stderr.log
|
||||
- pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
|
||||
- pc-bios/opensbi-riscv32-generic-fw_dynamic.elf
|
||||
- pc-bios/opensbi-riscv64-generic-fw_dynamic.bin
|
||||
- pc-bios/opensbi-riscv64-generic-fw_dynamic.elf
|
||||
- opensbi32-generic-stdout.log
|
||||
- opensbi32-generic-stderr.log
|
||||
- opensbi64-generic-stdout.log
|
||||
- opensbi64-generic-stderr.log
|
||||
image: $CI_REGISTRY_IMAGE:opensbi-cross-build
|
||||
variables:
|
||||
GIT_DEPTH: 3
|
||||
|
@ -55,10 +51,6 @@ build-opensbi:
|
|||
- export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
- echo "=== Using ${JOBS} simultaneous jobs ==="
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi32-virt 2>&1 1>opensbi32-virt-stdout.log | tee -a opensbi32-virt-stderr.log >&2
|
||||
- make -j${JOBS} -C roms opensbi32-generic 2>&1 1>opensbi32-generic-stdout.log | tee -a opensbi32-generic-stderr.log >&2
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi64-virt 2>&1 1>opensbi64-virt-stdout.log | tee -a opensbi64-virt-stderr.log >&2
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi32-sifive_u 2>&1 1>opensbi32-sifive_u-stdout.log | tee -a opensbi32-sifive_u-stderr.log >&2
|
||||
- make -j${JOBS} -C roms/opensbi clean
|
||||
- make -j${JOBS} -C roms opensbi64-sifive_u 2>&1 1>opensbi64-sifive_u-stdout.log | tee -a opensbi64-sifive_u-stderr.log >&2
|
||||
- make -j${JOBS} -C roms opensbi64-generic 2>&1 1>opensbi64-generic-stdout.log | tee -a opensbi64-generic-stderr.log >&2
|
||||
|
|
4
Makefile
4
Makefile
|
@ -249,8 +249,8 @@ u-boot.e500 u-boot-sam460-20100605.bin \
|
|||
qemu_vga.ndrv \
|
||||
edk2-licenses.txt \
|
||||
hppa-firmware.img \
|
||||
opensbi-riscv32-sifive_u-fw_jump.bin opensbi-riscv32-virt-fw_jump.bin \
|
||||
opensbi-riscv64-sifive_u-fw_jump.bin opensbi-riscv64-virt-fw_jump.bin
|
||||
opensbi-riscv32-generic-fw_dynamic.bin opensbi-riscv64-generic-fw_dynamic.bin \
|
||||
opensbi-riscv32-generic-fw_dynamic.elf opensbi-riscv64-generic-fw_dynamic.elf
|
||||
else
|
||||
BLOBS=
|
||||
endif
|
||||
|
|
|
@ -8129,6 +8129,7 @@ LINKS="$LINKS tests/qemu-iotests/check"
|
|||
LINKS="$LINKS python"
|
||||
for bios_file in \
|
||||
$source_path/pc-bios/*.bin \
|
||||
$source_path/pc-bios/*.elf \
|
||||
$source_path/pc-bios/*.lid \
|
||||
$source_path/pc-bios/*.rom \
|
||||
$source_path/pc-bios/*.dtb \
|
||||
|
|
|
@ -43,12 +43,22 @@ static void ibex_plic_irqs_set_pending(IbexPlicState *s, int irq, bool level)
|
|||
{
|
||||
int pending_num = irq / 32;
|
||||
|
||||
if (s->claimed[pending_num] & 1 << (irq % 32)) {
|
||||
/*
|
||||
* The interrupt has been claimed, but not compelted.
|
||||
* The pending bit can't be set.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
s->pending[pending_num] |= level << (irq % 32);
|
||||
}
|
||||
|
||||
static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
|
||||
{
|
||||
int i;
|
||||
uint32_t max_irq = 0;
|
||||
uint32_t max_prio = s->threshold;
|
||||
|
||||
for (i = 0; i < s->pending_num; i++) {
|
||||
uint32_t irq_num = ctz64(s->pending[i]) + (i * 32);
|
||||
|
@ -58,13 +68,16 @@ static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (s->priority[irq_num] > s->threshold) {
|
||||
if (!s->claim) {
|
||||
s->claim = irq_num;
|
||||
if (s->priority[irq_num] > max_prio) {
|
||||
max_irq = irq_num;
|
||||
max_prio = s->priority[irq_num];
|
||||
}
|
||||
}
|
||||
|
||||
if (max_irq) {
|
||||
s->claim = max_irq;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -120,7 +133,14 @@ static uint64_t ibex_plic_read(void *opaque, hwaddr addr,
|
|||
int pending_num = s->claim / 32;
|
||||
s->pending[pending_num] &= ~(1 << (s->claim % 32));
|
||||
|
||||
/* Set the interrupt as claimed, but not compelted */
|
||||
s->claimed[pending_num] |= 1 << (s->claim % 32);
|
||||
|
||||
/* Return the current claimed interrupt */
|
||||
ret = s->claim;
|
||||
|
||||
/* Update the interrupt status after the claim */
|
||||
ibex_plic_update(s);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -140,6 +160,7 @@ static void ibex_plic_write(void *opaque, hwaddr addr,
|
|||
} else if (addr_between(addr, s->priority_base, s->priority_num)) {
|
||||
uint32_t irq = ((addr - s->priority_base) >> 2) + 1;
|
||||
s->priority[irq] = value & 7;
|
||||
ibex_plic_update(s);
|
||||
} else if (addr_between(addr, s->enable_base, s->enable_num)) {
|
||||
uint32_t enable_reg = (addr - s->enable_base) / 4;
|
||||
|
||||
|
@ -151,6 +172,10 @@ static void ibex_plic_write(void *opaque, hwaddr addr,
|
|||
/* Interrupt was completed */
|
||||
s->claim = 0;
|
||||
}
|
||||
if (s->claimed[value / 32] & 1 << (value % 32)) {
|
||||
/* This value was already claimed, clear it. */
|
||||
s->claimed[value / 32] &= ~(1 << (value % 32));
|
||||
}
|
||||
}
|
||||
|
||||
ibex_plic_update(s);
|
||||
|
@ -211,6 +236,7 @@ static void ibex_plic_realize(DeviceState *dev, Error **errp)
|
|||
int i;
|
||||
|
||||
s->pending = g_new0(uint32_t, s->pending_num);
|
||||
s->claimed = g_new0(uint32_t, s->pending_num);
|
||||
s->source = g_new0(uint32_t, s->source_num);
|
||||
s->priority = g_new0(uint32_t, s->priority_num);
|
||||
s->enable = g_new0(uint32_t, s->enable_num);
|
||||
|
|
|
@ -60,9 +60,9 @@
|
|||
#include <libfdt.h>
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
# define BIOS_FILENAME "opensbi-riscv32-sifive_u-fw_jump.bin"
|
||||
# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.bin"
|
||||
#else
|
||||
# define BIOS_FILENAME "opensbi-riscv64-sifive_u-fw_jump.bin"
|
||||
# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.bin"
|
||||
#endif
|
||||
|
||||
static const struct MemmapEntry {
|
||||
|
@ -72,6 +72,7 @@ static const struct MemmapEntry {
|
|||
[SIFIVE_U_DEBUG] = { 0x0, 0x100 },
|
||||
[SIFIVE_U_MROM] = { 0x1000, 0xf000 },
|
||||
[SIFIVE_U_CLINT] = { 0x2000000, 0x10000 },
|
||||
[SIFIVE_U_L2CC] = { 0x2010000, 0x1000 },
|
||||
[SIFIVE_U_L2LIM] = { 0x8000000, 0x2000000 },
|
||||
[SIFIVE_U_PLIC] = { 0xc000000, 0x4000000 },
|
||||
[SIFIVE_U_PRCI] = { 0x10000000, 0x1000 },
|
||||
|
@ -302,6 +303,24 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
|||
qemu_fdt_setprop_string(fdt, nodename, "compatible", "gpio-restart");
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/soc/cache-controller@%lx",
|
||||
(long)memmap[SIFIVE_U_L2CC].base);
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "reg",
|
||||
0x0, memmap[SIFIVE_U_L2CC].base,
|
||||
0x0, memmap[SIFIVE_U_L2CC].size);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
|
||||
SIFIVE_U_L2CC_IRQ0, SIFIVE_U_L2CC_IRQ1, SIFIVE_U_L2CC_IRQ2);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
|
||||
qemu_fdt_setprop(fdt, nodename, "cache-unified", NULL, 0);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "cache-size", 2097152);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "cache-sets", 1024);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "cache-level", 2);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "cache-block-size", 64);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "compatible",
|
||||
"sifive,fu540-c000-ccache");
|
||||
g_free(nodename);
|
||||
|
||||
phy_phandle = phandle++;
|
||||
nodename = g_strdup_printf("/soc/ethernet@%lx",
|
||||
(long)memmap[SIFIVE_U_GEM].base);
|
||||
|
@ -733,6 +752,9 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
create_unimplemented_device("riscv.sifive.u.dmc",
|
||||
memmap[SIFIVE_U_DMC].base, memmap[SIFIVE_U_DMC].size);
|
||||
|
||||
create_unimplemented_device("riscv.sifive.u.l2cc",
|
||||
memmap[SIFIVE_U_L2CC].base, memmap[SIFIVE_U_L2CC].size);
|
||||
}
|
||||
|
||||
static Property sifive_u_soc_props[] = {
|
||||
|
|
|
@ -42,10 +42,15 @@
|
|||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
/*
|
||||
* Not like other RISC-V machines that use plain binary bios images,
|
||||
* keeping ELF files here was intentional because BIN files don't work
|
||||
* for the Spike machine as HTIF emulation depends on ELF parsing.
|
||||
*/
|
||||
#if defined(TARGET_RISCV32)
|
||||
# define BIOS_FILENAME "opensbi-riscv32-spike-fw_jump.elf"
|
||||
# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.elf"
|
||||
#else
|
||||
# define BIOS_FILENAME "opensbi-riscv64-spike-fw_jump.elf"
|
||||
# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.elf"
|
||||
#endif
|
||||
|
||||
static const struct MemmapEntry {
|
||||
|
|
|
@ -43,9 +43,9 @@
|
|||
#include "hw/pci-host/gpex.h"
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
# define BIOS_FILENAME "opensbi-riscv32-virt-fw_jump.bin"
|
||||
# define BIOS_FILENAME "opensbi-riscv32-generic-fw_dynamic.bin"
|
||||
#else
|
||||
# define BIOS_FILENAME "opensbi-riscv64-virt-fw_jump.bin"
|
||||
# define BIOS_FILENAME "opensbi-riscv64-generic-fw_dynamic.bin"
|
||||
#endif
|
||||
|
||||
static const struct MemmapEntry {
|
||||
|
|
|
@ -33,6 +33,7 @@ typedef struct IbexPlicState {
|
|||
MemoryRegion mmio;
|
||||
|
||||
uint32_t *pending;
|
||||
uint32_t *claimed;
|
||||
uint32_t *source;
|
||||
uint32_t *priority;
|
||||
uint32_t *enable;
|
||||
|
|
|
@ -71,6 +71,7 @@ enum {
|
|||
SIFIVE_U_DEBUG,
|
||||
SIFIVE_U_MROM,
|
||||
SIFIVE_U_CLINT,
|
||||
SIFIVE_U_L2CC,
|
||||
SIFIVE_U_L2LIM,
|
||||
SIFIVE_U_PLIC,
|
||||
SIFIVE_U_PRCI,
|
||||
|
@ -86,6 +87,9 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
SIFIVE_U_L2CC_IRQ0 = 1,
|
||||
SIFIVE_U_L2CC_IRQ1 = 2,
|
||||
SIFIVE_U_L2CC_IRQ2 = 3,
|
||||
SIFIVE_U_UART0_IRQ = 4,
|
||||
SIFIVE_U_UART1_IRQ = 5,
|
||||
SIFIVE_U_GPIO_IRQ0 = 7,
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -64,10 +64,8 @@ default help:
|
|||
@echo " u-boot.e500 -- update u-boot.e500"
|
||||
@echo " u-boot.sam460 -- update u-boot.sam460"
|
||||
@echo " efi -- update UEFI (edk2) platform firmware"
|
||||
@echo " opensbi32-virt -- update OpenSBI for 32-bit virt machine"
|
||||
@echo " opensbi64-virt -- update OpenSBI for 64-bit virt machine"
|
||||
@echo " opensbi32-sifive_u -- update OpenSBI for 32-bit sifive_u machine"
|
||||
@echo " opensbi64-sifive_u -- update OpenSBI for 64-bit sifive_u machine"
|
||||
@echo " opensbi32-generic -- update OpenSBI for 32-bit generic machine"
|
||||
@echo " opensbi64-generic -- update OpenSBI for 64-bit generic machine"
|
||||
@echo " bios-microvm -- update bios-microvm.bin (qboot)"
|
||||
@echo " clean -- delete the files generated by the previous" \
|
||||
"build targets"
|
||||
|
@ -170,29 +168,19 @@ skiboot:
|
|||
efi: edk2-basetools
|
||||
$(MAKE) -f Makefile.edk2
|
||||
|
||||
opensbi32-virt:
|
||||
opensbi32-generic:
|
||||
$(MAKE) -C opensbi \
|
||||
CROSS_COMPILE=$(riscv32_cross_prefix) \
|
||||
PLATFORM="qemu/virt"
|
||||
cp opensbi/build/platform/qemu/virt/firmware/fw_jump.bin ../pc-bios/opensbi-riscv32-virt-fw_jump.bin
|
||||
PLATFORM="generic"
|
||||
cp opensbi/build/platform/generic/firmware/fw_dynamic.bin ../pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
|
||||
cp opensbi/build/platform/generic/firmware/fw_dynamic.elf ../pc-bios/opensbi-riscv32-generic-fw_dynamic.elf
|
||||
|
||||
opensbi64-virt:
|
||||
opensbi64-generic:
|
||||
$(MAKE) -C opensbi \
|
||||
CROSS_COMPILE=$(riscv64_cross_prefix) \
|
||||
PLATFORM="qemu/virt"
|
||||
cp opensbi/build/platform/qemu/virt/firmware/fw_jump.bin ../pc-bios/opensbi-riscv64-virt-fw_jump.bin
|
||||
|
||||
opensbi32-sifive_u:
|
||||
$(MAKE) -C opensbi \
|
||||
CROSS_COMPILE=$(riscv32_cross_prefix) \
|
||||
PLATFORM="sifive/fu540"
|
||||
cp opensbi/build/platform/sifive/fu540/firmware/fw_jump.bin ../pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin
|
||||
|
||||
opensbi64-sifive_u:
|
||||
$(MAKE) -C opensbi \
|
||||
CROSS_COMPILE=$(riscv64_cross_prefix) \
|
||||
PLATFORM="sifive/fu540"
|
||||
cp opensbi/build/platform/sifive/fu540/firmware/fw_jump.bin ../pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin
|
||||
PLATFORM="generic"
|
||||
cp opensbi/build/platform/generic/firmware/fw_dynamic.bin ../pc-bios/opensbi-riscv64-generic-fw_dynamic.bin
|
||||
cp opensbi/build/platform/generic/firmware/fw_dynamic.elf ../pc-bios/opensbi-riscv64-generic-fw_dynamic.elf
|
||||
|
||||
bios-microvm:
|
||||
$(MAKE) -C qboot
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9f1b72ce66d659e91013b358939e832fb27223f5
|
||||
Subproject commit a98258d0b537a295f517bbc8d813007336731fa9
|
|
@ -543,7 +543,8 @@ restart:
|
|||
/* for superpage mappings, make a fake leaf PTE for the TLB's
|
||||
benefit. */
|
||||
target_ulong vpn = addr >> PGSHIFT;
|
||||
*physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
|
||||
*physical = ((ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT) |
|
||||
(addr & ~TARGET_PAGE_MASK);
|
||||
|
||||
/* set permissions on the TLB entry */
|
||||
if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
|
||||
|
@ -630,7 +631,7 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
|||
}
|
||||
}
|
||||
|
||||
return phys_addr;
|
||||
return phys_addr & TARGET_PAGE_MASK;
|
||||
}
|
||||
|
||||
void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
|
||||
|
@ -692,6 +693,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||
bool first_stage_error = true;
|
||||
int ret = TRANSLATE_FAIL;
|
||||
int mode = mmu_idx;
|
||||
target_ulong tlb_size = 0;
|
||||
|
||||
env->guest_phys_fault_addr = 0;
|
||||
|
||||
|
@ -783,8 +785,13 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||
}
|
||||
|
||||
if (ret == TRANSLATE_SUCCESS) {
|
||||
if (pmp_is_range_in_tlb(env, pa & TARGET_PAGE_MASK, &tlb_size)) {
|
||||
tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
|
||||
prot, mmu_idx, tlb_size);
|
||||
} else {
|
||||
tlb_set_page(cs, address & TARGET_PAGE_MASK, pa & TARGET_PAGE_MASK,
|
||||
prot, mmu_idx, TARGET_PAGE_SIZE);
|
||||
}
|
||||
return true;
|
||||
} else if (probe) {
|
||||
return false;
|
||||
|
|
|
@ -81,10 +81,19 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
|
|||
set_float_rounding_mode(softrm, &env->fp_status);
|
||||
}
|
||||
|
||||
static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
|
||||
uint64_t rs3, int flags)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
float32 frs3 = check_nanbox_s(rs3);
|
||||
return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
||||
uint64_t frs3)
|
||||
{
|
||||
return float32_muladd(frs1, frs2, frs3, 0, &env->fp_status);
|
||||
return do_fmadd_s(env, frs1, frs2, frs3, 0);
|
||||
}
|
||||
|
||||
uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
||||
|
@ -96,8 +105,7 @@ uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
|||
uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
||||
uint64_t frs3)
|
||||
{
|
||||
return float32_muladd(frs1, frs2, frs3, float_muladd_negate_c,
|
||||
&env->fp_status);
|
||||
return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_c);
|
||||
}
|
||||
|
||||
uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
||||
|
@ -110,8 +118,7 @@ uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
|||
uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
||||
uint64_t frs3)
|
||||
{
|
||||
return float32_muladd(frs1, frs2, frs3, float_muladd_negate_product,
|
||||
&env->fp_status);
|
||||
return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_product);
|
||||
}
|
||||
|
||||
uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
||||
|
@ -124,8 +131,8 @@ uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
|||
uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
||||
uint64_t frs3)
|
||||
{
|
||||
return float32_muladd(frs1, frs2, frs3, float_muladd_negate_c |
|
||||
float_muladd_negate_product, &env->fp_status);
|
||||
return do_fmadd_s(env, frs1, frs2, frs3,
|
||||
float_muladd_negate_c | float_muladd_negate_product);
|
||||
}
|
||||
|
||||
uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
||||
|
@ -135,102 +142,126 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
|
|||
float_muladd_negate_product, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
return float32_add(frs1, frs2, &env->fp_status);
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return nanbox_s(float32_add(frs1, frs2, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
return float32_sub(frs1, frs2, &env->fp_status);
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return nanbox_s(float32_sub(frs1, frs2, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
return float32_mul(frs1, frs2, &env->fp_status);
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return nanbox_s(float32_mul(frs1, frs2, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
return float32_div(frs1, frs2, &env->fp_status);
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return nanbox_s(float32_div(frs1, frs2, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
return float32_minnum(frs1, frs2, &env->fp_status);
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
return float32_maxnum(frs1, frs2, &env->fp_status);
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1)
|
||||
uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
return float32_sqrt(frs1, &env->fp_status);
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return nanbox_s(float32_sqrt(frs1, &env->fp_status));
|
||||
}
|
||||
|
||||
target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return float32_le(frs1, frs2, &env->fp_status);
|
||||
}
|
||||
|
||||
target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return float32_lt(frs1, frs2, &env->fp_status);
|
||||
}
|
||||
|
||||
target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
||||
target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
float32 frs2 = check_nanbox_s(rs2);
|
||||
return float32_eq_quiet(frs1, frs2, &env->fp_status);
|
||||
}
|
||||
|
||||
target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1)
|
||||
target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return float32_to_int32(frs1, &env->fp_status);
|
||||
}
|
||||
|
||||
target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1)
|
||||
target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return (int32_t)float32_to_uint32(frs1, &env->fp_status);
|
||||
}
|
||||
|
||||
#if defined(TARGET_RISCV64)
|
||||
uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1)
|
||||
uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return float32_to_int64(frs1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1)
|
||||
uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return float32_to_uint64(frs1, &env->fp_status);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
|
||||
{
|
||||
return int32_to_float32((int32_t)rs1, &env->fp_status);
|
||||
return nanbox_s(int32_to_float32((int32_t)rs1, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
|
||||
{
|
||||
return uint32_to_float32((uint32_t)rs1, &env->fp_status);
|
||||
return nanbox_s(uint32_to_float32((uint32_t)rs1, &env->fp_status));
|
||||
}
|
||||
|
||||
#if defined(TARGET_RISCV64)
|
||||
uint64_t helper_fcvt_s_l(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
return int64_to_float32(rs1, &env->fp_status);
|
||||
return nanbox_s(int64_to_float32(rs1, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
return uint64_to_float32(rs1, &env->fp_status);
|
||||
return nanbox_s(uint64_to_float32(rs1, &env->fp_status));
|
||||
}
|
||||
#endif
|
||||
|
||||
target_ulong helper_fclass_s(uint64_t frs1)
|
||||
target_ulong helper_fclass_s(uint64_t rs1)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return fclass_s(frs1);
|
||||
}
|
||||
|
||||
|
@ -266,12 +297,13 @@ uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
|
|||
|
||||
uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
return float64_to_float32(rs1, &env->fp_status);
|
||||
return nanbox_s(float64_to_float32(rs1, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
return float32_to_float64(rs1, &env->fp_status);
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return float32_to_float64(frs1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
|
||||
static bool trans_fld(DisasContext *ctx, arg_fld *a)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
tcg_gen_addi_tl(t0, t0, a->imm);
|
||||
|
||||
tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEQ);
|
||||
|
@ -35,10 +35,10 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a)
|
|||
|
||||
static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
tcg_gen_addi_tl(t0, t0, a->imm);
|
||||
|
||||
tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEQ);
|
||||
|
|
|
@ -23,30 +23,16 @@
|
|||
return false; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* RISC-V requires NaN-boxing of narrower width floating
|
||||
* point values. This applies when a 32-bit value is
|
||||
* assigned to a 64-bit FP register. Thus this does not
|
||||
* apply when the RVD extension is not present.
|
||||
*/
|
||||
static void gen_nanbox_fpr(DisasContext *ctx, int regno)
|
||||
{
|
||||
if (has_ext(ctx, RVD)) {
|
||||
tcg_gen_ori_i64(cpu_fpr[regno], cpu_fpr[regno],
|
||||
MAKE_64BIT_MASK(32, 32));
|
||||
}
|
||||
}
|
||||
|
||||
static bool trans_flw(DisasContext *ctx, arg_flw *a)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
tcg_gen_addi_tl(t0, t0, a->imm);
|
||||
|
||||
tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEUL);
|
||||
gen_nanbox_fpr(ctx, a->rd);
|
||||
gen_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rd]);
|
||||
|
||||
tcg_temp_free(t0);
|
||||
mark_fs_dirty(ctx);
|
||||
|
@ -55,11 +41,11 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a)
|
|||
|
||||
static bool trans_fsw(DisasContext *ctx, arg_fsw *a)
|
||||
{
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
tcg_gen_addi_tl(t0, t0, a->imm);
|
||||
|
||||
tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUL);
|
||||
|
@ -175,11 +161,20 @@ static bool trans_fsgnj_s(DisasContext *ctx, arg_fsgnj_s *a)
|
|||
{
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
if (a->rs1 == a->rs2) { /* FMOV */
|
||||
tcg_gen_mov_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1]);
|
||||
gen_check_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rs1]);
|
||||
} else { /* FSGNJ */
|
||||
tcg_gen_deposit_i64(cpu_fpr[a->rd], cpu_fpr[a->rs2], cpu_fpr[a->rs1],
|
||||
0, 31);
|
||||
TCGv_i64 rs1 = tcg_temp_new_i64();
|
||||
TCGv_i64 rs2 = tcg_temp_new_i64();
|
||||
|
||||
gen_check_nanbox_s(rs1, cpu_fpr[a->rs1]);
|
||||
gen_check_nanbox_s(rs2, cpu_fpr[a->rs2]);
|
||||
|
||||
/* This formulation retains the nanboxing of rs2. */
|
||||
tcg_gen_deposit_i64(cpu_fpr[a->rd], rs2, rs1, 0, 31);
|
||||
tcg_temp_free_i64(rs1);
|
||||
tcg_temp_free_i64(rs2);
|
||||
}
|
||||
mark_fs_dirty(ctx);
|
||||
return true;
|
||||
|
@ -187,32 +182,65 @@ static bool trans_fsgnj_s(DisasContext *ctx, arg_fsgnj_s *a)
|
|||
|
||||
static bool trans_fsgnjn_s(DisasContext *ctx, arg_fsgnjn_s *a)
|
||||
{
|
||||
TCGv_i64 rs1, rs2, mask;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
rs1 = tcg_temp_new_i64();
|
||||
gen_check_nanbox_s(rs1, cpu_fpr[a->rs1]);
|
||||
|
||||
if (a->rs1 == a->rs2) { /* FNEG */
|
||||
tcg_gen_xori_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], INT32_MIN);
|
||||
tcg_gen_xori_i64(cpu_fpr[a->rd], rs1, MAKE_64BIT_MASK(31, 1));
|
||||
} else {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
tcg_gen_not_i64(t0, cpu_fpr[a->rs2]);
|
||||
tcg_gen_deposit_i64(cpu_fpr[a->rd], t0, cpu_fpr[a->rs1], 0, 31);
|
||||
tcg_temp_free_i64(t0);
|
||||
rs2 = tcg_temp_new_i64();
|
||||
gen_check_nanbox_s(rs2, cpu_fpr[a->rs2]);
|
||||
|
||||
/*
|
||||
* Replace bit 31 in rs1 with inverse in rs2.
|
||||
* This formulation retains the nanboxing of rs1.
|
||||
*/
|
||||
mask = tcg_const_i64(~MAKE_64BIT_MASK(31, 1));
|
||||
tcg_gen_nor_i64(rs2, rs2, mask);
|
||||
tcg_gen_and_i64(rs1, mask, rs1);
|
||||
tcg_gen_or_i64(cpu_fpr[a->rd], rs1, rs2);
|
||||
|
||||
tcg_temp_free_i64(mask);
|
||||
tcg_temp_free_i64(rs2);
|
||||
}
|
||||
tcg_temp_free_i64(rs1);
|
||||
|
||||
mark_fs_dirty(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_fsgnjx_s(DisasContext *ctx, arg_fsgnjx_s *a)
|
||||
{
|
||||
TCGv_i64 rs1, rs2;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
rs1 = tcg_temp_new_i64();
|
||||
gen_check_nanbox_s(rs1, cpu_fpr[a->rs1]);
|
||||
|
||||
if (a->rs1 == a->rs2) { /* FABS */
|
||||
tcg_gen_andi_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], ~INT32_MIN);
|
||||
tcg_gen_andi_i64(cpu_fpr[a->rd], rs1, ~MAKE_64BIT_MASK(31, 1));
|
||||
} else {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
tcg_gen_andi_i64(t0, cpu_fpr[a->rs2], INT32_MIN);
|
||||
tcg_gen_xor_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], t0);
|
||||
tcg_temp_free_i64(t0);
|
||||
rs2 = tcg_temp_new_i64();
|
||||
gen_check_nanbox_s(rs2, cpu_fpr[a->rs2]);
|
||||
|
||||
/*
|
||||
* Xor bit 31 in rs1 with that in rs2.
|
||||
* This formulation retains the nanboxing of rs1.
|
||||
*/
|
||||
tcg_gen_andi_i64(rs2, rs2, MAKE_64BIT_MASK(31, 1));
|
||||
tcg_gen_xor_i64(cpu_fpr[a->rd], rs1, rs2);
|
||||
|
||||
tcg_temp_free_i64(rs2);
|
||||
}
|
||||
tcg_temp_free_i64(rs1);
|
||||
|
||||
mark_fs_dirty(ctx);
|
||||
return true;
|
||||
}
|
||||
|
@ -378,11 +406,8 @@ static bool trans_fmv_w_x(DisasContext *ctx, arg_fmv_w_x *a)
|
|||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
|
||||
#if defined(TARGET_RISCV64)
|
||||
tcg_gen_mov_i64(cpu_fpr[a->rd], t0);
|
||||
#else
|
||||
tcg_gen_extu_i32_i64(cpu_fpr[a->rd], t0);
|
||||
#endif
|
||||
tcg_gen_extu_tl_i64(cpu_fpr[a->rd], t0);
|
||||
gen_nanbox_s(cpu_fpr[a->rd], cpu_fpr[a->rd]);
|
||||
|
||||
mark_fs_dirty(ctx);
|
||||
tcg_temp_free(t0);
|
||||
|
|
|
@ -38,4 +38,20 @@ target_ulong fclass_d(uint64_t frs1);
|
|||
#define SEW32 2
|
||||
#define SEW64 3
|
||||
|
||||
static inline uint64_t nanbox_s(float32 f)
|
||||
{
|
||||
return f | MAKE_64BIT_MASK(32, 32);
|
||||
}
|
||||
|
||||
static inline float32 check_nanbox_s(uint64_t f)
|
||||
{
|
||||
uint64_t mask = MAKE_64BIT_MASK(32, 32);
|
||||
|
||||
if (likely((f & mask) == mask)) {
|
||||
return (uint32_t)f;
|
||||
} else {
|
||||
return 0x7fc00000u; /* default qnan */
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -320,8 +320,7 @@ void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
|
|||
|
||||
for (i = 0; i < sizeof(target_ulong); i++) {
|
||||
cfg_val = (val >> 8 * i) & 0xff;
|
||||
pmp_write_cfg(env, (reg_index * sizeof(target_ulong)) + i,
|
||||
cfg_val);
|
||||
pmp_write_cfg(env, (reg_index * 4) + i, cfg_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,7 +335,7 @@ target_ulong pmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index)
|
|||
target_ulong val = 0;
|
||||
|
||||
for (i = 0; i < sizeof(target_ulong); i++) {
|
||||
val = pmp_read_cfg(env, (reg_index * sizeof(target_ulong)) + i);
|
||||
val = pmp_read_cfg(env, (reg_index * 4) + i);
|
||||
cfg_val |= (val << (i * 8));
|
||||
}
|
||||
trace_pmpcfg_csr_read(env->mhartid, reg_index, cfg_val);
|
||||
|
@ -384,3 +383,55 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index)
|
|||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the TLB size if the start address or the end address of
|
||||
* PMP entry is presented in thie TLB page.
|
||||
*/
|
||||
static target_ulong pmp_get_tlb_size(CPURISCVState *env, int pmp_index,
|
||||
target_ulong tlb_sa, target_ulong tlb_ea)
|
||||
{
|
||||
target_ulong pmp_sa = env->pmp_state.addr[pmp_index].sa;
|
||||
target_ulong pmp_ea = env->pmp_state.addr[pmp_index].ea;
|
||||
|
||||
if (pmp_sa >= tlb_sa && pmp_ea <= tlb_ea) {
|
||||
return pmp_ea - pmp_sa + 1;
|
||||
}
|
||||
|
||||
if (pmp_sa >= tlb_sa && pmp_sa <= tlb_ea && pmp_ea >= tlb_ea) {
|
||||
return tlb_ea - pmp_sa + 1;
|
||||
}
|
||||
|
||||
if (pmp_ea <= tlb_ea && pmp_ea >= tlb_sa && pmp_sa <= tlb_sa) {
|
||||
return pmp_ea - tlb_sa + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check is there a PMP entry which range covers this page. If so,
|
||||
* try to find the minimum granularity for the TLB size.
|
||||
*/
|
||||
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
|
||||
target_ulong *tlb_size)
|
||||
{
|
||||
int i;
|
||||
target_ulong val;
|
||||
target_ulong tlb_ea = (tlb_sa + TARGET_PAGE_SIZE - 1);
|
||||
|
||||
for (i = 0; i < MAX_RISCV_PMPS; i++) {
|
||||
val = pmp_get_tlb_size(env, i, tlb_sa, tlb_ea);
|
||||
if (val) {
|
||||
if (*tlb_size == 0 || *tlb_size > val) {
|
||||
*tlb_size = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*tlb_size != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -60,5 +60,7 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
|
|||
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
|
||||
bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
|
||||
target_ulong size, pmp_priv_t priv, target_ulong mode);
|
||||
bool pmp_is_range_in_tlb(CPURISCVState *env, hwaddr tlb_sa,
|
||||
target_ulong *tlb_size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -90,6 +90,35 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
|
|||
return ctx->misa & ext;
|
||||
}
|
||||
|
||||
/*
|
||||
* RISC-V requires NaN-boxing of narrower width floating point values.
|
||||
* This applies when a 32-bit value is assigned to a 64-bit FP register.
|
||||
* For consistency and simplicity, we nanbox results even when the RVD
|
||||
* extension is not present.
|
||||
*/
|
||||
static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
|
||||
{
|
||||
tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32));
|
||||
}
|
||||
|
||||
/*
|
||||
* A narrow n-bit operation, where n < FLEN, checks that input operands
|
||||
* are correctly Nan-boxed, i.e., all upper FLEN - n bits are 1.
|
||||
* If so, the least-significant bits of the input are used, otherwise the
|
||||
* input value is treated as an n-bit canonical NaN (v2.2 section 9.2).
|
||||
*
|
||||
* Here, the result is always nan-boxed, even the canonical nan.
|
||||
*/
|
||||
static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
|
||||
{
|
||||
TCGv_i64 t_max = tcg_const_i64(0xffffffff00000000ull);
|
||||
TCGv_i64 t_nan = tcg_const_i64(0xffffffff7fc00000ull);
|
||||
|
||||
tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
|
||||
tcg_temp_free_i64(t_max);
|
||||
tcg_temp_free_i64(t_nan);
|
||||
}
|
||||
|
||||
static void generate_exception(DisasContext *ctx, int excp)
|
||||
{
|
||||
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
|
||||
|
|
Loading…
Reference in New Issue