From cb53b283b5adf4123273d07eee5e186e2e0a1b5b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 30 Apr 2021 15:12:55 +0800 Subject: [PATCH 01/32] hw/riscv: sifive_u: Switch to use qemu_fdt_setprop_string_array() helper Since commit 78da6a1bca22 ("device_tree: add qemu_fdt_setprop_string_array helper"), we can use the new helper to set the clock name for the ethernet controller node. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210430071302.1489082-1-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/sifive_u.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 698637e8e1..89cccd7fd5 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -95,9 +95,9 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, int cpu; uint32_t *cells; char *nodename; - char ethclk_names[] = "pclk\0hclk"; uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1; uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle; + static const char * const ethclk_names[2] = { "pclk", "hclk" }; if (ms->dtb) { fdt = s->fdt = load_device_tree(ms->dtb, &s->fdt_size); @@ -412,8 +412,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ); qemu_fdt_setprop_cells(fdt, nodename, "clocks", prci_phandle, PRCI_CLK_GEMGXLPLL, prci_phandle, PRCI_CLK_GEMGXLPLL); - qemu_fdt_setprop(fdt, nodename, "clock-names", ethclk_names, - sizeof(ethclk_names)); + qemu_fdt_setprop_string_array(fdt, nodename, "clock-names", + (char **)ðclk_names, ARRAY_SIZE(ethclk_names)); qemu_fdt_setprop(fdt, nodename, "local-mac-address", s->soc.gem.conf.macaddr.a, ETH_ALEN); qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1); From 2cc04550ac222237b979b5a45679ff746fc99a46 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 30 Apr 2021 15:12:56 +0800 Subject: [PATCH 02/32] hw/riscv: virt: Switch to use qemu_fdt_setprop_string_array() helper Since commit 78da6a1bca22 ("device_tree: add qemu_fdt_setprop_string_array helper"), we can use the new helper to set the compatible strings for the SiFive test device node. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210430071302.1489082-2-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 95a11adaa2..1e017d1c52 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -394,8 +394,11 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, (long)memmap[VIRT_TEST].base); qemu_fdt_add_subnode(fdt, name); { - const char compat[] = "sifive,test1\0sifive,test0\0syscon"; - qemu_fdt_setprop(fdt, name, "compatible", compat, sizeof(compat)); + static const char * const compat[3] = { + "sifive,test1", "sifive,test0", "syscon" + }; + qemu_fdt_setprop_string_array(fdt, name, "compatible", (char **)&compat, + ARRAY_SIZE(compat)); } qemu_fdt_setprop_cells(fdt, name, "reg", 0x0, memmap[VIRT_TEST].base, From 7cfbb17f023dc014d366b2f30af852aa62a5c3b1 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 30 Apr 2021 15:12:57 +0800 Subject: [PATCH 03/32] hw/riscv: Support the official CLINT DT bindings Linux kernel commit a2770b57d083 ("dt-bindings: timer: Add CLINT bindings") adds the official DT bindings for CLINT, which uses "sifive,clint0" as the compatible string. "riscv,clint0" is now legacy and has to be kept for backward compatibility of legacy systems. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210430071302.1489082-3-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/sifive_u.c | 6 +++++- hw/riscv/spike.c | 6 +++++- hw/riscv/virt.c | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 89cccd7fd5..d3828dc880 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -98,6 +98,9 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1; uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle; static const char * const ethclk_names[2] = { "pclk", "hclk" }; + static const char * const clint_compat[2] = { + "sifive,clint0", "riscv,clint0" + }; if (ms->dtb) { fdt = s->fdt = load_device_tree(ms->dtb, &s->fdt_size); @@ -209,7 +212,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, nodename = g_strdup_printf("/soc/clint@%lx", (long)memmap[SIFIVE_U_DEV_CLINT].base); qemu_fdt_add_subnode(fdt, nodename); - qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,clint0"); + qemu_fdt_setprop_string_array(fdt, nodename, "compatible", + (char **)&clint_compat, ARRAY_SIZE(clint_compat)); qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[SIFIVE_U_DEV_CLINT].base, 0x0, memmap[SIFIVE_U_DEV_CLINT].size); diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index fe0806a476..4b08816dfa 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -59,6 +59,9 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap, uint32_t cpu_phandle, intc_phandle, phandle = 1; char *name, *mem_name, *clint_name, *clust_name; char *core_name, *cpu_name, *intc_name; + static const char * const clint_compat[2] = { + "sifive,clint0", "riscv,clint0" + }; fdt = s->fdt = create_device_tree(&s->fdt_size); if (!fdt) { @@ -152,7 +155,8 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap, (memmap[SPIKE_CLINT].size * socket); clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr); qemu_fdt_add_subnode(fdt, clint_name); - qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0"); + qemu_fdt_setprop_string_array(fdt, clint_name, "compatible", + (char **)&clint_compat, ARRAY_SIZE(clint_compat)); qemu_fdt_setprop_cells(fdt, clint_name, "reg", 0x0, clint_addr, 0x0, memmap[SPIKE_CLINT].size); qemu_fdt_setprop(fdt, clint_name, "interrupts-extended", diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 1e017d1c52..5159e7e020 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -194,6 +194,9 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, char *name, *clint_name, *plic_name, *clust_name; hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2; hwaddr flashbase = virt_memmap[VIRT_FLASH].base; + static const char * const clint_compat[2] = { + "sifive,clint0", "riscv,clint0" + }; if (mc->dtb) { fdt = mc->fdt = load_device_tree(mc->dtb, &s->fdt_size); @@ -299,7 +302,8 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, (memmap[VIRT_CLINT].size * socket); clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr); qemu_fdt_add_subnode(fdt, clint_name); - qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0"); + qemu_fdt_setprop_string_array(fdt, clint_name, "compatible", + (char **)&clint_compat, ARRAY_SIZE(clint_compat)); qemu_fdt_setprop_cells(fdt, clint_name, "reg", 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size); qemu_fdt_setprop(fdt, clint_name, "interrupts-extended", From 60bb5407f02b9d7cf7078ff339cbae961b7e98cc Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 30 Apr 2021 15:12:58 +0800 Subject: [PATCH 04/32] hw/riscv: Support the official PLIC DT bindings The official DT bindings of PLIC uses "sifive,plic-1.0.0" as the compatible string in the upstream Linux kernel. "riscv,plic0" is now legacy and has to be kept for backward compatibility of legacy systems. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210430071302.1489082-4-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/sifive_u.c | 6 +++++- hw/riscv/virt.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index d3828dc880..a32a95d58f 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -101,6 +101,9 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, static const char * const clint_compat[2] = { "sifive,clint0", "riscv,clint0" }; + static const char * const plic_compat[2] = { + "sifive,plic-1.0.0", "riscv,plic0" + }; if (ms->dtb) { fdt = s->fdt = load_device_tree(ms->dtb, &s->fdt_size); @@ -270,7 +273,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, (long)memmap[SIFIVE_U_DEV_PLIC].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1); - qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0"); + qemu_fdt_setprop_string_array(fdt, nodename, "compatible", + (char **)&plic_compat, ARRAY_SIZE(plic_compat)); qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); qemu_fdt_setprop(fdt, nodename, "interrupts-extended", cells, (ms->smp.cpus * 4 - 2) * sizeof(uint32_t)); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 5159e7e020..560216d217 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -197,6 +197,9 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, static const char * const clint_compat[2] = { "sifive,clint0", "riscv,clint0" }; + static const char * const plic_compat[2] = { + "sifive,plic-1.0.0", "riscv,plic0" + }; if (mc->dtb) { fdt = mc->fdt = load_device_tree(mc->dtb, &s->fdt_size); @@ -319,7 +322,8 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, "#address-cells", FDT_PLIC_ADDR_CELLS); qemu_fdt_setprop_cell(fdt, plic_name, "#interrupt-cells", FDT_PLIC_INT_CELLS); - qemu_fdt_setprop_string(fdt, plic_name, "compatible", "riscv,plic0"); + qemu_fdt_setprop_string_array(fdt, plic_name, "compatible", + (char **)&plic_compat, ARRAY_SIZE(plic_compat)); qemu_fdt_setprop(fdt, plic_name, "interrupt-controller", NULL, 0); qemu_fdt_setprop(fdt, plic_name, "interrupts-extended", plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4); From 3ede8967c8a586c226da21d04283c72e24a2385e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 30 Apr 2021 15:12:59 +0800 Subject: [PATCH 05/32] docs/system/riscv: Correct the indentation level of supported devices The supported device bullet list has an additional space before each entry, which makes a wrong indentation level. Correct it. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210430071302.1489082-5-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- docs/system/riscv/microchip-icicle-kit.rst | 20 +++++++-------- docs/system/riscv/sifive_u.rst | 30 +++++++++++----------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/system/riscv/microchip-icicle-kit.rst b/docs/system/riscv/microchip-icicle-kit.rst index 4fe97bce3f..e803131763 100644 --- a/docs/system/riscv/microchip-icicle-kit.rst +++ b/docs/system/riscv/microchip-icicle-kit.rst @@ -15,16 +15,16 @@ Supported devices The ``microchip-icicle-kit`` machine supports the following devices: - * 1 E51 core - * 4 U54 cores - * Core Level Interruptor (CLINT) - * Platform-Level Interrupt Controller (PLIC) - * L2 Loosely Integrated Memory (L2-LIM) - * DDR memory controller - * 5 MMUARTs - * 1 DMA controller - * 2 GEM Ethernet controllers - * 1 SDHC storage controller +* 1 E51 core +* 4 U54 cores +* Core Level Interruptor (CLINT) +* Platform-Level Interrupt Controller (PLIC) +* L2 Loosely Integrated Memory (L2-LIM) +* DDR memory controller +* 5 MMUARTs +* 1 DMA controller +* 2 GEM Ethernet controllers +* 1 SDHC storage controller Boot options ------------ diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst index 98e7562848..dcdfbda931 100644 --- a/docs/system/riscv/sifive_u.rst +++ b/docs/system/riscv/sifive_u.rst @@ -9,21 +9,21 @@ Supported devices The ``sifive_u`` machine supports the following devices: - * 1 E51 / E31 core - * Up to 4 U54 / U34 cores - * Core Level Interruptor (CLINT) - * Platform-Level Interrupt Controller (PLIC) - * Power, Reset, Clock, Interrupt (PRCI) - * L2 Loosely Integrated Memory (L2-LIM) - * DDR memory controller - * 2 UARTs - * 1 GEM Ethernet controller - * 1 GPIO controller - * 1 One-Time Programmable (OTP) memory with stored serial number - * 1 DMA controller - * 2 QSPI controllers - * 1 ISSI 25WP256 flash - * 1 SD card in SPI mode +* 1 E51 / E31 core +* Up to 4 U54 / U34 cores +* Core Level Interruptor (CLINT) +* Platform-Level Interrupt Controller (PLIC) +* Power, Reset, Clock, Interrupt (PRCI) +* L2 Loosely Integrated Memory (L2-LIM) +* DDR memory controller +* 2 UARTs +* 1 GEM Ethernet controller +* 1 GPIO controller +* 1 One-Time Programmable (OTP) memory with stored serial number +* 1 DMA controller +* 2 QSPI controllers +* 1 ISSI 25WP256 flash +* 1 SD card in SPI mode Please note the real world HiFive Unleashed board has a fixed configuration of 1 E51 core and 4 U54 core combination and the RISC-V core boots in 64-bit mode. From 0147af69abb17a1ab5780821659c2e71d081c1e2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 30 Apr 2021 15:13:00 +0800 Subject: [PATCH 06/32] docs/system/riscv: sifive_u: Document '-dtb' usage Update the 'sifive_u' machine documentation to mention the '-dtb' option that can be used to pass a custom DTB to QEMU. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210430071302.1489082-6-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- docs/system/riscv/sifive_u.rst | 47 +++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst index dcdfbda931..32d0a1b85d 100644 --- a/docs/system/riscv/sifive_u.rst +++ b/docs/system/riscv/sifive_u.rst @@ -36,12 +36,21 @@ Hardware configuration information ---------------------------------- The ``sifive_u`` machine automatically generates a device tree blob ("dtb") -which it passes to the guest. This provides information about the addresses, -interrupt lines and other configuration of the various devices in the system. -Guest software should discover the devices that are present in the generated -DTB instead of using a DTB for the real hardware, as some of the devices are -not modeled by QEMU and trying to access these devices may cause unexpected -behavior. +which it passes to the guest, if there is no ``-dtb`` option. This provides +information about the addresses, interrupt lines and other configuration of +the various devices in the system. Guest software should discover the devices +that are present in the generated DTB instead of using a DTB for the real +hardware, as some of the devices are not modeled by QEMU and trying to access +these devices may cause unexpected behavior. + +If users want to provide their own DTB, they can use the ``-dtb`` option. +These DTBs should have the following requirements: + +* The /cpus node should contain at least one subnode for E51 and the number + of subnodes should match QEMU's ``-smp`` option +* The /memory reg size should match QEMU’s selected ram_size via ``-m`` +* Should contain a node for the CLINT device with a compatible string + "riscv,clint0" if using with OpenSBI BIOS images Boot options ------------ @@ -122,6 +131,32 @@ To boot the newly built Linux kernel in QEMU with the ``sifive_u`` machine: -initrd /path/to/rootfs.ext4 \ -append "root=/dev/ram" +Alternatively, we can use a custom DTB to boot the machine by inserting a CLINT +node in fu540-c000.dtsi in the Linux kernel, + +.. code-block:: none + + clint: clint@2000000 { + compatible = "riscv,clint0"; + interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7 + &cpu1_intc 3 &cpu1_intc 7 + &cpu2_intc 3 &cpu2_intc 7 + &cpu3_intc 3 &cpu3_intc 7 + &cpu4_intc 3 &cpu4_intc 7>; + reg = <0x00 0x2000000 0x00 0x10000>; + }; + +with the following command line options: + +.. code-block:: bash + + $ qemu-system-riscv64 -M sifive_u -smp 5 -m 8G \ + -display none -serial stdio \ + -kernel arch/riscv/boot/Image \ + -dtb arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dtb \ + -initrd /path/to/rootfs.ext4 \ + -append "root=/dev/ram" + To build a Linux mainline kernel that can be booted by the ``sifive_u`` machine in 32-bit mode, use the rv32_defconfig configuration. A patch is required to fix the 32-bit boot issue for Linux kernel v5.10. From a0acd0a175891afe554c907c4ecc941abbd98602 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 30 Apr 2021 15:13:01 +0800 Subject: [PATCH 07/32] hw/riscv: Use macros for BIOS image names The OpenSBI BIOS image names are used by many RISC-V machines. Let's define macros for them. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210430071302.1489082-7-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/sifive_u.c | 6 ++---- hw/riscv/spike.c | 6 ++---- hw/riscv/virt.c | 6 ++---- include/hw/riscv/boot.h | 5 +++++ 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index a32a95d58f..273c86418c 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -560,12 +560,10 @@ static void sifive_u_machine_init(MachineState *machine) if (riscv_is_32bit(&s->soc.u_cpus)) { firmware_end_addr = riscv_find_and_load_firmware(machine, - "opensbi-riscv32-generic-fw_dynamic.bin", - start_addr, NULL); + RISCV32_BIOS_BIN, start_addr, NULL); } else { firmware_end_addr = riscv_find_and_load_firmware(machine, - "opensbi-riscv64-generic-fw_dynamic.bin", - start_addr, NULL); + RISCV64_BIOS_BIN, start_addr, NULL); } if (machine->kernel_filename) { diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 4b08816dfa..fead77f0c4 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -258,13 +258,11 @@ static void spike_board_init(MachineState *machine) */ if (riscv_is_32bit(&s->soc[0])) { firmware_end_addr = riscv_find_and_load_firmware(machine, - "opensbi-riscv32-generic-fw_dynamic.elf", - memmap[SPIKE_DRAM].base, + RISCV32_BIOS_ELF, memmap[SPIKE_DRAM].base, htif_symbol_callback); } else { firmware_end_addr = riscv_find_and_load_firmware(machine, - "opensbi-riscv64-generic-fw_dynamic.elf", - memmap[SPIKE_DRAM].base, + RISCV64_BIOS_ELF, memmap[SPIKE_DRAM].base, htif_symbol_callback); } diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 560216d217..4a3cd2599a 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -681,12 +681,10 @@ static void virt_machine_init(MachineState *machine) if (riscv_is_32bit(&s->soc[0])) { firmware_end_addr = riscv_find_and_load_firmware(machine, - "opensbi-riscv32-generic-fw_dynamic.bin", - start_addr, NULL); + RISCV32_BIOS_BIN, start_addr, NULL); } else { firmware_end_addr = riscv_find_and_load_firmware(machine, - "opensbi-riscv64-generic-fw_dynamic.bin", - start_addr, NULL); + RISCV64_BIOS_BIN, start_addr, NULL); } if (machine->kernel_filename) { diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 11a21dd584..0e89400b09 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -24,6 +24,11 @@ #include "hw/loader.h" #include "hw/riscv/riscv_hart.h" +#define RISCV32_BIOS_BIN "opensbi-riscv32-generic-fw_dynamic.bin" +#define RISCV32_BIOS_ELF "opensbi-riscv32-generic-fw_dynamic.elf" +#define RISCV64_BIOS_BIN "opensbi-riscv64-generic-fw_dynamic.bin" +#define RISCV64_BIOS_ELF "opensbi-riscv64-generic-fw_dynamic.elf" + bool riscv_is_32bit(RISCVHartArrayState *harts); target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts, From 143897b50140cfd7540f867edca5d658e76aa9bf Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 30 Apr 2021 15:13:02 +0800 Subject: [PATCH 08/32] hw/riscv: microchip_pfsoc: Support direct kernel boot At present the Microchip Icicle Kit machine only supports using '-bios' to load the HSS, and does not support '-kernel' for direct kernel booting just like other RISC-V machines do. One has to use U-Boot which is chain-loaded by HSS, to load a kernel for testing. This is not so convenient. Adding '-kernel' support together with the existing '-bios', we follow the following table to select which payload we execute: -bios | -kernel | payload ------+------------+-------- N | N | HSS Y | don't care | HSS N | Y | kernel This ensures backwards compatibility with how we used to expose '-bios' to users. When '-kernel' is used for direct boot, '-dtb' must be present to provide a valid device tree for the board, as we don't generate device tree. When direct kernel boot is used, the OpenSBI fw_dynamic BIOS image is used to boot a payload like U-Boot or OS kernel directly. Documentation is updated to describe the direct kernel boot. Note as of today there is still no PolarFire SoC support in the upstream Linux kernel hence the document does not include instructions for that. It will be updated in the future. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-id: 20210430071302.1489082-8-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- docs/system/riscv/microchip-icicle-kit.rst | 30 ++++++-- hw/riscv/microchip_pfsoc.c | 81 +++++++++++++++++++++- 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/docs/system/riscv/microchip-icicle-kit.rst b/docs/system/riscv/microchip-icicle-kit.rst index e803131763..54ced661e3 100644 --- a/docs/system/riscv/microchip-icicle-kit.rst +++ b/docs/system/riscv/microchip-icicle-kit.rst @@ -31,17 +31,37 @@ Boot options The ``microchip-icicle-kit`` machine can start using the standard -bios functionality for loading its BIOS image, aka Hart Software Services (HSS_). -HSS loads the second stage bootloader U-Boot from an SD card. It does not -support direct kernel loading via the -kernel option. One has to load kernel -from U-Boot. +HSS loads the second stage bootloader U-Boot from an SD card. Then a kernel +can be loaded from U-Boot. It also supports direct kernel booting via the +-kernel option along with the device tree blob via -dtb. When direct kernel +boot is used, the OpenSBI fw_dynamic BIOS image is used to boot a payload +like U-Boot or OS kernel directly. + +The user provided DTB should have the following requirements: + +* The /cpus node should contain at least one subnode for E51 and the number + of subnodes should match QEMU's ``-smp`` option +* The /memory reg size should match QEMU’s selected ram_size via ``-m`` +* Should contain a node for the CLINT device with a compatible string + "riscv,clint0" + +QEMU follows below truth table to select which payload to execute: + +===== ========== ======= +-bios -kernel payload +===== ========== ======= + N N HSS + Y don't care HSS + N Y kernel +===== ========== ======= The memory is set to 1537 MiB by default which is the minimum required high memory size by HSS. A sanity check on ram size is performed in the machine init routine to prompt user to increase the RAM size to > 1537 MiB when less than 1537 MiB ram is detected. -Boot the machine ----------------- +Running HSS +----------- HSS 2020.12 release is tested at the time of writing. To build an HSS image that can be booted by the ``microchip-icicle-kit`` machine, type the following diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index 6cbd17ebf2..eb8e79e0a1 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -51,6 +51,7 @@ #include "hw/riscv/microchip_pfsoc.h" #include "hw/intc/sifive_clint.h" #include "hw/intc/sifive_plic.h" +#include "sysemu/device_tree.h" #include "sysemu/sysemu.h" /* @@ -460,6 +461,12 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) MemoryRegion *mem_high = g_new(MemoryRegion, 1); MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1); uint64_t mem_high_size; + hwaddr firmware_load_addr; + const char *firmware_name; + bool kernel_as_payload = false; + target_ulong firmware_end_addr, kernel_start_addr; + uint64_t kernel_entry; + uint32_t fdt_load_addr; DriveInfo *dinfo = drive_get_next(IF_SD); /* Sanity check on RAM size */ @@ -504,9 +511,6 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) memmap[MICROCHIP_PFSOC_DRAM_HI_ALIAS].base, mem_high_alias); - /* Load the firmware */ - riscv_find_and_load_firmware(machine, BIOS_FILENAME, RESET_VECTOR, NULL); - /* Attach an SD card */ if (dinfo) { CadenceSDHCIState *sdhci = &(s->soc.sdhci); @@ -516,6 +520,77 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) &error_fatal); qdev_realize_and_unref(card, sdhci->bus, &error_fatal); } + + /* + * We follow the following table to select which payload we execute. + * + * -bios | -kernel | payload + * -------+------------+-------- + * N | N | HSS + * Y | don't care | HSS + * N | Y | kernel + * + * This ensures backwards compatibility with how we used to expose -bios + * to users but allows them to run through direct kernel booting as well. + * + * When -kernel is used for direct boot, -dtb must be present to provide + * a valid device tree for the board, as we don't generate device tree. + */ + + if (machine->kernel_filename && machine->dtb) { + int fdt_size; + machine->fdt = load_device_tree(machine->dtb, &fdt_size); + if (!machine->fdt) { + error_report("load_device_tree() failed"); + exit(1); + } + + firmware_name = RISCV64_BIOS_BIN; + firmware_load_addr = memmap[MICROCHIP_PFSOC_DRAM_LO].base; + kernel_as_payload = true; + } + + if (!kernel_as_payload) { + firmware_name = BIOS_FILENAME; + firmware_load_addr = RESET_VECTOR; + } + + /* Load the firmware */ + firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name, + firmware_load_addr, NULL); + + if (kernel_as_payload) { + kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, + firmware_end_addr); + + kernel_entry = riscv_load_kernel(machine->kernel_filename, + kernel_start_addr, NULL); + + if (machine->initrd_filename) { + hwaddr start; + hwaddr end = riscv_load_initrd(machine->initrd_filename, + machine->ram_size, kernel_entry, + &start); + qemu_fdt_setprop_cell(machine->fdt, "/chosen", + "linux,initrd-start", start); + qemu_fdt_setprop_cell(machine->fdt, "/chosen", + "linux,initrd-end", end); + } + + if (machine->kernel_cmdline) { + qemu_fdt_setprop_string(machine->fdt, "/chosen", + "bootargs", machine->kernel_cmdline); + } + + /* Compute the fdt load address in dram */ + fdt_load_addr = riscv_load_fdt(memmap[MICROCHIP_PFSOC_DRAM_LO].base, + machine->ram_size, machine->fdt); + /* Load the reset vector */ + riscv_setup_rom_reset_vec(machine, &s->soc.u_cpus, firmware_load_addr, + memmap[MICROCHIP_PFSOC_ENVM_DATA].base, + memmap[MICROCHIP_PFSOC_ENVM_DATA].size, + kernel_entry, fdt_load_addr, machine->fdt); + } } static void microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data) From 719f0f603c2289f438b8d6ef4358d9407b4c2905 Mon Sep 17 00:00:00 2001 From: Jose Martins Date: Tue, 20 Apr 2021 22:36:56 +0100 Subject: [PATCH 09/32] target/riscv: fix wfi exception behavior The wfi exception trigger behavior should take into account user mode, hstatus.vtw, and the fact the an wfi might raise different types of exceptions depending on various factors: If supervisor mode is not present: - an illegal instruction exception should be generated if user mode executes and wfi instruction and mstatus.tw = 1. If supervisor mode is present: - when a wfi instruction is executed, an illegal exception should be triggered if either the current mode is user or the mode is supervisor and mstatus.tw is set. Plus, if the hypervisor extensions are enabled: - a virtual instruction exception should be raised when a wfi is executed from virtual-user or virtual-supervisor and hstatus.vtw is set. Signed-off-by: Jose Martins Reviewed-by: Alistair Francis Message-id: 20210420213656.85148-1-josemartins90@gmail.com Signed-off-by: Alistair Francis --- target/riscv/cpu_bits.h | 1 + target/riscv/op_helper.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 52640e6856..7330ff5a19 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -390,6 +390,7 @@ #define HSTATUS_HU 0x00000200 #define HSTATUS_VGEIN 0x0003F000 #define HSTATUS_VTVM 0x00100000 +#define HSTATUS_VTW 0x00200000 #define HSTATUS_VTSR 0x00400000 #define HSTATUS_VSXL 0x300000000 diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 170b494227..3c48e739ac 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -177,10 +177,15 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) void helper_wfi(CPURISCVState *env) { CPUState *cs = env_cpu(env); + bool rvs = riscv_has_ext(env, RVS); + bool prv_u = env->priv == PRV_U; + bool prv_s = env->priv == PRV_S; - if ((env->priv == PRV_S && - get_field(env->mstatus, MSTATUS_TW)) || - riscv_cpu_virt_enabled(env)) { + if (((prv_s || (!rvs && prv_u)) && get_field(env->mstatus, MSTATUS_TW)) || + (rvs && prv_u && !riscv_cpu_virt_enabled(env))) { + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + } else if (riscv_cpu_virt_enabled(env) && (prv_u || + (prv_s && get_field(env->hstatus, HSTATUS_VTW)))) { riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC()); } else { cs->halted = 1; From 6debd840c8fedee6a378b05800d3382864e3564d Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Tue, 4 May 2021 08:34:32 +1000 Subject: [PATCH 10/32] docs/system: Move the RISC-V -bios information to removed QEMU 5.1 changed the behaviour of the default boot for the RISC-V virt and sifive_u machines. This patch moves that change from the deprecated.rst file to the removed-features.rst file and the target-riscv.rst. Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 4f1c261e7f69045ab8bb8926d85fe1d35e48ea5b.1620081256.git.alistair.francis@wdc.com --- docs/system/deprecated.rst | 19 ------------------- docs/system/removed-features.rst | 5 +++++ docs/system/target-riscv.rst | 13 ++++++++++++- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index abbf8243a3..e2e0090878 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -52,25 +52,6 @@ pcspk-audiodev=``. ``tty`` and ``parport`` are aliases that will be removed. Instead, the actual backend names ``serial`` and ``parallel`` should be used. -RISC-V ``-bios`` (since 5.1) -'''''''''''''''''''''''''''' - -QEMU 4.1 introduced support for the -bios option in QEMU for RISC-V for the -RISC-V virt machine and sifive_u machine. QEMU 4.1 had no changes to the -default behaviour to avoid breakages. - -QEMU 5.1 changes the default behaviour from ``-bios none`` to ``-bios default``. - -QEMU 5.1 has three options: - 1. ``-bios default`` - This is the current default behavior if no -bios option - is included. This option will load the default OpenSBI firmware automatically. - The firmware is included with the QEMU release and no user interaction is - required. All a user needs to do is specify the kernel they want to boot - with the -kernel option - 2. ``-bios none`` - QEMU will not automatically load any firmware. It is up - to the user to load all the images they need. - 3. ``-bios `` - Tells QEMU to load the specified file as the firmwrae. - Short-form boolean options (since 6.0) '''''''''''''''''''''''''''''''''''''' diff --git a/docs/system/removed-features.rst b/docs/system/removed-features.rst index 1d22195b1d..2b21bd39ab 100644 --- a/docs/system/removed-features.rst +++ b/docs/system/removed-features.rst @@ -126,6 +126,11 @@ devices. Drives the board doesn't pick up can no longer be used with This option was undocumented and not used in the field. Use `-device usb-ccid`` instead. +RISC-V firmware not booted by default (removed in 5.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''' + +QEMU 5.1 changes the default behaviour from ``-bios none`` to ``-bios default`` +for the RISC-V ``virt`` machine and ``sifive_u`` machine. QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index 4b3c78382c..a5cc06b726 100644 --- a/docs/system/target-riscv.rst +++ b/docs/system/target-riscv.rst @@ -70,5 +70,16 @@ undocumented; you can get a complete list by running riscv/shakti-c riscv/sifive_u -RISC-V CPU features +RISC-V CPU firmware ------------------- + +When using the ``sifive_u`` or ``virt`` machine there are three different +firmware boot options: +1. ``-bios default`` - This is the default behaviour if no -bios option +is included. This option will load the default OpenSBI firmware automatically. +The firmware is included with the QEMU release and no user interaction is +required. All a user needs to do is specify the kernel they want to boot +with the -kernel option +2. ``-bios none`` - QEMU will not automatically load any firmware. It is up +to the user to load all the images they need. +3. ``-bios `` - Tells QEMU to load the specified file as the firmware. From bbf3d1b48fe170c0220a2267117d8a1ea9c2c2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 16 May 2021 22:53:33 +0200 Subject: [PATCH 11/32] target/riscv: Do not include 'pmp.h' in user emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Physical Memory Protection is a system feature. Avoid polluting the user-mode emulation by its definitions. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 20210516205333.696094-1-f4bug@amsat.org Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 7e879fb9ca..0619b491a4 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -97,7 +97,9 @@ enum { typedef struct CPURISCVState CPURISCVState; +#if !defined(CONFIG_USER_ONLY) #include "pmp.h" +#endif #define RV_VLEN_MAX 256 From 9a575d33fba497db48cda36273bde8710651888e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 14 May 2021 13:24:35 +0800 Subject: [PATCH 12/32] target/riscv: Remove unnecessary riscv_*_names[] declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit riscv_excp_names[] and riscv_intr_names[] are only referenced by target/riscv/cpu.c locally. Signed-off-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20210514052435.2203156-1-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 4 ++-- target/riscv/cpu.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 1f1cef1d6a..aa48bca830 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -51,7 +51,7 @@ const char * const riscv_fpr_regnames[] = { "f30/ft10", "f31/ft11" }; -const char * const riscv_excp_names[] = { +static const char * const riscv_excp_names[] = { "misaligned_fetch", "fault_fetch", "illegal_instruction", @@ -78,7 +78,7 @@ const char * const riscv_excp_names[] = { "guest_store_page_fault", }; -const char * const riscv_intr_names[] = { +static const char * const riscv_intr_names[] = { "u_software", "s_software", "vs_software", diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0619b491a4..0b22b0a523 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -320,8 +320,6 @@ static inline bool riscv_feature(CPURISCVState *env, int feature) extern const char * const riscv_int_regnames[]; extern const char * const riscv_fpr_regnames[]; -extern const char * const riscv_excp_names[]; -extern const char * const riscv_intr_names[]; const char *riscv_cpu_get_trap_name(target_ulong cause, bool async); void riscv_cpu_do_interrupt(CPUState *cpu); From a722701dd364b82dc115e94a29d767949f796000 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Wed, 19 May 2021 23:57:38 +0800 Subject: [PATCH 13/32] target/riscv: Dump CSR mscratch/sscratch/satp This dumps the CSR mscratch/sscratch/satp and meanwhile aligns the output of CSR mtval/stval. Signed-off-by: Changbin Du Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 20210519155738.20486-1-changbin.du@gmail.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index aa48bca830..ee2523f66b 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -286,12 +286,15 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) if (riscv_has_ext(env, RVH)) { qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause); } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->stval); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->stval); if (riscv_has_ext(env, RVH)) { qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval); qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2); } + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mscratch", env->mscratch); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sscratch", env->sscratch); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "satp ", env->satp); #endif for (i = 0; i < 32; i++) { From 787a4baf91fa2ff36b901c0b31ea73f3f0739415 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 21 May 2021 06:55:53 +0800 Subject: [PATCH 14/32] target/riscv/pmp: Add assert for ePMP operations Although we construct epmp_operation in such a way that it can only be between 0 and 15 Coverity complains that we don't handle the other possible cases. To fix Coverity and make it easier for humans to read add a default case to the switch statement that calls g_assert_not_reached(). Fixes: CID 1453108 Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Reviewed-by: LIU Zhiwei Message-id: ec5f225928eec448278c82fcb1f6805ee61dde82.1621550996.git.alistair.francis@wdc.com --- target/riscv/pmp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 78203291de..82ed020b10 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -402,6 +402,8 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, case 15: *allowed_privs = PMP_READ; break; + default: + g_assert_not_reached(); } } else { switch (epmp_operation) { @@ -433,6 +435,8 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, case 7: *allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC; break; + default: + g_assert_not_reached(); } } } From eee2d61e202b5bd49a5eb211e347e02c86287ef4 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Fri, 21 May 2021 13:48:16 +0800 Subject: [PATCH 15/32] target/riscv: Pass the same value to oprsz and maxsz. Since commit e2e7168a214b0ed98dc357bba96816486a289762, if oprsz is still zero(as we don't use this field), simd_desc will trigger an assert. Besides, tcg_gen_gvec_*_ptr calls simd_desc in it's implementation. Here we pass the value to maxsz and oprsz to bypass the assert. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Message-id: 20210521054816.1784297-1-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 89 ++++++++++++++----------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 47914a3b69..83d9a285ba 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -183,7 +183,7 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, * The first part is vlen in bytes, encoded in maxsz of simd_desc. * The second part is lmul, encoded in data of simd_desc. */ - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); @@ -334,7 +334,7 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2, mask = tcg_temp_new_ptr(); base = tcg_temp_new(); stride = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); gen_get_gpr(stride, rs2); @@ -462,7 +462,7 @@ static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, mask = tcg_temp_new_ptr(); index = tcg_temp_new_ptr(); base = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); @@ -594,7 +594,7 @@ static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); base = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); @@ -671,7 +671,7 @@ static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, mask = tcg_temp_new_ptr(); index = tcg_temp_new_ptr(); base = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); gen_get_gpr(base, rs1); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); @@ -831,7 +831,7 @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn, data = FIELD_DP32(data, VDATA, LMUL, s->lmul); tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), - cpu_env, 0, s->vlen / 8, data, fn); + cpu_env, s->vlen / 8, s->vlen / 8, data, fn); } gen_set_label(over); return true; @@ -874,7 +874,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, data = FIELD_DP32(data, VDATA, MLEN, s->mlen); data = FIELD_DP32(data, VDATA, VM, vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); @@ -1021,7 +1021,7 @@ static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm, data = FIELD_DP32(data, VDATA, MLEN, s->mlen); data = FIELD_DP32(data, VDATA, VM, vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); @@ -1119,7 +1119,7 @@ static bool do_opivv_widen(DisasContext *s, arg_rmrr *a, tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), - cpu_env, 0, s->vlen / 8, + cpu_env, s->vlen / 8, s->vlen / 8, data, fn); gen_set_label(over); return true; @@ -1207,7 +1207,7 @@ static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a, tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), - cpu_env, 0, s->vlen / 8, data, fn); + cpu_env, s->vlen / 8, s->vlen / 8, data, fn); gen_set_label(over); return true; } @@ -1284,8 +1284,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fns[s->sew]); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, \ + fns[s->sew]); \ gen_set_label(over); \ return true; \ } \ @@ -1473,8 +1474,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fns[s->sew]); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, \ + fns[s->sew]); \ gen_set_label(over); \ return true; \ } \ @@ -1690,7 +1692,7 @@ static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a) }; tcg_gen_ext_tl_i64(s1_i64, s1); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); fns[s->sew](dest, s1_i64, cpu_env, desc); @@ -1729,7 +1731,7 @@ static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a) s1 = tcg_const_i64(simm); dest = tcg_temp_new_ptr(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); fns[s->sew](dest, s1, cpu_env, desc); @@ -1838,8 +1840,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fns[s->sew - 1]); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, \ + fns[s->sew - 1]); \ gen_set_label(over); \ return true; \ } \ @@ -1863,7 +1866,7 @@ static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); @@ -1950,8 +1953,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fns[s->sew - 1]); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, \ + fns[s->sew - 1]); \ gen_set_label(over); \ return true; \ } \ @@ -2024,8 +2028,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fns[s->sew - 1]); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, \ + fns[s->sew - 1]); \ gen_set_label(over); \ return true; \ } \ @@ -2138,8 +2143,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fns[s->sew - 1]); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, \ + fns[s->sew - 1]); \ gen_set_label(over); \ return true; \ } \ @@ -2225,7 +2231,7 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a) tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); dest = tcg_temp_new_ptr(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd)); fns[s->sew - 1](dest, cpu_fpr[a->rs1], cpu_env, desc); @@ -2278,8 +2284,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fns[s->sew - 1]); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, \ + fns[s->sew - 1]); \ gen_set_label(over); \ return true; \ } \ @@ -2326,8 +2333,9 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fns[s->sew - 1]); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, \ + fns[s->sew - 1]); \ gen_set_label(over); \ return true; \ } \ @@ -2388,8 +2396,8 @@ static bool trans_##NAME(DisasContext *s, arg_r *a) \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ - vreg_ofs(s, a->rs2), cpu_env, 0, \ - s->vlen / 8, data, fn); \ + vreg_ofs(s, a->rs2), cpu_env, \ + s->vlen / 8, s->vlen / 8, data, fn); \ gen_set_label(over); \ return true; \ } \ @@ -2420,7 +2428,7 @@ static bool trans_vmpopc_m(DisasContext *s, arg_rmr *a) mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); dst = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -2452,7 +2460,7 @@ static bool trans_vmfirst_m(DisasContext *s, arg_rmr *a) mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); dst = tcg_temp_new(); - desc = tcg_const_i32(simd_desc(0, s->vlen / 8, data)); + desc = tcg_const_i32(simd_desc(s->vlen / 8, s->vlen / 8, data)); tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); @@ -2486,7 +2494,8 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), \ vreg_ofs(s, 0), vreg_ofs(s, a->rs2), \ - cpu_env, 0, s->vlen / 8, data, fn); \ + cpu_env, s->vlen / 8, s->vlen / 8, \ + data, fn); \ gen_set_label(over); \ return true; \ } \ @@ -2516,8 +2525,8 @@ static bool trans_viota_m(DisasContext *s, arg_viota_m *a) gen_helper_viota_m_w, gen_helper_viota_m_d, }; tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), - vreg_ofs(s, a->rs2), cpu_env, 0, - s->vlen / 8, data, fns[s->sew]); + vreg_ofs(s, a->rs2), cpu_env, + s->vlen / 8, s->vlen / 8, data, fns[s->sew]); gen_set_label(over); return true; } @@ -2542,7 +2551,8 @@ static bool trans_vid_v(DisasContext *s, arg_vid_v *a) gen_helper_vid_v_w, gen_helper_vid_v_d, }; tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), - cpu_env, 0, s->vlen / 8, data, fns[s->sew]); + cpu_env, s->vlen / 8, s->vlen / 8, + data, fns[s->sew]); gen_set_label(over); return true; } @@ -2895,7 +2905,8 @@ static bool trans_vcompress_vm(DisasContext *s, arg_r *a) data = FIELD_DP32(data, VDATA, LMUL, s->lmul); tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), - cpu_env, 0, s->vlen / 8, data, fns[s->sew]); + cpu_env, s->vlen / 8, s->vlen / 8, data, + fns[s->sew]); gen_set_label(over); return true; } From 00718208c127315d82f1f1f8383ef29bc478628e Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:02 +0800 Subject: [PATCH 16/32] target/riscv: reformat @sh format encoding for B-extension Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-2-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 8901ba1e1b..f75642bb0d 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -23,7 +23,7 @@ %rd 7:5 %sh5 20:5 -%sh10 20:10 +%sh7 20:7 %csr 20:12 %rm 12:3 %nf 29:3 !function=ex_plus_1 @@ -59,7 +59,7 @@ @u .................... ..... ....... &u imm=%imm_u %rd @j .................... ..... ....... &j imm=%imm_j %rd -@sh ...... ...... ..... ... ..... ....... &shift shamt=%sh10 %rs1 %rd +@sh ...... ...... ..... ... ..... ....... &shift shamt=%sh7 %rs1 %rd @csr ............ ..... ... ..... ....... %csr %rs1 %rd @atom_ld ..... aq:1 rl:1 ..... ........ ..... ....... &atomic rs2=0 %rs1 %rd @@ -125,9 +125,9 @@ sltiu ............ ..... 011 ..... 0010011 @i xori ............ ..... 100 ..... 0010011 @i ori ............ ..... 110 ..... 0010011 @i andi ............ ..... 111 ..... 0010011 @i -slli 00.... ...... ..... 001 ..... 0010011 @sh -srli 00.... ...... ..... 101 ..... 0010011 @sh -srai 01.... ...... ..... 101 ..... 0010011 @sh +slli 00000. ...... ..... 001 ..... 0010011 @sh +srli 00000. ...... ..... 101 ..... 0010011 @sh +srai 01000. ...... ..... 101 ..... 0010011 @sh add 0000000 ..... ..... 000 ..... 0110011 @r sub 0100000 ..... ..... 000 ..... 0110011 @r sll 0000000 ..... ..... 001 ..... 0110011 @r From 438240185a9456747b19a29290018316271a3762 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:03 +0800 Subject: [PATCH 17/32] target/riscv: rvb: count leading/trailing zeros Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-3-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 1 + target/riscv/insn32.decode | 11 ++++++- target/riscv/insn_trans/trans_rvb.c.inc | 44 +++++++++++++++++++++++++ target/riscv/translate.c | 38 +++++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 target/riscv/insn_trans/trans_rvb.c.inc diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0b22b0a523..c0c99c3d8d 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -67,6 +67,7 @@ #define RVS RV('S') #define RVU RV('U') #define RVH RV('H') +#define RVB RV('B') /* 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 diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index f75642bb0d..9a2ffab150 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -41,6 +41,7 @@ &i imm rs1 rd &j imm rd &r rd rs1 rs2 +&r2 rd rs1 &s imm rs1 rs2 &u imm rd &shift shamt rs1 rd @@ -68,7 +69,7 @@ @r4_rm ..... .. ..... ..... ... ..... ....... %rs3 %rs2 %rs1 %rm %rd @r_rm ....... ..... ..... ... ..... ....... %rs2 %rs1 %rm %rd @r2_rm ....... ..... ..... ... ..... ....... %rs1 %rm %rd -@r2 ....... ..... ..... ... ..... ....... %rs1 %rd +@r2 ....... ..... ..... ... ..... ....... &r2 %rs1 %rd @r2_nfvm ... ... vm:1 ..... ..... ... ..... ....... &r2nfvm %nf %rs1 %rd @r2_vm ...... vm:1 ..... ..... ... ..... ....... &rmr %rs2 %rd @r1_vm ...... vm:1 ..... ..... ... ..... ....... %rd @@ -657,3 +658,11 @@ vamomind_v 10000 . . ..... ..... 111 ..... 0101111 @r_wdvm vamomaxd_v 10100 . . ..... ..... 111 ..... 0101111 @r_wdvm vamominud_v 11000 . . ..... ..... 111 ..... 0101111 @r_wdvm vamomaxud_v 11100 . . ..... ..... 111 ..... 0101111 @r_wdvm + +# *** RV32B Standard Extension *** +clz 011000 000000 ..... 001 ..... 0010011 @r2 +ctz 011000 000001 ..... 001 ..... 0010011 @r2 + +# *** RV64B Standard Extension (in addition to RV32B) *** +clzw 0110000 00000 ..... 001 ..... 0011011 @r2 +ctzw 0110000 00001 ..... 001 ..... 0011011 @r2 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc new file mode 100644 index 0000000000..157b4e3c41 --- /dev/null +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -0,0 +1,44 @@ +/* + * RISC-V translation routines for the RVB Standard Extension. + * + * Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com + * Copyright (c) 2020 Frank Chang, frank.chang@sifive.com + * + * 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 . + */ + +static bool trans_clz(DisasContext *ctx, arg_clz *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_unary(ctx, a, gen_clz); +} + +static bool trans_ctz(DisasContext *ctx, arg_ctz *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_unary(ctx, a, gen_ctz); +} + +static bool trans_clzw(DisasContext *ctx, arg_clzw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_unary(ctx, a, gen_clzw); +} + +static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_unary(ctx, a, gen_ctzw); +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index e945352bca..60fac0fe27 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -548,6 +548,19 @@ static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a, return true; } +static void gen_ctzw(TCGv ret, TCGv arg1) +{ + tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); + tcg_gen_ctzi_tl(ret, ret, 64); +} + +static void gen_clzw(TCGv ret, TCGv arg1) +{ + tcg_gen_ext32u_tl(ret, arg1); + tcg_gen_clzi_tl(ret, ret, 64); + tcg_gen_subi_tl(ret, ret, 32); +} + static bool gen_arith(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { @@ -593,6 +606,30 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) return cpu_ldl_code(env, pc); } +static void gen_ctz(TCGv ret, TCGv arg1) +{ + tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS); +} + +static void gen_clz(TCGv ret, TCGv arg1) +{ + tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS); +} + +static bool gen_unary(DisasContext *ctx, arg_r2 *a, + void(*func)(TCGv, TCGv)) +{ + TCGv source = tcg_temp_new(); + + gen_get_gpr(source, a->rs1); + + (*func)(source, source); + + gen_set_gpr(a->rd, source); + tcg_temp_free(source); + return true; +} + /* Include insn module translation function */ #include "insn_trans/trans_rvi.c.inc" #include "insn_trans/trans_rvm.c.inc" @@ -601,6 +638,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) #include "insn_trans/trans_rvd.c.inc" #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_privileged.c.inc" /* Include the auto-generated decoder for 16 bit insn */ From 1e16310ca1bd368f20eb93683cc37389d5db185d Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Thu, 6 May 2021 00:06:04 +0800 Subject: [PATCH 18/32] target/riscv: rvb: count bits set Signed-off-by: Kito Cheng Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Signed-off-by: Frank Chang Message-id: 20210505160620.15723-4-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 2 ++ target/riscv/insn_trans/trans_rvb.c.inc | 13 +++++++++++++ target/riscv/translate.c | 6 ++++++ 3 files changed, 21 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 9a2ffab150..6f7671872d 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -662,7 +662,9 @@ vamomaxud_v 11100 . . ..... ..... 111 ..... 0101111 @r_wdvm # *** RV32B Standard Extension *** clz 011000 000000 ..... 001 ..... 0010011 @r2 ctz 011000 000001 ..... 001 ..... 0010011 @r2 +cpop 011000 000010 ..... 001 ..... 0010011 @r2 # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 ctzw 0110000 00001 ..... 001 ..... 0011011 @r2 +cpopw 0110000 00010 ..... 001 ..... 0011011 @r2 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 157b4e3c41..4a5d271b43 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -29,6 +29,12 @@ static bool trans_ctz(DisasContext *ctx, arg_ctz *a) return gen_unary(ctx, a, gen_ctz); } +static bool trans_cpop(DisasContext *ctx, arg_cpop *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_unary(ctx, a, tcg_gen_ctpop_tl); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -42,3 +48,10 @@ static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a) REQUIRE_EXT(ctx, RVB); return gen_unary(ctx, a, gen_ctzw); } + +static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_unary(ctx, a, gen_cpopw); +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 60fac0fe27..c1a30c2172 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -561,6 +561,12 @@ static void gen_clzw(TCGv ret, TCGv arg1) tcg_gen_subi_tl(ret, ret, 32); } +static void gen_cpopw(TCGv ret, TCGv arg1) +{ + tcg_gen_ext32u_tl(arg1, arg1); + tcg_gen_ctpop_tl(ret, arg1); +} + static bool gen_arith(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { From 0bcdb686e586d8f5bfa2b2f9261d75a76b15e3cb Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:05 +0800 Subject: [PATCH 19/32] target/riscv: rvb: logic-with-negate Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-5-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 3 +++ target/riscv/insn_trans/trans_rvb.c.inc | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 6f7671872d..a4d95ea621 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -663,6 +663,9 @@ vamomaxud_v 11100 . . ..... ..... 111 ..... 0101111 @r_wdvm clz 011000 000000 ..... 001 ..... 0010011 @r2 ctz 011000 000001 ..... 001 ..... 0010011 @r2 cpop 011000 000010 ..... 001 ..... 0010011 @r2 +andn 0100000 .......... 111 ..... 0110011 @r +orn 0100000 .......... 110 ..... 0110011 @r +xnor 0100000 .......... 100 ..... 0110011 @r # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 4a5d271b43..b8676785c6 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -35,6 +35,24 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a) return gen_unary(ctx, a, tcg_gen_ctpop_tl); } +static bool trans_andn(DisasContext *ctx, arg_andn *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, tcg_gen_andc_tl); +} + +static bool trans_orn(DisasContext *ctx, arg_orn *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, tcg_gen_orc_tl); +} + +static bool trans_xnor(DisasContext *ctx, arg_xnor *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, tcg_gen_eqv_tl); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); From 6ef5843182382f6a84995590ad91047b0f2bc1fa Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:06 +0800 Subject: [PATCH 20/32] target/riscv: rvb: pack two words into one register Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-6-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 6 ++++ target/riscv/insn_trans/trans_rvb.c.inc | 32 ++++++++++++++++++++ target/riscv/translate.c | 40 +++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index a4d95ea621..9b2fd4b6fe 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -666,8 +666,14 @@ cpop 011000 000010 ..... 001 ..... 0010011 @r2 andn 0100000 .......... 111 ..... 0110011 @r orn 0100000 .......... 110 ..... 0110011 @r xnor 0100000 .......... 100 ..... 0110011 @r +pack 0000100 .......... 100 ..... 0110011 @r +packu 0100100 .......... 100 ..... 0110011 @r +packh 0000100 .......... 111 ..... 0110011 @r # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 ctzw 0110000 00001 ..... 001 ..... 0011011 @r2 cpopw 0110000 00010 ..... 001 ..... 0011011 @r2 + +packw 0000100 .......... 100 ..... 0111011 @r +packuw 0100100 .......... 100 ..... 0111011 @r diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index b8676785c6..770205f96f 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -53,6 +53,24 @@ static bool trans_xnor(DisasContext *ctx, arg_xnor *a) return gen_arith(ctx, a, tcg_gen_eqv_tl); } +static bool trans_pack(DisasContext *ctx, arg_pack *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, gen_pack); +} + +static bool trans_packu(DisasContext *ctx, arg_packu *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, gen_packu); +} + +static bool trans_packh(DisasContext *ctx, arg_packh *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, gen_packh); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -73,3 +91,17 @@ static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) REQUIRE_EXT(ctx, RVB); return gen_unary(ctx, a, gen_cpopw); } + +static bool trans_packw(DisasContext *ctx, arg_packw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, gen_packw); +} + +static bool trans_packuw(DisasContext *ctx, arg_packuw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, gen_packuw); +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index c1a30c2172..5f1a3c694f 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -548,6 +548,29 @@ static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a, return true; } +static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_deposit_tl(ret, arg1, arg2, + TARGET_LONG_BITS / 2, + TARGET_LONG_BITS / 2); +} + +static void gen_packu(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t = tcg_temp_new(); + tcg_gen_shri_tl(t, arg1, TARGET_LONG_BITS / 2); + tcg_gen_deposit_tl(ret, arg2, t, 0, TARGET_LONG_BITS / 2); + tcg_temp_free(t); +} + +static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t = tcg_temp_new(); + tcg_gen_ext8u_tl(t, arg2); + tcg_gen_deposit_tl(ret, arg1, t, 8, TARGET_LONG_BITS - 8); + tcg_temp_free(t); +} + static void gen_ctzw(TCGv ret, TCGv arg1) { tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); @@ -567,6 +590,23 @@ static void gen_cpopw(TCGv ret, TCGv arg1) tcg_gen_ctpop_tl(ret, arg1); } +static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t = tcg_temp_new(); + tcg_gen_ext16s_tl(t, arg2); + tcg_gen_deposit_tl(ret, arg1, t, 16, 48); + tcg_temp_free(t); +} + +static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t = tcg_temp_new(); + tcg_gen_shri_tl(t, arg1, 16); + tcg_gen_deposit_tl(ret, arg2, t, 0, 16); + tcg_gen_ext32s_tl(ret, ret); + tcg_temp_free(t); +} + static bool gen_arith(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { From 82655d8115f022a0132a74e0229dc7fa9b623b87 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:07 +0800 Subject: [PATCH 21/32] target/riscv: rvb: min/max instructions Signed-off-by: Kito Cheng Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Signed-off-by: Frank Chang Message-id: 20210505160620.15723-7-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 4 ++++ target/riscv/insn_trans/trans_rvb.c.inc | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 9b2fd4b6fe..81dfdfbafd 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -669,6 +669,10 @@ xnor 0100000 .......... 100 ..... 0110011 @r pack 0000100 .......... 100 ..... 0110011 @r packu 0100100 .......... 100 ..... 0110011 @r packh 0000100 .......... 111 ..... 0110011 @r +min 0000101 .......... 100 ..... 0110011 @r +minu 0000101 .......... 101 ..... 0110011 @r +max 0000101 .......... 110 ..... 0110011 @r +maxu 0000101 .......... 111 ..... 0110011 @r # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 770205f96f..5a4fc02f70 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -71,6 +71,30 @@ static bool trans_packh(DisasContext *ctx, arg_packh *a) return gen_arith(ctx, a, gen_packh); } +static bool trans_min(DisasContext *ctx, arg_min *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, tcg_gen_smin_tl); +} + +static bool trans_max(DisasContext *ctx, arg_max *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, tcg_gen_smax_tl); +} + +static bool trans_minu(DisasContext *ctx, arg_minu *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, tcg_gen_umin_tl); +} + +static bool trans_maxu(DisasContext *ctx, arg_maxu *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, tcg_gen_umax_tl); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); From 2a81973829d0e77bbfdcf9ca217de8fde5cff88f Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:08 +0800 Subject: [PATCH 22/32] target/riscv: rvb: sign-extend instructions Signed-off-by: Kito Cheng Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Signed-off-by: Frank Chang Message-id: 20210505160620.15723-8-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 3 +++ target/riscv/insn_trans/trans_rvb.c.inc | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 81dfdfbafd..9361984634 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -663,6 +663,9 @@ vamomaxud_v 11100 . . ..... ..... 111 ..... 0101111 @r_wdvm clz 011000 000000 ..... 001 ..... 0010011 @r2 ctz 011000 000001 ..... 001 ..... 0010011 @r2 cpop 011000 000010 ..... 001 ..... 0010011 @r2 +sext_b 011000 000100 ..... 001 ..... 0010011 @r2 +sext_h 011000 000101 ..... 001 ..... 0010011 @r2 + andn 0100000 .......... 111 ..... 0110011 @r orn 0100000 .......... 110 ..... 0110011 @r xnor 0100000 .......... 100 ..... 0110011 @r diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 5a4fc02f70..3d594e8cb4 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -95,6 +95,18 @@ static bool trans_maxu(DisasContext *ctx, arg_maxu *a) return gen_arith(ctx, a, tcg_gen_umax_tl); } +static bool trans_sext_b(DisasContext *ctx, arg_sext_b *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_unary(ctx, a, tcg_gen_ext8s_tl); +} + +static bool trans_sext_h(DisasContext *ctx, arg_sext_h *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_unary(ctx, a, tcg_gen_ext16s_tl); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); From 981d3568dfa8b5180de1719fa590db558e9720b7 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Thu, 6 May 2021 00:06:09 +0800 Subject: [PATCH 23/32] target/riscv: add gen_shifti() and gen_shiftiw() helper functions Add gen_shifti() and gen_shiftiw() helper functions to reuse the same interfaces for immediate shift instructions. Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-9-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 54 ++----------------------- target/riscv/translate.c | 39 ++++++++++++++++++ 2 files changed, 43 insertions(+), 50 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index bd93f634cf..6e736c9d0d 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -268,54 +268,17 @@ static bool trans_andi(DisasContext *ctx, arg_andi *a) } static bool trans_slli(DisasContext *ctx, arg_slli *a) { - if (a->shamt >= TARGET_LONG_BITS) { - return false; - } - - if (a->rd != 0) { - TCGv t = tcg_temp_new(); - gen_get_gpr(t, a->rs1); - - tcg_gen_shli_tl(t, t, a->shamt); - - gen_set_gpr(a->rd, t); - tcg_temp_free(t); - } /* NOP otherwise */ - return true; + return gen_shifti(ctx, a, tcg_gen_shl_tl); } static bool trans_srli(DisasContext *ctx, arg_srli *a) { - if (a->shamt >= TARGET_LONG_BITS) { - return false; - } - - if (a->rd != 0) { - TCGv t = tcg_temp_new(); - gen_get_gpr(t, a->rs1); - - tcg_gen_shri_tl(t, t, a->shamt); - gen_set_gpr(a->rd, t); - tcg_temp_free(t); - } /* NOP otherwise */ - return true; + return gen_shifti(ctx, a, tcg_gen_shr_tl); } static bool trans_srai(DisasContext *ctx, arg_srai *a) { - if (a->shamt >= TARGET_LONG_BITS) { - return false; - } - - if (a->rd != 0) { - TCGv t = tcg_temp_new(); - gen_get_gpr(t, a->rs1); - - tcg_gen_sari_tl(t, t, a->shamt); - gen_set_gpr(a->rd, t); - tcg_temp_free(t); - } /* NOP otherwise */ - return true; + return gen_shifti(ctx, a, tcg_gen_sar_tl); } static bool trans_add(DisasContext *ctx, arg_add *a) @@ -377,16 +340,7 @@ static bool trans_addiw(DisasContext *ctx, arg_addiw *a) static bool trans_slliw(DisasContext *ctx, arg_slliw *a) { REQUIRE_64BIT(ctx); - TCGv source1; - source1 = tcg_temp_new(); - gen_get_gpr(source1, a->rs1); - - tcg_gen_shli_tl(source1, source1, a->shamt); - tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); - - tcg_temp_free(source1); - return true; + return gen_shiftiw(ctx, a, tcg_gen_shl_tl); } static bool trans_srliw(DisasContext *ctx, arg_srliw *a) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 5f1a3c694f..292cf09932 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -652,6 +652,45 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) return cpu_ldl_code(env, pc); } +static bool gen_shifti(DisasContext *ctx, arg_shift *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + if (a->shamt >= TARGET_LONG_BITS) { + return false; + } + + TCGv source1 = tcg_temp_new(); + TCGv source2 = tcg_temp_new(); + + gen_get_gpr(source1, a->rs1); + + tcg_gen_movi_tl(source2, a->shamt); + (*func)(source1, source1, source2); + + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + tcg_temp_free(source2); + return true; +} + +static bool gen_shiftiw(DisasContext *ctx, arg_shift *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + TCGv source1 = tcg_temp_new(); + TCGv source2 = tcg_temp_new(); + + gen_get_gpr(source1, a->rs1); + tcg_gen_movi_tl(source2, a->shamt); + + (*func)(source1, source1, source2); + tcg_gen_ext32s_tl(source1, source1); + + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + tcg_temp_free(source2); + return true; +} + static void gen_ctz(TCGv ret, TCGv arg1) { tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS); From 23cd17773bdc559877cc81b7129c4dd41ae53e4f Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Thu, 6 May 2021 00:06:10 +0800 Subject: [PATCH 24/32] target/riscv: rvb: single-bit instructions Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-10-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 17 +++++ target/riscv/insn_trans/trans_rvb.c.inc | 97 +++++++++++++++++++++++++ target/riscv/translate.c | 61 ++++++++++++++++ 3 files changed, 175 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 9361984634..433b601b93 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -676,6 +676,15 @@ min 0000101 .......... 100 ..... 0110011 @r minu 0000101 .......... 101 ..... 0110011 @r max 0000101 .......... 110 ..... 0110011 @r maxu 0000101 .......... 111 ..... 0110011 @r +bset 0010100 .......... 001 ..... 0110011 @r +bclr 0100100 .......... 001 ..... 0110011 @r +binv 0110100 .......... 001 ..... 0110011 @r +bext 0100100 .......... 101 ..... 0110011 @r + +bseti 00101. ........... 001 ..... 0010011 @sh +bclri 01001. ........... 001 ..... 0010011 @sh +binvi 01101. ........... 001 ..... 0010011 @sh +bexti 01001. ........... 101 ..... 0010011 @sh # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 @@ -684,3 +693,11 @@ cpopw 0110000 00010 ..... 001 ..... 0011011 @r2 packw 0000100 .......... 100 ..... 0111011 @r packuw 0100100 .......... 100 ..... 0111011 @r +bsetw 0010100 .......... 001 ..... 0111011 @r +bclrw 0100100 .......... 001 ..... 0111011 @r +binvw 0110100 .......... 001 ..... 0111011 @r +bextw 0100100 .......... 101 ..... 0111011 @r + +bsetiw 0010100 .......... 001 ..... 0011011 @sh5 +bclriw 0100100 .......... 001 ..... 0011011 @sh5 +binviw 0110100 .......... 001 ..... 0011011 @sh5 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 3d594e8cb4..69e5af44a1 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -107,6 +107,54 @@ static bool trans_sext_h(DisasContext *ctx, arg_sext_h *a) return gen_unary(ctx, a, tcg_gen_ext16s_tl); } +static bool trans_bset(DisasContext *ctx, arg_bset *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, gen_bset); +} + +static bool trans_bseti(DisasContext *ctx, arg_bseti *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shifti(ctx, a, gen_bset); +} + +static bool trans_bclr(DisasContext *ctx, arg_bclr *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, gen_bclr); +} + +static bool trans_bclri(DisasContext *ctx, arg_bclri *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shifti(ctx, a, gen_bclr); +} + +static bool trans_binv(DisasContext *ctx, arg_binv *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, gen_binv); +} + +static bool trans_binvi(DisasContext *ctx, arg_binvi *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shifti(ctx, a, gen_binv); +} + +static bool trans_bext(DisasContext *ctx, arg_bext *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, gen_bext); +} + +static bool trans_bexti(DisasContext *ctx, arg_bexti *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shifti(ctx, a, gen_bext); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -141,3 +189,52 @@ static bool trans_packuw(DisasContext *ctx, arg_packuw *a) REQUIRE_EXT(ctx, RVB); return gen_arith(ctx, a, gen_packuw); } + +static bool trans_bsetw(DisasContext *ctx, arg_bsetw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_bset); +} + +static bool trans_bsetiw(DisasContext *ctx, arg_bsetiw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftiw(ctx, a, gen_bset); +} + +static bool trans_bclrw(DisasContext *ctx, arg_bclrw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_bclr); +} + +static bool trans_bclriw(DisasContext *ctx, arg_bclriw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftiw(ctx, a, gen_bclr); +} + +static bool trans_binvw(DisasContext *ctx, arg_binvw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_binv); +} + +static bool trans_binviw(DisasContext *ctx, arg_binviw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftiw(ctx, a, gen_binv); +} + +static bool trans_bextw(DisasContext *ctx, arg_bextw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_bext); +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 292cf09932..e12240d125 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -571,6 +571,48 @@ static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2) tcg_temp_free(t); } +static void gen_sbop_mask(TCGv ret, TCGv shamt) +{ + tcg_gen_movi_tl(ret, 1); + tcg_gen_shl_tl(ret, ret, shamt); +} + +static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt) +{ + TCGv t = tcg_temp_new(); + + gen_sbop_mask(t, shamt); + tcg_gen_or_tl(ret, arg1, t); + + tcg_temp_free(t); +} + +static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt) +{ + TCGv t = tcg_temp_new(); + + gen_sbop_mask(t, shamt); + tcg_gen_andc_tl(ret, arg1, t); + + tcg_temp_free(t); +} + +static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt) +{ + TCGv t = tcg_temp_new(); + + gen_sbop_mask(t, shamt); + tcg_gen_xor_tl(ret, arg1, t); + + tcg_temp_free(t); +} + +static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt) +{ + tcg_gen_shr_tl(ret, arg1, shamt); + tcg_gen_andi_tl(ret, ret, 1); +} + static void gen_ctzw(TCGv ret, TCGv arg1) { tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); @@ -673,6 +715,25 @@ static bool gen_shifti(DisasContext *ctx, arg_shift *a, return true; } +static bool gen_shiftw(DisasContext *ctx, arg_r *a, + void(*func)(TCGv, TCGv, TCGv)) +{ + TCGv source1 = tcg_temp_new(); + TCGv source2 = tcg_temp_new(); + + gen_get_gpr(source1, a->rs1); + gen_get_gpr(source2, a->rs2); + + tcg_gen_andi_tl(source2, source2, 31); + (*func)(source1, source1, source2); + tcg_gen_ext32s_tl(source1, source1); + + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + tcg_temp_free(source2); + return true; +} + static bool gen_shiftiw(DisasContext *ctx, arg_shift *a, void(*func)(TCGv, TCGv, TCGv)) { From 91d8fc676819eff4ffcb7a8038e6de7d1dd381d3 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:11 +0800 Subject: [PATCH 25/32] target/riscv: rvb: shift ones Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-11-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 8 ++++ target/riscv/insn_trans/trans_rvb.c.inc | 52 +++++++++++++++++++++++++ target/riscv/translate.c | 14 +++++++ 3 files changed, 74 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 433b601b93..6bc9bbae9e 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -680,11 +680,15 @@ bset 0010100 .......... 001 ..... 0110011 @r bclr 0100100 .......... 001 ..... 0110011 @r binv 0110100 .......... 001 ..... 0110011 @r bext 0100100 .......... 101 ..... 0110011 @r +slo 0010000 .......... 001 ..... 0110011 @r +sro 0010000 .......... 101 ..... 0110011 @r bseti 00101. ........... 001 ..... 0010011 @sh bclri 01001. ........... 001 ..... 0010011 @sh binvi 01101. ........... 001 ..... 0010011 @sh bexti 01001. ........... 101 ..... 0010011 @sh +sloi 00100. ........... 001 ..... 0010011 @sh +sroi 00100. ........... 101 ..... 0010011 @sh # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 @@ -697,7 +701,11 @@ bsetw 0010100 .......... 001 ..... 0111011 @r bclrw 0100100 .......... 001 ..... 0111011 @r binvw 0110100 .......... 001 ..... 0111011 @r bextw 0100100 .......... 101 ..... 0111011 @r +slow 0010000 .......... 001 ..... 0111011 @r +srow 0010000 .......... 101 ..... 0111011 @r bsetiw 0010100 .......... 001 ..... 0011011 @sh5 bclriw 0100100 .......... 001 ..... 0011011 @sh5 binviw 0110100 .......... 001 ..... 0011011 @sh5 +sloiw 0010000 .......... 001 ..... 0011011 @sh5 +sroiw 0010000 .......... 101 ..... 0011011 @sh5 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 69e5af44a1..28640322c4 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -155,6 +155,30 @@ static bool trans_bexti(DisasContext *ctx, arg_bexti *a) return gen_shifti(ctx, a, gen_bext); } +static bool trans_slo(DisasContext *ctx, arg_slo *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, gen_slo); +} + +static bool trans_sloi(DisasContext *ctx, arg_sloi *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shifti(ctx, a, gen_slo); +} + +static bool trans_sro(DisasContext *ctx, arg_sro *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, gen_sro); +} + +static bool trans_sroi(DisasContext *ctx, arg_sroi *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shifti(ctx, a, gen_sro); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -238,3 +262,31 @@ static bool trans_bextw(DisasContext *ctx, arg_bextw *a) REQUIRE_EXT(ctx, RVB); return gen_shiftw(ctx, a, gen_bext); } + +static bool trans_slow(DisasContext *ctx, arg_slow *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_slo); +} + +static bool trans_sloiw(DisasContext *ctx, arg_sloiw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftiw(ctx, a, gen_slo); +} + +static bool trans_srow(DisasContext *ctx, arg_srow *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_sro); +} + +static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftiw(ctx, a, gen_sro); +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index e12240d125..088cf9f767 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -613,6 +613,20 @@ static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt) tcg_gen_andi_tl(ret, ret, 1); } +static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_not_tl(ret, arg1); + tcg_gen_shl_tl(ret, ret, arg2); + tcg_gen_not_tl(ret, ret); +} + +static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_not_tl(ret, arg1); + tcg_gen_shr_tl(ret, ret, arg2); + tcg_gen_not_tl(ret, ret); +} + static void gen_ctzw(TCGv ret, TCGv arg1) { tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); From e58529a8d03ab8e9127f3e7cdf757ff84af75698 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:12 +0800 Subject: [PATCH 26/32] target/riscv: rvb: rotate (left/right) Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-12-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 6 ++++ target/riscv/insn_trans/trans_rvb.c.inc | 39 +++++++++++++++++++++++++ target/riscv/translate.c | 36 +++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 6bc9bbae9e..71a9a182c0 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -682,6 +682,8 @@ binv 0110100 .......... 001 ..... 0110011 @r bext 0100100 .......... 101 ..... 0110011 @r slo 0010000 .......... 001 ..... 0110011 @r sro 0010000 .......... 101 ..... 0110011 @r +ror 0110000 .......... 101 ..... 0110011 @r +rol 0110000 .......... 001 ..... 0110011 @r bseti 00101. ........... 001 ..... 0010011 @sh bclri 01001. ........... 001 ..... 0010011 @sh @@ -689,6 +691,7 @@ binvi 01101. ........... 001 ..... 0010011 @sh bexti 01001. ........... 101 ..... 0010011 @sh sloi 00100. ........... 001 ..... 0010011 @sh sroi 00100. ........... 101 ..... 0010011 @sh +rori 01100. ........... 101 ..... 0010011 @sh # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 @@ -703,9 +706,12 @@ binvw 0110100 .......... 001 ..... 0111011 @r bextw 0100100 .......... 101 ..... 0111011 @r slow 0010000 .......... 001 ..... 0111011 @r srow 0010000 .......... 101 ..... 0111011 @r +rorw 0110000 .......... 101 ..... 0111011 @r +rolw 0110000 .......... 001 ..... 0111011 @r bsetiw 0010100 .......... 001 ..... 0011011 @sh5 bclriw 0100100 .......... 001 ..... 0011011 @sh5 binviw 0110100 .......... 001 ..... 0011011 @sh5 sloiw 0010000 .......... 001 ..... 0011011 @sh5 sroiw 0010000 .......... 101 ..... 0011011 @sh5 +roriw 0110000 .......... 101 ..... 0011011 @sh5 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 28640322c4..429738db15 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -179,6 +179,24 @@ static bool trans_sroi(DisasContext *ctx, arg_sroi *a) return gen_shifti(ctx, a, gen_sro); } +static bool trans_ror(DisasContext *ctx, arg_ror *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, tcg_gen_rotr_tl); +} + +static bool trans_rori(DisasContext *ctx, arg_rori *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shifti(ctx, a, tcg_gen_rotr_tl); +} + +static bool trans_rol(DisasContext *ctx, arg_rol *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, tcg_gen_rotl_tl); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -290,3 +308,24 @@ static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a) REQUIRE_EXT(ctx, RVB); return gen_shiftiw(ctx, a, gen_sro); } + +static bool trans_rorw(DisasContext *ctx, arg_rorw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_rorw); +} + +static bool trans_roriw(DisasContext *ctx, arg_roriw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftiw(ctx, a, gen_rorw); +} + +static bool trans_rolw(DisasContext *ctx, arg_rolw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_rolw); +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 088cf9f767..c09b93f1b8 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -663,6 +663,42 @@ static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2) tcg_temp_free(t); } +static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + /* truncate to 32-bits */ + tcg_gen_trunc_tl_i32(t1, arg1); + tcg_gen_trunc_tl_i32(t2, arg2); + + tcg_gen_rotr_i32(t1, t1, t2); + + /* sign-extend 64-bits */ + tcg_gen_ext_i32_tl(ret, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); +} + +static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + /* truncate to 32-bits */ + tcg_gen_trunc_tl_i32(t1, arg1); + tcg_gen_trunc_tl_i32(t2, arg2); + + tcg_gen_rotl_i32(t1, t1, t2); + + /* sign-extend 64-bits */ + tcg_gen_ext_i32_tl(ret, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); +} + static bool gen_arith(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { From 831ec7f3d1ede387eca225ccaccb2845cbbca85e Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Thu, 6 May 2021 00:06:13 +0800 Subject: [PATCH 27/32] target/riscv: rvb: generalized reverse Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Message-id: 20210505160620.15723-13-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/bitmanip_helper.c | 64 +++++++++++++++++++++++++ target/riscv/helper.h | 4 ++ target/riscv/insn32.decode | 4 ++ target/riscv/insn_trans/trans_rvb.c.inc | 31 ++++++++++++ target/riscv/meson.build | 1 + target/riscv/translate.c | 28 +++++++++++ 6 files changed, 132 insertions(+) create mode 100644 target/riscv/bitmanip_helper.c diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/bitmanip_helper.c new file mode 100644 index 0000000000..c625adaded --- /dev/null +++ b/target/riscv/bitmanip_helper.c @@ -0,0 +1,64 @@ +/* + * RISC-V Bitmanip Extension Helpers for QEMU. + * + * Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com + * Copyright (c) 2020 Frank Chang, frank.chang@sifive.com + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/host-utils.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" +#include "tcg/tcg.h" + +static const uint64_t adjacent_masks[] = { + dup_const(MO_8, 0x55), + dup_const(MO_8, 0x33), + dup_const(MO_8, 0x0f), + dup_const(MO_16, 0xff), + dup_const(MO_32, 0xffff), + UINT32_MAX +}; + +static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift) +{ + return ((x & mask) << shift) | ((x & ~mask) >> shift); +} + +static target_ulong do_grev(target_ulong rs1, + target_ulong rs2, + int bits) +{ + target_ulong x = rs1; + int i, shift; + + for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) { + if (rs2 & shift) { + x = do_swap(x, adjacent_masks[i], shift); + } + } + + return x; +} + +target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2) +{ + return do_grev(rs1, rs2, TARGET_LONG_BITS); +} + +target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2) +{ + return do_grev(rs1, rs2, 32); +} diff --git a/target/riscv/helper.h b/target/riscv/helper.h index c7267593c3..f81b8faf3b 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -58,6 +58,10 @@ DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, tl) DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, tl) DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64) +/* Bitmanip */ +DEF_HELPER_FLAGS_2(grev, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(grevw, TCG_CALL_NO_RWG_SE, tl, tl, tl) + /* Special functions */ DEF_HELPER_3(csrrw, tl, env, tl, tl) DEF_HELPER_4(csrrs, tl, env, tl, tl, tl) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 71a9a182c0..6b5e276a9f 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -684,6 +684,7 @@ slo 0010000 .......... 001 ..... 0110011 @r sro 0010000 .......... 101 ..... 0110011 @r ror 0110000 .......... 101 ..... 0110011 @r rol 0110000 .......... 001 ..... 0110011 @r +grev 0110100 .......... 101 ..... 0110011 @r bseti 00101. ........... 001 ..... 0010011 @sh bclri 01001. ........... 001 ..... 0010011 @sh @@ -692,6 +693,7 @@ bexti 01001. ........... 101 ..... 0010011 @sh sloi 00100. ........... 001 ..... 0010011 @sh sroi 00100. ........... 101 ..... 0010011 @sh rori 01100. ........... 101 ..... 0010011 @sh +grevi 01101. ........... 101 ..... 0010011 @sh # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 @@ -708,6 +710,7 @@ slow 0010000 .......... 001 ..... 0111011 @r srow 0010000 .......... 101 ..... 0111011 @r rorw 0110000 .......... 101 ..... 0111011 @r rolw 0110000 .......... 001 ..... 0111011 @r +grevw 0110100 .......... 101 ..... 0111011 @r bsetiw 0010100 .......... 001 ..... 0011011 @sh5 bclriw 0100100 .......... 001 ..... 0011011 @sh5 @@ -715,3 +718,4 @@ binviw 0110100 .......... 001 ..... 0011011 @sh5 sloiw 0010000 .......... 001 ..... 0011011 @sh5 sroiw 0010000 .......... 101 ..... 0011011 @sh5 roriw 0110000 .......... 101 ..... 0011011 @sh5 +greviw 0110100 .......... 101 ..... 0011011 @sh5 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 429738db15..281e0ffae9 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -197,6 +197,23 @@ static bool trans_rol(DisasContext *ctx, arg_rol *a) return gen_shift(ctx, a, tcg_gen_rotl_tl); } +static bool trans_grev(DisasContext *ctx, arg_grev *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, gen_helper_grev); +} + +static bool trans_grevi(DisasContext *ctx, arg_grevi *a) +{ + REQUIRE_EXT(ctx, RVB); + + if (a->shamt >= TARGET_LONG_BITS) { + return false; + } + + return gen_grevi(ctx, a); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -329,3 +346,17 @@ static bool trans_rolw(DisasContext *ctx, arg_rolw *a) REQUIRE_EXT(ctx, RVB); return gen_shiftw(ctx, a, gen_rolw); } + +static bool trans_grevw(DisasContext *ctx, arg_grevw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_grevw); +} + +static bool trans_greviw(DisasContext *ctx, arg_greviw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftiw(ctx, a, gen_grevw); +} diff --git a/target/riscv/meson.build b/target/riscv/meson.build index af6c3416b7..d5e0bc93ea 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -16,6 +16,7 @@ riscv_ss.add(files( 'gdbstub.c', 'op_helper.c', 'vector_helper.c', + 'bitmanip_helper.c', 'translate.c', )) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index c09b93f1b8..8deb05add4 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -627,6 +627,28 @@ static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2) tcg_gen_not_tl(ret, ret); } +static bool gen_grevi(DisasContext *ctx, arg_grevi *a) +{ + TCGv source1 = tcg_temp_new(); + TCGv source2; + + gen_get_gpr(source1, a->rs1); + + if (a->shamt == (TARGET_LONG_BITS - 8)) { + /* rev8, byte swaps */ + tcg_gen_bswap_tl(source1, source1); + } else { + source2 = tcg_temp_new(); + tcg_gen_movi_tl(source2, a->shamt); + gen_helper_grev(source1, source1, source2); + tcg_temp_free(source2); + } + + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + return true; +} + static void gen_ctzw(TCGv ret, TCGv arg1) { tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); @@ -699,6 +721,12 @@ static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) tcg_temp_free_i32(t2); } +static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_ext32u_tl(arg1, arg1); + gen_helper_grev(ret, arg1, arg2); +} + static bool gen_arith(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { From c24f0422fbc0924389c1345ee30d8f87730ae633 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Thu, 6 May 2021 00:06:14 +0800 Subject: [PATCH 28/32] target/riscv: rvb: generalized or-combine Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Message-id: 20210505160620.15723-14-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/bitmanip_helper.c | 26 +++++++++++++++++++++++++ target/riscv/helper.h | 2 ++ target/riscv/insn32.decode | 4 ++++ target/riscv/insn_trans/trans_rvb.c.inc | 26 +++++++++++++++++++++++++ target/riscv/translate.c | 6 ++++++ 5 files changed, 64 insertions(+) diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/bitmanip_helper.c index c625adaded..5b2f795d03 100644 --- a/target/riscv/bitmanip_helper.c +++ b/target/riscv/bitmanip_helper.c @@ -62,3 +62,29 @@ target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2) { return do_grev(rs1, rs2, 32); } + +static target_ulong do_gorc(target_ulong rs1, + target_ulong rs2, + int bits) +{ + target_ulong x = rs1; + int i, shift; + + for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) { + if (rs2 & shift) { + x |= do_swap(x, adjacent_masks[i], shift); + } + } + + return x; +} + +target_ulong HELPER(gorc)(target_ulong rs1, target_ulong rs2) +{ + return do_gorc(rs1, rs2, TARGET_LONG_BITS); +} + +target_ulong HELPER(gorcw)(target_ulong rs1, target_ulong rs2) +{ + return do_gorc(rs1, rs2, 32); +} diff --git a/target/riscv/helper.h b/target/riscv/helper.h index f81b8faf3b..415e37bc37 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -61,6 +61,8 @@ DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64) /* Bitmanip */ DEF_HELPER_FLAGS_2(grev, TCG_CALL_NO_RWG_SE, tl, tl, tl) DEF_HELPER_FLAGS_2(grevw, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(gorc, TCG_CALL_NO_RWG_SE, tl, tl, tl) +DEF_HELPER_FLAGS_2(gorcw, TCG_CALL_NO_RWG_SE, tl, tl, tl) /* Special functions */ DEF_HELPER_3(csrrw, tl, env, tl, tl) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 6b5e276a9f..e6dab8dbbc 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -685,6 +685,7 @@ sro 0010000 .......... 101 ..... 0110011 @r ror 0110000 .......... 101 ..... 0110011 @r rol 0110000 .......... 001 ..... 0110011 @r grev 0110100 .......... 101 ..... 0110011 @r +gorc 0010100 .......... 101 ..... 0110011 @r bseti 00101. ........... 001 ..... 0010011 @sh bclri 01001. ........... 001 ..... 0010011 @sh @@ -694,6 +695,7 @@ sloi 00100. ........... 001 ..... 0010011 @sh sroi 00100. ........... 101 ..... 0010011 @sh rori 01100. ........... 101 ..... 0010011 @sh grevi 01101. ........... 101 ..... 0010011 @sh +gorci 00101. ........... 101 ..... 0010011 @sh # *** RV64B Standard Extension (in addition to RV32B) *** clzw 0110000 00000 ..... 001 ..... 0011011 @r2 @@ -711,6 +713,7 @@ srow 0010000 .......... 101 ..... 0111011 @r rorw 0110000 .......... 101 ..... 0111011 @r rolw 0110000 .......... 001 ..... 0111011 @r grevw 0110100 .......... 101 ..... 0111011 @r +gorcw 0010100 .......... 101 ..... 0111011 @r bsetiw 0010100 .......... 001 ..... 0011011 @sh5 bclriw 0100100 .......... 001 ..... 0011011 @sh5 @@ -719,3 +722,4 @@ sloiw 0010000 .......... 001 ..... 0011011 @sh5 sroiw 0010000 .......... 101 ..... 0011011 @sh5 roriw 0110000 .......... 101 ..... 0011011 @sh5 greviw 0110100 .......... 101 ..... 0011011 @sh5 +gorciw 0010100 .......... 101 ..... 0011011 @sh5 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 281e0ffae9..ec9f9d2ef2 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -214,6 +214,18 @@ static bool trans_grevi(DisasContext *ctx, arg_grevi *a) return gen_grevi(ctx, a); } +static bool trans_gorc(DisasContext *ctx, arg_gorc *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shift(ctx, a, gen_helper_gorc); +} + +static bool trans_gorci(DisasContext *ctx, arg_gorci *a) +{ + REQUIRE_EXT(ctx, RVB); + return gen_shifti(ctx, a, gen_helper_gorc); +} + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -360,3 +372,17 @@ static bool trans_greviw(DisasContext *ctx, arg_greviw *a) REQUIRE_EXT(ctx, RVB); return gen_shiftiw(ctx, a, gen_grevw); } + +static bool trans_gorcw(DisasContext *ctx, arg_gorcw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftw(ctx, a, gen_gorcw); +} + +static bool trans_gorciw(DisasContext *ctx, arg_gorciw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_shiftiw(ctx, a, gen_gorcw); +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 8deb05add4..35d4d36eef 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -727,6 +727,12 @@ static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2) gen_helper_grev(ret, arg1, arg2); } +static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_ext32u_tl(arg1, arg1); + gen_helper_gorcw(ret, arg1, arg2); +} + static bool gen_arith(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { From 920a1f9955c528f2be3ff9c9e1cbf40ddad1b192 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:15 +0800 Subject: [PATCH 29/32] target/riscv: rvb: address calculation Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Message-id: 20210505160620.15723-15-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 6 +++++ target/riscv/insn_trans/trans_rvb.c.inc | 24 +++++++++++++++++++ target/riscv/translate.c | 32 +++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index e6dab8dbbc..287920ee9b 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -686,6 +686,9 @@ ror 0110000 .......... 101 ..... 0110011 @r rol 0110000 .......... 001 ..... 0110011 @r grev 0110100 .......... 101 ..... 0110011 @r gorc 0010100 .......... 101 ..... 0110011 @r +sh1add 0010000 .......... 010 ..... 0110011 @r +sh2add 0010000 .......... 100 ..... 0110011 @r +sh3add 0010000 .......... 110 ..... 0110011 @r bseti 00101. ........... 001 ..... 0010011 @sh bclri 01001. ........... 001 ..... 0010011 @sh @@ -714,6 +717,9 @@ rorw 0110000 .......... 101 ..... 0111011 @r rolw 0110000 .......... 001 ..... 0111011 @r grevw 0110100 .......... 101 ..... 0111011 @r gorcw 0010100 .......... 101 ..... 0111011 @r +sh1add_uw 0010000 .......... 010 ..... 0111011 @r +sh2add_uw 0010000 .......... 100 ..... 0111011 @r +sh3add_uw 0010000 .......... 110 ..... 0111011 @r bsetiw 0010100 .......... 001 ..... 0011011 @sh5 bclriw 0100100 .......... 001 ..... 0011011 @sh5 diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index ec9f9d2ef2..b27114a068 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -226,6 +226,17 @@ static bool trans_gorci(DisasContext *ctx, arg_gorci *a) return gen_shifti(ctx, a, gen_helper_gorc); } +#define GEN_TRANS_SHADD(SHAMT) \ +static bool trans_sh##SHAMT##add(DisasContext *ctx, arg_sh##SHAMT##add *a) \ +{ \ + REQUIRE_EXT(ctx, RVB); \ + return gen_arith(ctx, a, gen_sh##SHAMT##add); \ +} + +GEN_TRANS_SHADD(1) +GEN_TRANS_SHADD(2) +GEN_TRANS_SHADD(3) + static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -386,3 +397,16 @@ static bool trans_gorciw(DisasContext *ctx, arg_gorciw *a) REQUIRE_EXT(ctx, RVB); return gen_shiftiw(ctx, a, gen_gorcw); } + +#define GEN_TRANS_SHADD_UW(SHAMT) \ +static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, \ + arg_sh##SHAMT##add_uw *a) \ +{ \ + REQUIRE_64BIT(ctx); \ + REQUIRE_EXT(ctx, RVB); \ + return gen_arith(ctx, a, gen_sh##SHAMT##add_uw); \ +} + +GEN_TRANS_SHADD_UW(1) +GEN_TRANS_SHADD_UW(2) +GEN_TRANS_SHADD_UW(3) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 35d4d36eef..ae9b5f7a2e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -649,6 +649,21 @@ static bool gen_grevi(DisasContext *ctx, arg_grevi *a) return true; } +#define GEN_SHADD(SHAMT) \ +static void gen_sh##SHAMT##add(TCGv ret, TCGv arg1, TCGv arg2) \ +{ \ + TCGv t = tcg_temp_new(); \ + \ + tcg_gen_shli_tl(t, arg1, SHAMT); \ + tcg_gen_add_tl(ret, t, arg2); \ + \ + tcg_temp_free(t); \ +} + +GEN_SHADD(1) +GEN_SHADD(2) +GEN_SHADD(3) + static void gen_ctzw(TCGv ret, TCGv arg1) { tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); @@ -733,6 +748,23 @@ static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2) gen_helper_gorcw(ret, arg1, arg2); } +#define GEN_SHADD_UW(SHAMT) \ +static void gen_sh##SHAMT##add_uw(TCGv ret, TCGv arg1, TCGv arg2) \ +{ \ + TCGv t = tcg_temp_new(); \ + \ + tcg_gen_ext32u_tl(t, arg1); \ + \ + tcg_gen_shli_tl(t, t, SHAMT); \ + tcg_gen_add_tl(ret, t, arg2); \ + \ + tcg_temp_free(t); \ +} + +GEN_SHADD_UW(1) +GEN_SHADD_UW(2) +GEN_SHADD_UW(3) + static bool gen_arith(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { From 3a4a43e4e213a18d1ee4ed97090a5e86401c85bc Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:16 +0800 Subject: [PATCH 30/32] target/riscv: rvb: add/shift with prefix zero-extend Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Message-id: 20210505160620.15723-16-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 3 +++ target/riscv/insn_trans/trans_rvb.c.inc | 26 +++++++++++++++++++++++++ target/riscv/translate.c | 6 ++++++ 3 files changed, 35 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 287920ee9b..f09f8d5faf 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -720,6 +720,7 @@ gorcw 0010100 .......... 101 ..... 0111011 @r sh1add_uw 0010000 .......... 010 ..... 0111011 @r sh2add_uw 0010000 .......... 100 ..... 0111011 @r sh3add_uw 0010000 .......... 110 ..... 0111011 @r +add_uw 0000100 .......... 000 ..... 0111011 @r bsetiw 0010100 .......... 001 ..... 0011011 @sh5 bclriw 0100100 .......... 001 ..... 0011011 @sh5 @@ -729,3 +730,5 @@ sroiw 0010000 .......... 101 ..... 0011011 @sh5 roriw 0110000 .......... 101 ..... 0011011 @sh5 greviw 0110100 .......... 101 ..... 0011011 @sh5 gorciw 0010100 .......... 101 ..... 0011011 @sh5 + +slli_uw 00001. ........... 001 ..... 0011011 @sh diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index b27114a068..9e81f6e3de 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -410,3 +410,29 @@ static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, \ GEN_TRANS_SHADD_UW(1) GEN_TRANS_SHADD_UW(2) GEN_TRANS_SHADD_UW(3) + +static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + return gen_arith(ctx, a, gen_add_uw); +} + +static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a) +{ + REQUIRE_64BIT(ctx); + REQUIRE_EXT(ctx, RVB); + + TCGv source1 = tcg_temp_new(); + gen_get_gpr(source1, a->rs1); + + if (a->shamt < 32) { + tcg_gen_deposit_z_tl(source1, source1, a->shamt, 32); + } else { + tcg_gen_shli_tl(source1, source1, a->shamt); + } + + gen_set_gpr(a->rd, source1); + tcg_temp_free(source1); + return true; +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index ae9b5f7a2e..c6e8739614 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -765,6 +765,12 @@ GEN_SHADD_UW(1) GEN_SHADD_UW(2) GEN_SHADD_UW(3) +static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2) +{ + tcg_gen_ext32u_tl(arg1, arg1); + tcg_gen_add_tl(ret, arg1, arg2); +} + static bool gen_arith(DisasContext *ctx, arg_r *a, void(*func)(TCGv, TCGv, TCGv)) { From d52e94081e626b6b4b181dc7a6fc8f0b98e7d403 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 6 May 2021 00:06:17 +0800 Subject: [PATCH 31/32] target/riscv: rvb: support and turn on B-extension from command line B-extension is default off, use cpu rv32 or rv64 with x-b=true to enable B-extension. Signed-off-by: Kito Cheng Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Reviewed-by: Richard Henderson Message-id: 20210505160620.15723-17-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 4 ++++ target/riscv/cpu.h | 1 + 2 files changed, 5 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ee2523f66b..5702c53c62 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -489,6 +489,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) if (cpu->cfg.ext_h) { target_misa |= RVH; } + if (cpu->cfg.ext_b) { + target_misa |= RVB; + } if (cpu->cfg.ext_v) { target_misa |= RVV; if (!is_power_of_2(cpu->cfg.vlen)) { @@ -559,6 +562,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true), DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true), /* This is experimental so mark with 'x-' */ + DEFINE_PROP_BOOL("x-b", RISCVCPU, cfg.ext_b, false), DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false), DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false), DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index c0c99c3d8d..de9262c930 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -286,6 +286,7 @@ struct RISCVCPU { bool ext_f; bool ext_d; bool ext_c; + bool ext_b; bool ext_s; bool ext_u; bool ext_h; From d2c1a177b138be35cb96216baa870c3564b123e4 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Thu, 6 May 2021 00:06:18 +0800 Subject: [PATCH 32/32] target/riscv: rvb: add b-ext version cpu option Default b-ext version is v0.93. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20210505160620.15723-18-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 23 +++++++++++++++++++++++ target/riscv/cpu.h | 3 +++ 2 files changed, 26 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 5702c53c62..991a6bb760 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -127,6 +127,11 @@ static void set_priv_version(CPURISCVState *env, int priv_ver) env->priv_ver = priv_ver; } +static void set_bext_version(CPURISCVState *env, int bext_ver) +{ + env->bext_ver = bext_ver; +} + static void set_vext_version(CPURISCVState *env, int vext_ver) { env->vext_ver = vext_ver; @@ -388,6 +393,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) CPURISCVState *env = &cpu->env; RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); int priv_version = PRIV_VERSION_1_11_0; + int bext_version = BEXT_VERSION_0_93_0; int vext_version = VEXT_VERSION_0_07_1; target_ulong target_misa = env->misa; Error *local_err = NULL; @@ -412,6 +418,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } set_priv_version(env, priv_version); + set_bext_version(env, bext_version); set_vext_version(env, vext_version); if (cpu->cfg.mmu) { @@ -491,6 +498,21 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } if (cpu->cfg.ext_b) { target_misa |= RVB; + + if (cpu->cfg.bext_spec) { + if (!g_strcmp0(cpu->cfg.bext_spec, "v0.93")) { + bext_version = BEXT_VERSION_0_93_0; + } else { + error_setg(errp, + "Unsupported bitmanip spec version '%s'", + cpu->cfg.bext_spec); + return; + } + } else { + qemu_log("bitmanip version is not specified, " + "use the default value v0.93\n"); + } + set_bext_version(env, bext_version); } if (cpu->cfg.ext_v) { target_misa |= RVV; @@ -569,6 +591,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), + DEFINE_PROP_STRING("bext_spec", RISCVCPU, cfg.bext_spec), DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index de9262c930..bf1c899c00 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -83,6 +83,7 @@ enum { #define PRIV_VERSION_1_10_0 0x00011000 #define PRIV_VERSION_1_11_0 0x00011100 +#define BEXT_VERSION_0_93_0 0x00009300 #define VEXT_VERSION_0_07_1 0x00000701 enum { @@ -132,6 +133,7 @@ struct CPURISCVState { target_ulong guest_phys_fault_addr; target_ulong priv_ver; + target_ulong bext_ver; target_ulong vext_ver; target_ulong misa; target_ulong misa_mask; @@ -297,6 +299,7 @@ struct RISCVCPU { char *priv_spec; char *user_spec; + char *bext_spec; char *vext_spec; uint16_t vlen; uint16_t elen;