A large collection of RISC-V fixes, improvements and features
- Clenaup some left over v1.9 code - Documentation improvements - Support for the shakti_c machine - Internal cleanup of the CSR accesses - Updates to the OpenTitan platform - Support for the virtio-vga - Fix for the saturate subtract in vector extensions - Experimental support for the ePMP spec - A range of other internal code cleanups and bug fixes -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmCaWaYACgkQIeENKd+X cFS97Af/c+Zh5KddhY0qYm6/deabhzn2fPrensOX+UlQbThpbKLHPZ+ceh1GRYBl tqfiQa6ByhLhHk4UihIjJvLL9UW+UUxR3zsUfHcFHGAmy22ms9oiGB+se37gj/YB 2WySYQhHlwW1iz+55mMh+c1wjckFFVjX4dQgh7pl60AJWxNdzNOBUr/BwMZUh0zM UFsYDGS2MF3JId8VkW4Ui4fKTw0HBexK4gKXOsRIpF6R3+PQa3m4ppr/YZfyUy5W o8lZhztoO5TgyGyNpCo6UdG9JlJP5iNnPRTn+ordqJhpNKFTLQeuLBW9gMpB9BiG L1fvPePKz7GWxI/Xrl9uwNyWSYwetA== =6TPt -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210511' into staging A large collection of RISC-V fixes, improvements and features - Clenaup some left over v1.9 code - Documentation improvements - Support for the shakti_c machine - Internal cleanup of the CSR accesses - Updates to the OpenTitan platform - Support for the virtio-vga - Fix for the saturate subtract in vector extensions - Experimental support for the ePMP spec - A range of other internal code cleanups and bug fixes # gpg: Signature made Tue 11 May 2021 11:17:10 BST # gpg: using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [full] # Primary key fingerprint: F6C4 AC46 D493 4868 D3B8 CE8F 21E1 0D29 DF97 7054 * remotes/alistair/tags/pull-riscv-to-apply-20210511: (42 commits) target/riscv: Fix the RV64H decode comment target/riscv: Consolidate RV32/64 16-bit instructions target/riscv: Consolidate RV32/64 32-bit instructions target/riscv: Remove an unused CASE_OP_32_64 macro target/riscv: Remove the unused HSTATUS_WPRI macro target/riscv: Remove the hardcoded SATP_MODE macro target/riscv: Remove the hardcoded MSTATUS_SD macro target/riscv: Remove the hardcoded HGATP_MODE macro target/riscv: Remove the hardcoded SSTATUS_SD macro target/riscv: Remove the hardcoded RVXLEN macro target/riscv: fix a typo with interrupt names fpu/softfloat: set invalid excp flag for RISC-V muladd instructions hw/riscv: Fix OT IBEX reset vector target/riscv: fix exception index on instruction access fault target/riscv: fix vrgather macro index variable type bug target/riscv: Add ePMP support for the Ibex CPU target/riscv/pmp: Remove outdated comment target/riscv: Add a config option for ePMP target/riscv: Implementation of enhanced PMP (ePMP) target/riscv: Add ePMP CSR access functions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3e9f48bcda
14
MAINTAINERS
14
MAINTAINERS
@ -295,9 +295,8 @@ F: tests/acceptance/machine_ppc.py
|
||||
|
||||
RISC-V TCG CPUs
|
||||
M: Palmer Dabbelt <palmer@dabbelt.com>
|
||||
M: Alistair Francis <Alistair.Francis@wdc.com>
|
||||
M: Sagar Karandikar <sagark@eecs.berkeley.edu>
|
||||
M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
||||
M: Alistair Francis <alistair.francis@wdc.com>
|
||||
M: Bin Meng <bin.meng@windriver.com>
|
||||
L: qemu-riscv@nongnu.org
|
||||
S: Supported
|
||||
F: target/riscv/
|
||||
@ -1415,6 +1414,15 @@ F: include/hw/misc/mchp_pfsoc_dmc.h
|
||||
F: include/hw/misc/mchp_pfsoc_ioscb.h
|
||||
F: include/hw/misc/mchp_pfsoc_sysreg.h
|
||||
|
||||
Shakti C class SoC
|
||||
M: Vijai Kumar K <vijai@behindbytes.com>
|
||||
L: qemu-riscv@nongnu.org
|
||||
S: Supported
|
||||
F: hw/riscv/shakti_c.c
|
||||
F: hw/char/shakti_uart.c
|
||||
F: include/hw/riscv/shakti_c.h
|
||||
F: include/hw/char/shakti_uart.h
|
||||
|
||||
SiFive Machines
|
||||
M: Alistair Francis <Alistair.Francis@wdc.com>
|
||||
M: Bin Meng <bin.meng@windriver.com>
|
||||
|
@ -13,3 +13,4 @@ CONFIG_SIFIVE_E=y
|
||||
CONFIG_SIFIVE_U=y
|
||||
CONFIG_RISCV_VIRT=y
|
||||
CONFIG_MICROCHIP_PFSOC=y
|
||||
CONFIG_SHAKTI_C=y
|
||||
|
@ -92,9 +92,12 @@ shown below:
|
||||
specified in the executable format header. This option should only
|
||||
be used for the boot image. This will also cause the image to be
|
||||
written to the specified CPU's address space. If not specified, the
|
||||
default is CPU 0. <force-raw> - Setting force-raw=on forces the file
|
||||
to be treated as a raw image. This can be used to load supported
|
||||
executable formats as if they were raw.
|
||||
default is CPU 0.
|
||||
|
||||
``<force-raw>``
|
||||
Setting 'force-raw=on' forces the file to be treated as a raw image.
|
||||
This can be used to load supported executable formats as if they
|
||||
were raw.
|
||||
|
||||
All values are parsed using the standard QemuOpts parsing. This allows the user
|
||||
to specify any values in any format supported. By default the values
|
||||
|
82
docs/system/riscv/shakti-c.rst
Normal file
82
docs/system/riscv/shakti-c.rst
Normal file
@ -0,0 +1,82 @@
|
||||
Shakti C Reference Platform (``shakti_c``)
|
||||
==========================================
|
||||
|
||||
Shakti C Reference Platform is a reference platform based on arty a7 100t
|
||||
for the Shakti SoC.
|
||||
|
||||
Shakti SoC is a SoC based on the Shakti C-class processor core. Shakti C
|
||||
is a 64bit RV64GCSUN processor core.
|
||||
|
||||
For more details on Shakti SoC, please see:
|
||||
https://gitlab.com/shaktiproject/cores/shakti-soc/-/blob/master/fpga/boards/artya7-100t/c-class/README.rst
|
||||
|
||||
For more info on the Shakti C-class core, please see:
|
||||
https://c-class.readthedocs.io/en/latest/
|
||||
|
||||
Supported devices
|
||||
-----------------
|
||||
|
||||
The ``shakti_c`` machine supports the following devices:
|
||||
|
||||
* 1 C-class core
|
||||
* Core Level Interruptor (CLINT)
|
||||
* Platform-Level Interrupt Controller (PLIC)
|
||||
* 1 UART
|
||||
|
||||
Boot options
|
||||
------------
|
||||
|
||||
The ``shakti_c`` machine can start using the standard -bios
|
||||
functionality for loading the baremetal application or opensbi.
|
||||
|
||||
Boot the machine
|
||||
----------------
|
||||
|
||||
Shakti SDK
|
||||
~~~~~~~~~~
|
||||
Shakti SDK can be used to generate the baremetal example UART applications.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://gitlab.com/behindbytes/shakti-sdk.git
|
||||
$ cd shakti-sdk
|
||||
$ make software PROGRAM=loopback TARGET=artix7_100t
|
||||
|
||||
Binary would be generated in:
|
||||
software/examples/uart_applns/loopback/output/loopback.shakti
|
||||
|
||||
You could also download the precompiled example applicatons using below
|
||||
commands.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ wget -c https://gitlab.com/behindbytes/shakti-binaries/-/raw/master/sdk/shakti_sdk_qemu.zip
|
||||
$ unzip shakti_sdk_qemu.zip
|
||||
|
||||
Then we can run the UART example using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ qemu-system-riscv64 -M shakti_c -nographic \
|
||||
-bios path/to/shakti_sdk_qemu/loopback.shakti
|
||||
|
||||
OpenSBI
|
||||
~~~~~~~
|
||||
We can also run OpenSBI with Test Payload.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://github.com/riscv/opensbi.git -b v0.9
|
||||
$ cd opensbi
|
||||
$ wget -c https://gitlab.com/behindbytes/shakti-binaries/-/raw/master/dts/shakti.dtb
|
||||
$ export CROSS_COMPILE=riscv64-unknown-elf-
|
||||
$ export FW_FDT_PATH=./shakti.dtb
|
||||
$ make PLATFORM=generic
|
||||
|
||||
fw_payload.elf would be generated in build/platform/generic/firmware/fw_payload.elf.
|
||||
Boot it using the below qemu command.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ qemu-system-riscv64 -M shakti_c -nographic \
|
||||
-bios path/to/fw_payload.elf
|
@ -67,6 +67,7 @@ undocumented; you can get a complete list by running
|
||||
:maxdepth: 1
|
||||
|
||||
riscv/microchip-icicle-kit
|
||||
riscv/shakti-c
|
||||
riscv/sifive_u
|
||||
|
||||
RISC-V CPU features
|
||||
|
@ -627,6 +627,12 @@ static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
#elif defined(TARGET_RISCV)
|
||||
/* For RISC-V, InvalidOp is set when multiplicands are Inf and zero */
|
||||
if (infzero) {
|
||||
float_raise(float_flag_invalid, status);
|
||||
}
|
||||
return 3; /* default NaN */
|
||||
#elif defined(TARGET_XTENSA)
|
||||
/*
|
||||
* For Xtensa, the (inf,zero,nan) case sets InvalidOp and returns
|
||||
|
@ -19,6 +19,7 @@ softmmu_ss.add(when: 'CONFIG_SERIAL', if_true: files('serial.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SERIAL_ISA', if_true: files('serial-isa.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SERIAL_PCI', if_true: files('serial-pci.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SERIAL_PCI_MULTI', if_true: files('serial-pci-multi.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SHAKTI', if_true: files('shakti_uart.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-console.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen_console.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_uartlite.c'))
|
||||
|
185
hw/char/shakti_uart.c
Normal file
185
hw/char/shakti_uart.c
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* SHAKTI UART
|
||||
*
|
||||
* Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/char/shakti_uart.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-properties-system.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
static uint64_t shakti_uart_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
ShaktiUartState *s = opaque;
|
||||
|
||||
switch (addr) {
|
||||
case SHAKTI_UART_BAUD:
|
||||
return s->uart_baud;
|
||||
case SHAKTI_UART_RX:
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
s->uart_status &= ~SHAKTI_UART_STATUS_RX_NOT_EMPTY;
|
||||
return s->uart_rx;
|
||||
case SHAKTI_UART_STATUS:
|
||||
return s->uart_status;
|
||||
case SHAKTI_UART_DELAY:
|
||||
return s->uart_delay;
|
||||
case SHAKTI_UART_CONTROL:
|
||||
return s->uart_control;
|
||||
case SHAKTI_UART_INT_EN:
|
||||
return s->uart_interrupt;
|
||||
case SHAKTI_UART_IQ_CYCLES:
|
||||
return s->uart_iq_cycles;
|
||||
case SHAKTI_UART_RX_THRES:
|
||||
return s->uart_rx_threshold;
|
||||
default:
|
||||
/* Also handles TX REG which is write only */
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shakti_uart_write(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
ShaktiUartState *s = opaque;
|
||||
uint32_t value = data;
|
||||
uint8_t ch;
|
||||
|
||||
switch (addr) {
|
||||
case SHAKTI_UART_BAUD:
|
||||
s->uart_baud = value;
|
||||
break;
|
||||
case SHAKTI_UART_TX:
|
||||
ch = value;
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
s->uart_status &= ~SHAKTI_UART_STATUS_TX_FULL;
|
||||
break;
|
||||
case SHAKTI_UART_STATUS:
|
||||
s->uart_status = value;
|
||||
break;
|
||||
case SHAKTI_UART_DELAY:
|
||||
s->uart_delay = value;
|
||||
break;
|
||||
case SHAKTI_UART_CONTROL:
|
||||
s->uart_control = value;
|
||||
break;
|
||||
case SHAKTI_UART_INT_EN:
|
||||
s->uart_interrupt = value;
|
||||
break;
|
||||
case SHAKTI_UART_IQ_CYCLES:
|
||||
s->uart_iq_cycles = value;
|
||||
break;
|
||||
case SHAKTI_UART_RX_THRES:
|
||||
s->uart_rx_threshold = value;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps shakti_uart_ops = {
|
||||
.read = shakti_uart_read,
|
||||
.write = shakti_uart_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.impl = {.min_access_size = 1, .max_access_size = 4},
|
||||
.valid = {.min_access_size = 1, .max_access_size = 4},
|
||||
};
|
||||
|
||||
static void shakti_uart_reset(DeviceState *dev)
|
||||
{
|
||||
ShaktiUartState *s = SHAKTI_UART(dev);
|
||||
|
||||
s->uart_baud = SHAKTI_UART_BAUD_DEFAULT;
|
||||
s->uart_tx = 0x0;
|
||||
s->uart_rx = 0x0;
|
||||
s->uart_status = 0x0000;
|
||||
s->uart_delay = 0x0000;
|
||||
s->uart_control = SHAKTI_UART_CONTROL_DEFAULT;
|
||||
s->uart_interrupt = 0x0000;
|
||||
s->uart_iq_cycles = 0x00;
|
||||
s->uart_rx_threshold = 0x00;
|
||||
}
|
||||
|
||||
static int shakti_uart_can_receive(void *opaque)
|
||||
{
|
||||
ShaktiUartState *s = opaque;
|
||||
|
||||
return !(s->uart_status & SHAKTI_UART_STATUS_RX_NOT_EMPTY);
|
||||
}
|
||||
|
||||
static void shakti_uart_receive(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
ShaktiUartState *s = opaque;
|
||||
|
||||
s->uart_rx = *buf;
|
||||
s->uart_status |= SHAKTI_UART_STATUS_RX_NOT_EMPTY;
|
||||
}
|
||||
|
||||
static void shakti_uart_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ShaktiUartState *sus = SHAKTI_UART(dev);
|
||||
qemu_chr_fe_set_handlers(&sus->chr, shakti_uart_can_receive,
|
||||
shakti_uart_receive, NULL, NULL, sus, NULL, true);
|
||||
}
|
||||
|
||||
static void shakti_uart_instance_init(Object *obj)
|
||||
{
|
||||
ShaktiUartState *sus = SHAKTI_UART(obj);
|
||||
memory_region_init_io(&sus->mmio,
|
||||
obj,
|
||||
&shakti_uart_ops,
|
||||
sus,
|
||||
TYPE_SHAKTI_UART,
|
||||
0x1000);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &sus->mmio);
|
||||
}
|
||||
|
||||
static Property shakti_uart_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev", ShaktiUartState, chr),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void shakti_uart_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
dc->reset = shakti_uart_reset;
|
||||
dc->realize = shakti_uart_realize;
|
||||
device_class_set_props(dc, shakti_uart_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo shakti_uart_info = {
|
||||
.name = TYPE_SHAKTI_UART,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ShaktiUartState),
|
||||
.class_init = shakti_uart_class_init,
|
||||
.instance_init = shakti_uart_instance_init,
|
||||
};
|
||||
|
||||
static void shakti_uart_register_types(void)
|
||||
{
|
||||
type_register_static(&shakti_uart_info);
|
||||
}
|
||||
type_init(shakti_uart_register_types)
|
@ -90,6 +90,10 @@ cmsdk_apb_uart_set_params(int speed) "CMSDK APB UART: params set to %d 8N1"
|
||||
nrf51_uart_read(uint64_t addr, uint64_t r, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
|
||||
nrf51_uart_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
|
||||
|
||||
# shakti_uart.c
|
||||
shakti_uart_read(uint64_t addr, uint16_t r, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx16 " size %u"
|
||||
shakti_uart_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%" PRIx64 " value 0x%" PRIx64 " size %u"
|
||||
|
||||
# exynos4210_uart.c
|
||||
exynos_uart_dmabusy(uint32_t channel) "UART%d: DMA busy (Rx buffer empty)"
|
||||
exynos_uart_dmaready(uint32_t channel) "UART%d: DMA ready"
|
||||
|
@ -225,23 +225,23 @@ static void ibex_plic_irq_request(void *opaque, int irq, int level)
|
||||
|
||||
static Property ibex_plic_properties[] = {
|
||||
DEFINE_PROP_UINT32("num-cpus", IbexPlicState, num_cpus, 1),
|
||||
DEFINE_PROP_UINT32("num-sources", IbexPlicState, num_sources, 80),
|
||||
DEFINE_PROP_UINT32("num-sources", IbexPlicState, num_sources, 176),
|
||||
|
||||
DEFINE_PROP_UINT32("pending-base", IbexPlicState, pending_base, 0),
|
||||
DEFINE_PROP_UINT32("pending-num", IbexPlicState, pending_num, 3),
|
||||
DEFINE_PROP_UINT32("pending-num", IbexPlicState, pending_num, 6),
|
||||
|
||||
DEFINE_PROP_UINT32("source-base", IbexPlicState, source_base, 0x0c),
|
||||
DEFINE_PROP_UINT32("source-num", IbexPlicState, source_num, 3),
|
||||
DEFINE_PROP_UINT32("source-base", IbexPlicState, source_base, 0x18),
|
||||
DEFINE_PROP_UINT32("source-num", IbexPlicState, source_num, 6),
|
||||
|
||||
DEFINE_PROP_UINT32("priority-base", IbexPlicState, priority_base, 0x18),
|
||||
DEFINE_PROP_UINT32("priority-num", IbexPlicState, priority_num, 80),
|
||||
DEFINE_PROP_UINT32("priority-base", IbexPlicState, priority_base, 0x30),
|
||||
DEFINE_PROP_UINT32("priority-num", IbexPlicState, priority_num, 177),
|
||||
|
||||
DEFINE_PROP_UINT32("enable-base", IbexPlicState, enable_base, 0x200),
|
||||
DEFINE_PROP_UINT32("enable-num", IbexPlicState, enable_num, 3),
|
||||
DEFINE_PROP_UINT32("enable-base", IbexPlicState, enable_base, 0x300),
|
||||
DEFINE_PROP_UINT32("enable-num", IbexPlicState, enable_num, 6),
|
||||
|
||||
DEFINE_PROP_UINT32("threshold-base", IbexPlicState, threshold_base, 0x20c),
|
||||
DEFINE_PROP_UINT32("threshold-base", IbexPlicState, threshold_base, 0x318),
|
||||
|
||||
DEFINE_PROP_UINT32("claim-base", IbexPlicState, claim_base, 0x210),
|
||||
DEFINE_PROP_UINT32("claim-base", IbexPlicState, claim_base, 0x31c),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -19,9 +19,20 @@ config OPENTITAN
|
||||
select IBEX
|
||||
select UNIMP
|
||||
|
||||
config SHAKTI
|
||||
bool
|
||||
|
||||
config SHAKTI_C
|
||||
bool
|
||||
select UNIMP
|
||||
select SHAKTI
|
||||
select SIFIVE_CLINT
|
||||
select SIFIVE_PLIC
|
||||
|
||||
config RISCV_VIRT
|
||||
bool
|
||||
imply PCI_DEVICES
|
||||
imply VIRTIO_VGA
|
||||
imply TEST_DEVICES
|
||||
select GOLDFISH_RTC
|
||||
select MSI_NONBROKEN
|
||||
|
@ -4,6 +4,7 @@ riscv_ss.add(files('numa.c'))
|
||||
riscv_ss.add(files('riscv_hart.c'))
|
||||
riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c'))
|
||||
riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c'))
|
||||
riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c'))
|
||||
riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c'))
|
||||
riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c'))
|
||||
riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))
|
||||
|
@ -119,7 +119,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus,
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x8090, &error_abort);
|
||||
object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x8080, &error_abort);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_abort);
|
||||
|
||||
/* Boot ROM */
|
||||
@ -148,16 +148,16 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart), 0, memmap[IBEX_DEV_UART].base);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart),
|
||||
0, qdev_get_gpio_in(DEVICE(&s->plic),
|
||||
IBEX_UART_TX_WATERMARK_IRQ));
|
||||
IBEX_UART0_TX_WATERMARK_IRQ));
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart),
|
||||
1, qdev_get_gpio_in(DEVICE(&s->plic),
|
||||
IBEX_UART_RX_WATERMARK_IRQ));
|
||||
IBEX_UART0_RX_WATERMARK_IRQ));
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart),
|
||||
2, qdev_get_gpio_in(DEVICE(&s->plic),
|
||||
IBEX_UART_TX_EMPTY_IRQ));
|
||||
IBEX_UART0_TX_EMPTY_IRQ));
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart),
|
||||
3, qdev_get_gpio_in(DEVICE(&s->plic),
|
||||
IBEX_UART_RX_OVERFLOW_IRQ));
|
||||
IBEX_UART0_RX_OVERFLOW_IRQ));
|
||||
|
||||
create_unimplemented_device("riscv.lowrisc.ibex.gpio",
|
||||
memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size);
|
||||
|
181
hw/riscv/shakti_c.c
Normal file
181
hw/riscv/shakti_c.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Shakti C-class SoC emulation
|
||||
*
|
||||
* Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/riscv/shakti_c.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/intc/sifive_plic.h"
|
||||
#include "hw/intc/sifive_clint.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/riscv/boot.h"
|
||||
|
||||
|
||||
static const struct MemmapEntry {
|
||||
hwaddr base;
|
||||
hwaddr size;
|
||||
} shakti_c_memmap[] = {
|
||||
[SHAKTI_C_ROM] = { 0x00001000, 0x2000 },
|
||||
[SHAKTI_C_RAM] = { 0x80000000, 0x0 },
|
||||
[SHAKTI_C_UART] = { 0x00011300, 0x00040 },
|
||||
[SHAKTI_C_GPIO] = { 0x020d0000, 0x00100 },
|
||||
[SHAKTI_C_PLIC] = { 0x0c000000, 0x20000 },
|
||||
[SHAKTI_C_CLINT] = { 0x02000000, 0xc0000 },
|
||||
[SHAKTI_C_I2C] = { 0x20c00000, 0x00100 },
|
||||
};
|
||||
|
||||
static void shakti_c_machine_state_init(MachineState *mstate)
|
||||
{
|
||||
ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate);
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
||||
|
||||
/* Allow only Shakti C CPU for this platform */
|
||||
if (strcmp(mstate->cpu_type, TYPE_RISCV_CPU_SHAKTI_C) != 0) {
|
||||
error_report("This board can only be used with Shakti C CPU");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Initialize SoC */
|
||||
object_initialize_child(OBJECT(mstate), "soc", &sms->soc,
|
||||
TYPE_RISCV_SHAKTI_SOC);
|
||||
qdev_realize(DEVICE(&sms->soc), NULL, &error_abort);
|
||||
|
||||
/* register RAM */
|
||||
memory_region_init_ram(main_mem, NULL, "riscv.shakti.c.ram",
|
||||
mstate->ram_size, &error_fatal);
|
||||
memory_region_add_subregion(system_memory,
|
||||
shakti_c_memmap[SHAKTI_C_RAM].base,
|
||||
main_mem);
|
||||
|
||||
/* ROM reset vector */
|
||||
riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus,
|
||||
shakti_c_memmap[SHAKTI_C_RAM].base,
|
||||
shakti_c_memmap[SHAKTI_C_ROM].base,
|
||||
shakti_c_memmap[SHAKTI_C_ROM].size, 0, 0,
|
||||
NULL);
|
||||
if (mstate->firmware) {
|
||||
riscv_load_firmware(mstate->firmware,
|
||||
shakti_c_memmap[SHAKTI_C_RAM].base,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void shakti_c_machine_instance_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static void shakti_c_machine_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(klass);
|
||||
mc->desc = "RISC-V Board compatible with Shakti SDK";
|
||||
mc->init = shakti_c_machine_state_init;
|
||||
mc->default_cpu_type = TYPE_RISCV_CPU_SHAKTI_C;
|
||||
}
|
||||
|
||||
static const TypeInfo shakti_c_machine_type_info = {
|
||||
.name = TYPE_RISCV_SHAKTI_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.class_init = shakti_c_machine_class_init,
|
||||
.instance_init = shakti_c_machine_instance_init,
|
||||
.instance_size = sizeof(ShaktiCMachineState),
|
||||
};
|
||||
|
||||
static void shakti_c_machine_type_info_register(void)
|
||||
{
|
||||
type_register_static(&shakti_c_machine_type_info);
|
||||
}
|
||||
type_init(shakti_c_machine_type_info_register)
|
||||
|
||||
static void shakti_c_soc_state_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ShaktiCSoCState *sss = RISCV_SHAKTI_SOC(dev);
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
|
||||
sysbus_realize(SYS_BUS_DEVICE(&sss->cpus), &error_abort);
|
||||
|
||||
sss->plic = sifive_plic_create(shakti_c_memmap[SHAKTI_C_PLIC].base,
|
||||
(char *)SHAKTI_C_PLIC_HART_CONFIG, 0,
|
||||
SHAKTI_C_PLIC_NUM_SOURCES,
|
||||
SHAKTI_C_PLIC_NUM_PRIORITIES,
|
||||
SHAKTI_C_PLIC_PRIORITY_BASE,
|
||||
SHAKTI_C_PLIC_PENDING_BASE,
|
||||
SHAKTI_C_PLIC_ENABLE_BASE,
|
||||
SHAKTI_C_PLIC_ENABLE_STRIDE,
|
||||
SHAKTI_C_PLIC_CONTEXT_BASE,
|
||||
SHAKTI_C_PLIC_CONTEXT_STRIDE,
|
||||
shakti_c_memmap[SHAKTI_C_PLIC].size);
|
||||
|
||||
sifive_clint_create(shakti_c_memmap[SHAKTI_C_CLINT].base,
|
||||
shakti_c_memmap[SHAKTI_C_CLINT].size, 0, 1,
|
||||
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
|
||||
SIFIVE_CLINT_TIMEBASE_FREQ, false);
|
||||
|
||||
qdev_prop_set_chr(DEVICE(&(sss->uart)), "chardev", serial_hd(0));
|
||||
if (!sysbus_realize(SYS_BUS_DEVICE(&sss->uart), errp)) {
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&sss->uart), 0,
|
||||
shakti_c_memmap[SHAKTI_C_UART].base);
|
||||
|
||||
/* ROM */
|
||||
memory_region_init_rom(&sss->rom, OBJECT(dev), "riscv.shakti.c.rom",
|
||||
shakti_c_memmap[SHAKTI_C_ROM].size, &error_fatal);
|
||||
memory_region_add_subregion(system_memory,
|
||||
shakti_c_memmap[SHAKTI_C_ROM].base, &sss->rom);
|
||||
}
|
||||
|
||||
static void shakti_c_soc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
dc->realize = shakti_c_soc_state_realize;
|
||||
}
|
||||
|
||||
static void shakti_c_soc_instance_init(Object *obj)
|
||||
{
|
||||
ShaktiCSoCState *sss = RISCV_SHAKTI_SOC(obj);
|
||||
|
||||
object_initialize_child(obj, "cpus", &sss->cpus, TYPE_RISCV_HART_ARRAY);
|
||||
object_initialize_child(obj, "uart", &sss->uart, TYPE_SHAKTI_UART);
|
||||
|
||||
/*
|
||||
* CPU type is fixed and we are not supporting passing from commandline yet.
|
||||
* So let it be in instance_init. When supported should use ms->cpu_type
|
||||
* instead of TYPE_RISCV_CPU_SHAKTI_C
|
||||
*/
|
||||
object_property_set_str(OBJECT(&sss->cpus), "cpu-type",
|
||||
TYPE_RISCV_CPU_SHAKTI_C, &error_abort);
|
||||
object_property_set_int(OBJECT(&sss->cpus), "num-harts", 1,
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
static const TypeInfo shakti_c_type_info = {
|
||||
.name = TYPE_RISCV_SHAKTI_SOC,
|
||||
.parent = TYPE_DEVICE,
|
||||
.class_init = shakti_c_soc_class_init,
|
||||
.instance_init = shakti_c_soc_instance_init,
|
||||
.instance_size = sizeof(ShaktiCSoCState),
|
||||
};
|
||||
|
||||
static void shakti_c_type_info_register(void)
|
||||
{
|
||||
type_register_static(&shakti_c_type_info);
|
||||
}
|
||||
type_init(shakti_c_type_info_register)
|
@ -48,7 +48,7 @@
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
static MemMapEntry sifive_e_memmap[] = {
|
||||
static const MemMapEntry sifive_e_memmap[] = {
|
||||
[SIFIVE_E_DEV_DEBUG] = { 0x0, 0x1000 },
|
||||
[SIFIVE_E_DEV_MROM] = { 0x1000, 0x2000 },
|
||||
[SIFIVE_E_DEV_OTP] = { 0x20000, 0x2000 },
|
||||
|
74
include/hw/char/shakti_uart.h
Normal file
74
include/hw/char/shakti_uart.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* SHAKTI UART
|
||||
*
|
||||
* Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef HW_SHAKTI_UART_H
|
||||
#define HW_SHAKTI_UART_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "chardev/char-fe.h"
|
||||
|
||||
#define SHAKTI_UART_BAUD 0x00
|
||||
#define SHAKTI_UART_TX 0x04
|
||||
#define SHAKTI_UART_RX 0x08
|
||||
#define SHAKTI_UART_STATUS 0x0C
|
||||
#define SHAKTI_UART_DELAY 0x10
|
||||
#define SHAKTI_UART_CONTROL 0x14
|
||||
#define SHAKTI_UART_INT_EN 0x18
|
||||
#define SHAKTI_UART_IQ_CYCLES 0x1C
|
||||
#define SHAKTI_UART_RX_THRES 0x20
|
||||
|
||||
#define SHAKTI_UART_STATUS_TX_EMPTY (1 << 0)
|
||||
#define SHAKTI_UART_STATUS_TX_FULL (1 << 1)
|
||||
#define SHAKTI_UART_STATUS_RX_NOT_EMPTY (1 << 2)
|
||||
#define SHAKTI_UART_STATUS_RX_FULL (1 << 3)
|
||||
/* 9600 8N1 is the default setting */
|
||||
/* Reg value = (50000000 Hz)/(16 * 9600)*/
|
||||
#define SHAKTI_UART_BAUD_DEFAULT 0x0145
|
||||
#define SHAKTI_UART_CONTROL_DEFAULT 0x0100
|
||||
|
||||
#define TYPE_SHAKTI_UART "shakti-uart"
|
||||
#define SHAKTI_UART(obj) \
|
||||
OBJECT_CHECK(ShaktiUartState, (obj), TYPE_SHAKTI_UART)
|
||||
|
||||
typedef struct {
|
||||
/* <private> */
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/* <public> */
|
||||
MemoryRegion mmio;
|
||||
|
||||
uint32_t uart_baud;
|
||||
uint32_t uart_tx;
|
||||
uint32_t uart_rx;
|
||||
uint32_t uart_status;
|
||||
uint32_t uart_delay;
|
||||
uint32_t uart_control;
|
||||
uint32_t uart_interrupt;
|
||||
uint32_t uart_iq_cycles;
|
||||
uint32_t uart_rx_threshold;
|
||||
|
||||
CharBackend chr;
|
||||
} ShaktiUartState;
|
||||
|
||||
#endif /* HW_SHAKTI_UART_H */
|
@ -82,14 +82,14 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
IBEX_UART_RX_PARITY_ERR_IRQ = 0x28,
|
||||
IBEX_UART_RX_TIMEOUT_IRQ = 0x27,
|
||||
IBEX_UART_RX_BREAK_ERR_IRQ = 0x26,
|
||||
IBEX_UART_RX_FRAME_ERR_IRQ = 0x25,
|
||||
IBEX_UART_RX_OVERFLOW_IRQ = 0x24,
|
||||
IBEX_UART_TX_EMPTY_IRQ = 0x23,
|
||||
IBEX_UART_RX_WATERMARK_IRQ = 0x22,
|
||||
IBEX_UART_TX_WATERMARK_IRQ = 0x21,
|
||||
IBEX_UART0_RX_PARITY_ERR_IRQ = 8,
|
||||
IBEX_UART0_RX_TIMEOUT_IRQ = 7,
|
||||
IBEX_UART0_RX_BREAK_ERR_IRQ = 6,
|
||||
IBEX_UART0_RX_FRAME_ERR_IRQ = 5,
|
||||
IBEX_UART0_RX_OVERFLOW_IRQ = 4,
|
||||
IBEX_UART0_TX_EMPTY_IRQ = 3,
|
||||
IBEX_UART0_RX_WATERMARK_IRQ = 2,
|
||||
IBEX_UART0_TX_WATERMARK_IRQ = 1,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
75
include/hw/riscv/shakti_c.h
Normal file
75
include/hw/riscv/shakti_c.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Shakti C-class SoC emulation
|
||||
*
|
||||
* Copyright (c) 2021 Vijai Kumar K <vijai@behindbytes.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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HW_SHAKTI_H
|
||||
#define HW_SHAKTI_H
|
||||
|
||||
#include "hw/riscv/riscv_hart.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/char/shakti_uart.h"
|
||||
|
||||
#define TYPE_RISCV_SHAKTI_SOC "riscv.shakti.cclass.soc"
|
||||
#define RISCV_SHAKTI_SOC(obj) \
|
||||
OBJECT_CHECK(ShaktiCSoCState, (obj), TYPE_RISCV_SHAKTI_SOC)
|
||||
|
||||
typedef struct ShaktiCSoCState {
|
||||
/*< private >*/
|
||||
DeviceState parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
RISCVHartArrayState cpus;
|
||||
DeviceState *plic;
|
||||
ShaktiUartState uart;
|
||||
MemoryRegion rom;
|
||||
|
||||
} ShaktiCSoCState;
|
||||
|
||||
#define TYPE_RISCV_SHAKTI_MACHINE MACHINE_TYPE_NAME("shakti_c")
|
||||
#define RISCV_SHAKTI_MACHINE(obj) \
|
||||
OBJECT_CHECK(ShaktiCMachineState, (obj), TYPE_RISCV_SHAKTI_MACHINE)
|
||||
typedef struct ShaktiCMachineState {
|
||||
/*< private >*/
|
||||
MachineState parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
ShaktiCSoCState soc;
|
||||
} ShaktiCMachineState;
|
||||
|
||||
enum {
|
||||
SHAKTI_C_ROM,
|
||||
SHAKTI_C_RAM,
|
||||
SHAKTI_C_UART,
|
||||
SHAKTI_C_GPIO,
|
||||
SHAKTI_C_PLIC,
|
||||
SHAKTI_C_CLINT,
|
||||
SHAKTI_C_I2C,
|
||||
};
|
||||
|
||||
#define SHAKTI_C_PLIC_HART_CONFIG "MS"
|
||||
/* Including Interrupt ID 0 (no interrupt)*/
|
||||
#define SHAKTI_C_PLIC_NUM_SOURCES 28
|
||||
/* Excluding Priority 0 */
|
||||
#define SHAKTI_C_PLIC_NUM_PRIORITIES 2
|
||||
#define SHAKTI_C_PLIC_PRIORITY_BASE 0x04
|
||||
#define SHAKTI_C_PLIC_PENDING_BASE 0x1000
|
||||
#define SHAKTI_C_PLIC_ENABLE_BASE 0x2000
|
||||
#define SHAKTI_C_PLIC_ENABLE_STRIDE 0x80
|
||||
#define SHAKTI_C_PLIC_CONTEXT_BASE 0x200000
|
||||
#define SHAKTI_C_PLIC_CONTEXT_STRIDE 0x1000
|
||||
|
||||
#endif
|
@ -88,8 +88,8 @@ const char * const riscv_intr_names[] = {
|
||||
"vs_timer",
|
||||
"m_timer",
|
||||
"u_external",
|
||||
"s_external",
|
||||
"vs_external",
|
||||
"h_external",
|
||||
"m_external",
|
||||
"reserved",
|
||||
"reserved",
|
||||
@ -137,7 +137,7 @@ static void set_feature(CPURISCVState *env, int feature)
|
||||
env->features |= (1ULL << feature);
|
||||
}
|
||||
|
||||
static void set_resetvec(CPURISCVState *env, int resetvec)
|
||||
static void set_resetvec(CPURISCVState *env, target_ulong resetvec)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
env->resetvec = resetvec;
|
||||
@ -147,7 +147,11 @@ static void set_resetvec(CPURISCVState *env, int resetvec)
|
||||
static void riscv_any_cpu_init(Object *obj)
|
||||
{
|
||||
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
||||
set_misa(env, RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
|
||||
#if defined(TARGET_RISCV32)
|
||||
set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
|
||||
#elif defined(TARGET_RISCV64)
|
||||
set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
|
||||
#endif
|
||||
set_priv_version(env, PRIV_VERSION_1_11_0);
|
||||
}
|
||||
|
||||
@ -202,6 +206,7 @@ static void rv32_ibex_cpu_init(Object *obj)
|
||||
set_misa(env, RV32 | RVI | RVM | RVC | RVU);
|
||||
set_priv_version(env, PRIV_VERSION_1_10_0);
|
||||
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
|
||||
qdev_prop_set_bit(DEVICE(obj), "x-epmp", true);
|
||||
}
|
||||
|
||||
static void rv32_imafcu_nommu_cpu_init(Object *obj)
|
||||
@ -282,7 +287,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
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->sbadaddr);
|
||||
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);
|
||||
@ -358,7 +363,7 @@ static void riscv_cpu_reset(DeviceState *dev)
|
||||
env->pc = env->resetvec;
|
||||
env->two_stage_lookup = false;
|
||||
#endif
|
||||
cs->exception_index = EXCP_NONE;
|
||||
cs->exception_index = RISCV_EXCP_NONE;
|
||||
env->load_res = -1;
|
||||
set_default_nan_mode(1, &env->fp_status);
|
||||
}
|
||||
@ -412,6 +417,14 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
if (cpu->cfg.pmp) {
|
||||
set_feature(env, RISCV_FEATURE_PMP);
|
||||
|
||||
/*
|
||||
* Enhanced PMP should only be available
|
||||
* on harts with PMP support
|
||||
*/
|
||||
if (cpu->cfg.epmp) {
|
||||
set_feature(env, RISCV_FEATURE_EPMP);
|
||||
}
|
||||
}
|
||||
|
||||
set_resetvec(env, cpu->cfg.resetvec);
|
||||
@ -554,6 +567,8 @@ static Property riscv_cpu_properties[] = {
|
||||
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
|
||||
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
|
||||
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
|
||||
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
|
||||
|
||||
DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
@ -708,6 +723,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
|
||||
DEFINE_CPU(TYPE_RISCV_CPU_BASE64, rv64_base_cpu_init),
|
||||
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init),
|
||||
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init),
|
||||
DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init),
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
|
||||
#define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
|
||||
#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex")
|
||||
#define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c")
|
||||
#define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
|
||||
#define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34")
|
||||
#define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
|
||||
@ -53,12 +54,6 @@
|
||||
#define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2))
|
||||
#define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2))
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
#define RVXLEN RV32
|
||||
#elif defined(TARGET_RISCV64)
|
||||
#define RVXLEN RV64
|
||||
#endif
|
||||
|
||||
#define RV(x) ((target_ulong)1 << (x - 'A'))
|
||||
|
||||
#define RVI RV('I')
|
||||
@ -80,6 +75,7 @@
|
||||
enum {
|
||||
RISCV_FEATURE_MMU,
|
||||
RISCV_FEATURE_PMP,
|
||||
RISCV_FEATURE_EPMP,
|
||||
RISCV_FEATURE_MISA
|
||||
};
|
||||
|
||||
@ -163,10 +159,8 @@ struct CPURISCVState {
|
||||
target_ulong mie;
|
||||
target_ulong mideleg;
|
||||
|
||||
target_ulong sptbr; /* until: priv-1.9.1 */
|
||||
target_ulong satp; /* since: priv-1.10.0 */
|
||||
target_ulong sbadaddr;
|
||||
target_ulong mbadaddr;
|
||||
target_ulong stval;
|
||||
target_ulong medeleg;
|
||||
|
||||
target_ulong stvec;
|
||||
@ -230,6 +224,7 @@ struct CPURISCVState {
|
||||
|
||||
/* physical memory protection */
|
||||
pmp_table_t pmp_state;
|
||||
target_ulong mseccfg;
|
||||
|
||||
/* machine specific rdtime callback */
|
||||
uint64_t (*rdtime_fn)(uint32_t);
|
||||
@ -303,6 +298,7 @@ struct RISCVCPU {
|
||||
uint16_t elen;
|
||||
bool mmu;
|
||||
bool pmp;
|
||||
bool epmp;
|
||||
uint64_t resetvec;
|
||||
} cfg;
|
||||
};
|
||||
@ -455,10 +451,13 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
|
||||
*pflags = flags;
|
||||
}
|
||||
|
||||
int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
|
||||
target_ulong new_value, target_ulong write_mask);
|
||||
int riscv_csrrw_debug(CPURISCVState *env, int csrno, target_ulong *ret_value,
|
||||
target_ulong new_value, target_ulong write_mask);
|
||||
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_value,
|
||||
target_ulong new_value, target_ulong write_mask);
|
||||
RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_value,
|
||||
target_ulong new_value,
|
||||
target_ulong write_mask);
|
||||
|
||||
static inline void riscv_csr_write(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
@ -473,13 +472,16 @@ static inline target_ulong riscv_csr_read(CPURISCVState *env, int csrno)
|
||||
return val;
|
||||
}
|
||||
|
||||
typedef int (*riscv_csr_predicate_fn)(CPURISCVState *env, int csrno);
|
||||
typedef int (*riscv_csr_read_fn)(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_value);
|
||||
typedef int (*riscv_csr_write_fn)(CPURISCVState *env, int csrno,
|
||||
target_ulong new_value);
|
||||
typedef int (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_value, target_ulong new_value, target_ulong write_mask);
|
||||
typedef RISCVException (*riscv_csr_predicate_fn)(CPURISCVState *env,
|
||||
int csrno);
|
||||
typedef RISCVException (*riscv_csr_read_fn)(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_value);
|
||||
typedef RISCVException (*riscv_csr_write_fn)(CPURISCVState *env, int csrno,
|
||||
target_ulong new_value);
|
||||
typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
|
||||
target_ulong *ret_value,
|
||||
target_ulong new_value,
|
||||
target_ulong write_mask);
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
|
@ -153,12 +153,6 @@
|
||||
/* 32-bit only */
|
||||
#define CSR_MSTATUSH 0x310
|
||||
|
||||
/* Legacy Counter Setup (priv v1.9.1) */
|
||||
/* Update to #define CSR_MCOUNTINHIBIT 0x320 for 1.11.0 */
|
||||
#define CSR_MUCOUNTEREN 0x320
|
||||
#define CSR_MSCOUNTEREN 0x321
|
||||
#define CSR_MHCOUNTEREN 0x322
|
||||
|
||||
/* Machine Trap Handling */
|
||||
#define CSR_MSCRATCH 0x340
|
||||
#define CSR_MEPC 0x341
|
||||
@ -166,9 +160,6 @@
|
||||
#define CSR_MTVAL 0x343
|
||||
#define CSR_MIP 0x344
|
||||
|
||||
/* Legacy Machine Trap Handling (priv v1.9.1) */
|
||||
#define CSR_MBADADDR 0x343
|
||||
|
||||
/* Supervisor Trap Setup */
|
||||
#define CSR_SSTATUS 0x100
|
||||
#define CSR_SEDELEG 0x102
|
||||
@ -184,9 +175,6 @@
|
||||
#define CSR_STVAL 0x143
|
||||
#define CSR_SIP 0x144
|
||||
|
||||
/* Legacy Supervisor Trap Handling (priv v1.9.1) */
|
||||
#define CSR_SBADADDR 0x143
|
||||
|
||||
/* Supervisor Protection and Translation */
|
||||
#define CSR_SPTBR 0x180
|
||||
#define CSR_SATP 0x180
|
||||
@ -207,17 +195,6 @@
|
||||
#define CSR_HTIMEDELTA 0x605
|
||||
#define CSR_HTIMEDELTAH 0x615
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
#define HGATP_MODE SATP32_MODE
|
||||
#define HGATP_VMID SATP32_ASID
|
||||
#define HGATP_PPN SATP32_PPN
|
||||
#endif
|
||||
#if defined(TARGET_RISCV64)
|
||||
#define HGATP_MODE SATP64_MODE
|
||||
#define HGATP_VMID SATP64_ASID
|
||||
#define HGATP_PPN SATP64_PPN
|
||||
#endif
|
||||
|
||||
/* Virtual CSRs */
|
||||
#define CSR_VSSTATUS 0x200
|
||||
#define CSR_VSIE 0x204
|
||||
@ -232,6 +209,9 @@
|
||||
#define CSR_MTINST 0x34a
|
||||
#define CSR_MTVAL2 0x34b
|
||||
|
||||
/* Enhanced Physical Memory Protection (ePMP) */
|
||||
#define CSR_MSECCFG 0x390
|
||||
#define CSR_MSECCFGH 0x391
|
||||
/* Physical Memory Protection */
|
||||
#define CSR_PMPCFG0 0x3a0
|
||||
#define CSR_PMPCFG1 0x3a1
|
||||
@ -354,14 +334,6 @@
|
||||
#define CSR_MHPMCOUNTER30H 0xb9e
|
||||
#define CSR_MHPMCOUNTER31H 0xb9f
|
||||
|
||||
/* Legacy Machine Protection and Translation (priv v1.9.1) */
|
||||
#define CSR_MBASE 0x380
|
||||
#define CSR_MBOUND 0x381
|
||||
#define CSR_MIBASE 0x382
|
||||
#define CSR_MIBOUND 0x383
|
||||
#define CSR_MDBASE 0x384
|
||||
#define CSR_MDBOUND 0x385
|
||||
|
||||
/* mstatus CSR bits */
|
||||
#define MSTATUS_UIE 0x00000001
|
||||
#define MSTATUS_SIE 0x00000002
|
||||
@ -375,10 +347,8 @@
|
||||
#define MSTATUS_FS 0x00006000
|
||||
#define MSTATUS_XS 0x00018000
|
||||
#define MSTATUS_MPRV 0x00020000
|
||||
#define MSTATUS_PUM 0x00040000 /* until: priv-1.9.1 */
|
||||
#define MSTATUS_SUM 0x00040000 /* since: priv-1.10 */
|
||||
#define MSTATUS_MXR 0x00080000
|
||||
#define MSTATUS_VM 0x1F000000 /* until: priv-1.9.1 */
|
||||
#define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */
|
||||
#define MSTATUS_TW 0x00200000 /* since: priv-1.10 */
|
||||
#define MSTATUS_TSR 0x00400000 /* since: priv-1.10 */
|
||||
@ -398,16 +368,6 @@
|
||||
#define MXL_RV64 2
|
||||
#define MXL_RV128 3
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
#define MSTATUS_SD MSTATUS32_SD
|
||||
#define MISA_MXL MISA32_MXL
|
||||
#define MXL_VAL MXL_RV32
|
||||
#elif defined(TARGET_RISCV64)
|
||||
#define MSTATUS_SD MSTATUS64_SD
|
||||
#define MISA_MXL MISA64_MXL
|
||||
#define MXL_VAL MXL_RV64
|
||||
#endif
|
||||
|
||||
/* sstatus CSR bits */
|
||||
#define SSTATUS_UIE 0x00000001
|
||||
#define SSTATUS_SIE 0x00000002
|
||||
@ -416,19 +376,12 @@
|
||||
#define SSTATUS_SPP 0x00000100
|
||||
#define SSTATUS_FS 0x00006000
|
||||
#define SSTATUS_XS 0x00018000
|
||||
#define SSTATUS_PUM 0x00040000 /* until: priv-1.9.1 */
|
||||
#define SSTATUS_SUM 0x00040000 /* since: priv-1.10 */
|
||||
#define SSTATUS_MXR 0x00080000
|
||||
|
||||
#define SSTATUS32_SD 0x80000000
|
||||
#define SSTATUS64_SD 0x8000000000000000ULL
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
#define SSTATUS_SD SSTATUS32_SD
|
||||
#elif defined(TARGET_RISCV64)
|
||||
#define SSTATUS_SD SSTATUS64_SD
|
||||
#endif
|
||||
|
||||
/* hstatus CSR bits */
|
||||
#define HSTATUS_VSBE 0x00000020
|
||||
#define HSTATUS_GVA 0x00000040
|
||||
@ -443,12 +396,6 @@
|
||||
#define HSTATUS32_WPRI 0xFF8FF87E
|
||||
#define HSTATUS64_WPRI 0xFFFFFFFFFF8FF87EULL
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
#define HSTATUS_WPRI HSTATUS32_WPRI
|
||||
#elif defined(TARGET_RISCV64)
|
||||
#define HSTATUS_WPRI HSTATUS64_WPRI
|
||||
#endif
|
||||
|
||||
#define HCOUNTEREN_CY (1 << 0)
|
||||
#define HCOUNTEREN_TM (1 << 1)
|
||||
#define HCOUNTEREN_IR (1 << 2)
|
||||
@ -479,17 +426,6 @@
|
||||
#define SATP64_ASID 0x0FFFF00000000000ULL
|
||||
#define SATP64_PPN 0x00000FFFFFFFFFFFULL
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
#define SATP_MODE SATP32_MODE
|
||||
#define SATP_ASID SATP32_ASID
|
||||
#define SATP_PPN SATP32_PPN
|
||||
#endif
|
||||
#if defined(TARGET_RISCV64)
|
||||
#define SATP_MODE SATP64_MODE
|
||||
#define SATP_ASID SATP64_ASID
|
||||
#define SATP_PPN SATP64_PPN
|
||||
#endif
|
||||
|
||||
/* VM modes (mstatus.vm) privileged ISA 1.9.1 */
|
||||
#define VM_1_09_MBARE 0
|
||||
#define VM_1_09_MBB 1
|
||||
@ -527,27 +463,29 @@
|
||||
#define DEFAULT_RSTVEC 0x1000
|
||||
|
||||
/* Exception causes */
|
||||
#define EXCP_NONE -1 /* sentinel value */
|
||||
#define RISCV_EXCP_INST_ADDR_MIS 0x0
|
||||
#define RISCV_EXCP_INST_ACCESS_FAULT 0x1
|
||||
#define RISCV_EXCP_ILLEGAL_INST 0x2
|
||||
#define RISCV_EXCP_BREAKPOINT 0x3
|
||||
#define RISCV_EXCP_LOAD_ADDR_MIS 0x4
|
||||
#define RISCV_EXCP_LOAD_ACCESS_FAULT 0x5
|
||||
#define RISCV_EXCP_STORE_AMO_ADDR_MIS 0x6
|
||||
#define RISCV_EXCP_STORE_AMO_ACCESS_FAULT 0x7
|
||||
#define RISCV_EXCP_U_ECALL 0x8
|
||||
#define RISCV_EXCP_S_ECALL 0x9
|
||||
#define RISCV_EXCP_VS_ECALL 0xa
|
||||
#define RISCV_EXCP_M_ECALL 0xb
|
||||
#define RISCV_EXCP_INST_PAGE_FAULT 0xc /* since: priv-1.10.0 */
|
||||
#define RISCV_EXCP_LOAD_PAGE_FAULT 0xd /* since: priv-1.10.0 */
|
||||
#define RISCV_EXCP_STORE_PAGE_FAULT 0xf /* since: priv-1.10.0 */
|
||||
#define RISCV_EXCP_SEMIHOST 0x10
|
||||
#define RISCV_EXCP_INST_GUEST_PAGE_FAULT 0x14
|
||||
#define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT 0x15
|
||||
#define RISCV_EXCP_VIRT_INSTRUCTION_FAULT 0x16
|
||||
#define RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT 0x17
|
||||
typedef enum RISCVException {
|
||||
RISCV_EXCP_NONE = -1, /* sentinel value */
|
||||
RISCV_EXCP_INST_ADDR_MIS = 0x0,
|
||||
RISCV_EXCP_INST_ACCESS_FAULT = 0x1,
|
||||
RISCV_EXCP_ILLEGAL_INST = 0x2,
|
||||
RISCV_EXCP_BREAKPOINT = 0x3,
|
||||
RISCV_EXCP_LOAD_ADDR_MIS = 0x4,
|
||||
RISCV_EXCP_LOAD_ACCESS_FAULT = 0x5,
|
||||
RISCV_EXCP_STORE_AMO_ADDR_MIS = 0x6,
|
||||
RISCV_EXCP_STORE_AMO_ACCESS_FAULT = 0x7,
|
||||
RISCV_EXCP_U_ECALL = 0x8,
|
||||
RISCV_EXCP_S_ECALL = 0x9,
|
||||
RISCV_EXCP_VS_ECALL = 0xa,
|
||||
RISCV_EXCP_M_ECALL = 0xb,
|
||||
RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
|
||||
RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
|
||||
RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
|
||||
RISCV_EXCP_SEMIHOST = 0x10,
|
||||
RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
|
||||
RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT = 0x15,
|
||||
RISCV_EXCP_VIRT_INSTRUCTION_FAULT = 0x16,
|
||||
RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT = 0x17,
|
||||
} RISCVException;
|
||||
|
||||
#define RISCV_EXCP_INT_FLAG 0x80000000
|
||||
#define RISCV_EXCP_INT_MASK 0x7fffffff
|
||||
|
@ -72,7 +72,7 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
|
||||
if (irqs) {
|
||||
return ctz64(irqs); /* since non-zero */
|
||||
} else {
|
||||
return EXCP_NONE; /* indicates no pending interrupt */
|
||||
return RISCV_EXCP_NONE; /* indicates no pending interrupt */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -136,8 +136,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
|
||||
env->vscause = env->scause;
|
||||
env->scause = env->scause_hs;
|
||||
|
||||
env->vstval = env->sbadaddr;
|
||||
env->sbadaddr = env->stval_hs;
|
||||
env->vstval = env->stval;
|
||||
env->stval = env->stval_hs;
|
||||
|
||||
env->vsatp = env->satp;
|
||||
env->satp = env->satp_hs;
|
||||
@ -159,8 +159,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
|
||||
env->scause_hs = env->scause;
|
||||
env->scause = env->vscause;
|
||||
|
||||
env->stval_hs = env->sbadaddr;
|
||||
env->sbadaddr = env->vstval;
|
||||
env->stval_hs = env->stval;
|
||||
env->stval = env->vstval;
|
||||
|
||||
env->satp_hs = env->satp;
|
||||
env->satp = env->vsatp;
|
||||
@ -342,12 +342,14 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot,
|
||||
* @first_stage: Are we in first stage translation?
|
||||
* Second stage is used for hypervisor guest translation
|
||||
* @two_stage: Are we going to perform two stage translation
|
||||
* @is_debug: Is this access from a debugger or the monitor?
|
||||
*/
|
||||
static int get_physical_address(CPURISCVState *env, hwaddr *physical,
|
||||
int *prot, target_ulong addr,
|
||||
target_ulong *fault_pte_addr,
|
||||
int access_type, int mmu_idx,
|
||||
bool first_stage, bool two_stage)
|
||||
bool first_stage, bool two_stage,
|
||||
bool is_debug)
|
||||
{
|
||||
/* NOTE: the env->pc value visible here will not be
|
||||
* correct, but the value visible to the exception handler
|
||||
@ -403,20 +405,35 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
|
||||
|
||||
if (first_stage == true) {
|
||||
if (use_background) {
|
||||
base = (hwaddr)get_field(env->vsatp, SATP_PPN) << PGSHIFT;
|
||||
vm = get_field(env->vsatp, SATP_MODE);
|
||||
if (riscv_cpu_is_32bit(env)) {
|
||||
base = (hwaddr)get_field(env->vsatp, SATP32_PPN) << PGSHIFT;
|
||||
vm = get_field(env->vsatp, SATP32_MODE);
|
||||
} else {
|
||||
base = (hwaddr)get_field(env->vsatp, SATP64_PPN) << PGSHIFT;
|
||||
vm = get_field(env->vsatp, SATP64_MODE);
|
||||
}
|
||||
} else {
|
||||
base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
|
||||
vm = get_field(env->satp, SATP_MODE);
|
||||
if (riscv_cpu_is_32bit(env)) {
|
||||
base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT;
|
||||
vm = get_field(env->satp, SATP32_MODE);
|
||||
} else {
|
||||
base = (hwaddr)get_field(env->satp, SATP64_PPN) << PGSHIFT;
|
||||
vm = get_field(env->satp, SATP64_MODE);
|
||||
}
|
||||
}
|
||||
widened = 0;
|
||||
} else {
|
||||
base = (hwaddr)get_field(env->hgatp, HGATP_PPN) << PGSHIFT;
|
||||
vm = get_field(env->hgatp, HGATP_MODE);
|
||||
if (riscv_cpu_is_32bit(env)) {
|
||||
base = (hwaddr)get_field(env->hgatp, SATP32_PPN) << PGSHIFT;
|
||||
vm = get_field(env->hgatp, SATP32_MODE);
|
||||
} else {
|
||||
base = (hwaddr)get_field(env->hgatp, SATP64_PPN) << PGSHIFT;
|
||||
vm = get_field(env->hgatp, SATP64_MODE);
|
||||
}
|
||||
widened = 2;
|
||||
}
|
||||
/* status.SUM will be ignored if execute on background */
|
||||
sum = get_field(env->mstatus, MSTATUS_SUM) || use_background;
|
||||
sum = get_field(env->mstatus, MSTATUS_SUM) || use_background || is_debug;
|
||||
switch (vm) {
|
||||
case VM_1_10_SV32:
|
||||
levels = 2; ptidxbits = 10; ptesize = 4; break;
|
||||
@ -475,7 +492,8 @@ restart:
|
||||
/* Do the second stage translation on the base PTE address. */
|
||||
int vbase_ret = get_physical_address(env, &vbase, &vbase_prot,
|
||||
base, NULL, MMU_DATA_LOAD,
|
||||
mmu_idx, false, true);
|
||||
mmu_idx, false, true,
|
||||
is_debug);
|
||||
|
||||
if (vbase_ret != TRANSLATE_SUCCESS) {
|
||||
if (fault_pte_addr) {
|
||||
@ -615,16 +633,23 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
|
||||
bool first_stage, bool two_stage)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int page_fault_exceptions;
|
||||
if (first_stage) {
|
||||
page_fault_exceptions =
|
||||
get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
|
||||
!pmp_violation;
|
||||
int page_fault_exceptions, vm;
|
||||
uint64_t stap_mode;
|
||||
|
||||
if (riscv_cpu_is_32bit(env)) {
|
||||
stap_mode = SATP32_MODE;
|
||||
} else {
|
||||
page_fault_exceptions =
|
||||
get_field(env->hgatp, HGATP_MODE) != VM_1_10_MBARE &&
|
||||
!pmp_violation;
|
||||
stap_mode = SATP64_MODE;
|
||||
}
|
||||
|
||||
if (first_stage) {
|
||||
vm = get_field(env->satp, stap_mode);
|
||||
} else {
|
||||
vm = get_field(env->hgatp, stap_mode);
|
||||
}
|
||||
|
||||
page_fault_exceptions = vm != VM_1_10_MBARE && !pmp_violation;
|
||||
|
||||
switch (access_type) {
|
||||
case MMU_INST_FETCH:
|
||||
if (riscv_cpu_virt_enabled(env) && !first_stage) {
|
||||
@ -666,13 +691,13 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
int mmu_idx = cpu_mmu_index(&cpu->env, false);
|
||||
|
||||
if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx,
|
||||
true, riscv_cpu_virt_enabled(env))) {
|
||||
true, riscv_cpu_virt_enabled(env), true)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (riscv_cpu_virt_enabled(env)) {
|
||||
if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL,
|
||||
0, mmu_idx, false, true)) {
|
||||
0, mmu_idx, false, true, true)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -691,8 +716,10 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
|
||||
|
||||
if (access_type == MMU_DATA_STORE) {
|
||||
cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
|
||||
} else {
|
||||
} else if (access_type == MMU_DATA_LOAD) {
|
||||
cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
|
||||
} else {
|
||||
cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
|
||||
}
|
||||
|
||||
env->badaddr = addr;
|
||||
@ -768,7 +795,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
/* Two stage lookup */
|
||||
ret = get_physical_address(env, &pa, &prot, address,
|
||||
&env->guest_phys_fault_addr, access_type,
|
||||
mmu_idx, true, true);
|
||||
mmu_idx, true, true, false);
|
||||
|
||||
/*
|
||||
* A G-stage exception may be triggered during two state lookup.
|
||||
@ -790,7 +817,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
im_address = pa;
|
||||
|
||||
ret = get_physical_address(env, &pa, &prot2, im_address, NULL,
|
||||
access_type, mmu_idx, false, true);
|
||||
access_type, mmu_idx, false, true,
|
||||
false);
|
||||
|
||||
qemu_log_mask(CPU_LOG_MMU,
|
||||
"%s 2nd-stage address=%" VADDR_PRIx " ret %d physical "
|
||||
@ -825,7 +853,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
} else {
|
||||
/* Single stage lookup */
|
||||
ret = get_physical_address(env, &pa, &prot, address, NULL,
|
||||
access_type, mmu_idx, true, false);
|
||||
access_type, mmu_idx, true, false, false);
|
||||
|
||||
qemu_log_mask(CPU_LOG_MMU,
|
||||
"%s address=%" VADDR_PRIx " ret %d physical "
|
||||
@ -1023,7 +1051,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
||||
env->mstatus = s;
|
||||
env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
|
||||
env->sepc = env->pc;
|
||||
env->sbadaddr = tval;
|
||||
env->stval = tval;
|
||||
env->htval = htval;
|
||||
env->pc = (env->stvec >> 2 << 2) +
|
||||
((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
|
||||
@ -1054,7 +1082,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
||||
env->mstatus = s;
|
||||
env->mcause = cause | ~(((target_ulong)-1) >> async);
|
||||
env->mepc = env->pc;
|
||||
env->mbadaddr = tval;
|
||||
env->mtval = tval;
|
||||
env->mtval2 = mtval2;
|
||||
env->pc = (env->mtvec >> 2 << 2) +
|
||||
((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
|
||||
@ -1069,5 +1097,5 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
||||
|
||||
env->two_stage_lookup = false;
|
||||
#endif
|
||||
cs->exception_index = EXCP_NONE; /* mark handled to qemu */
|
||||
cs->exception_index = RISCV_EXCP_NONE; /* mark handled to qemu */
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -223,13 +223,13 @@ target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1)
|
||||
return (int32_t)float32_to_uint32(frs1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
|
||||
target_ulong helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return float32_to_int64(frs1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)
|
||||
target_ulong helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)
|
||||
{
|
||||
float32 frs1 = check_nanbox_s(rs1);
|
||||
return float32_to_uint64(frs1, &env->fp_status);
|
||||
@ -245,12 +245,12 @@ uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
|
||||
return nanbox_s(uint32_to_float32((uint32_t)rs1, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_s_l(CPURISCVState *env, uint64_t rs1)
|
||||
uint64_t helper_fcvt_s_l(CPURISCVState *env, target_ulong rs1)
|
||||
{
|
||||
return nanbox_s(int64_to_float32(rs1, &env->fp_status));
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1)
|
||||
uint64_t helper_fcvt_s_lu(CPURISCVState *env, target_ulong rs1)
|
||||
{
|
||||
return nanbox_s(uint64_to_float32(rs1, &env->fp_status));
|
||||
}
|
||||
@ -332,12 +332,12 @@ target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1)
|
||||
return (int32_t)float64_to_uint32(frs1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
|
||||
target_ulong helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
|
||||
{
|
||||
return float64_to_int64(frs1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1)
|
||||
target_ulong helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1)
|
||||
{
|
||||
return float64_to_uint64(frs1, &env->fp_status);
|
||||
}
|
||||
@ -352,12 +352,12 @@ uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1)
|
||||
return uint32_to_float64((uint32_t)rs1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_d_l(CPURISCVState *env, uint64_t rs1)
|
||||
uint64_t helper_fcvt_d_l(CPURISCVState *env, target_ulong rs1)
|
||||
{
|
||||
return int64_to_float64(rs1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint64_t helper_fcvt_d_lu(CPURISCVState *env, uint64_t rs1)
|
||||
uint64_t helper_fcvt_d_lu(CPURISCVState *env, target_ulong rs1)
|
||||
{
|
||||
return uint64_to_float64(rs1, &env->fp_status);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n)
|
||||
*/
|
||||
result = riscv_csrrw_debug(env, n - 32, &val,
|
||||
0, 0);
|
||||
if (result == 0) {
|
||||
if (result == RISCV_EXCP_NONE) {
|
||||
return gdb_get_regl(buf, val);
|
||||
}
|
||||
}
|
||||
@ -94,7 +94,7 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||
*/
|
||||
result = riscv_csrrw_debug(env, n - 32, NULL,
|
||||
val, -1);
|
||||
if (result == 0) {
|
||||
if (result == RISCV_EXCP_NONE) {
|
||||
return sizeof(target_ulong);
|
||||
}
|
||||
}
|
||||
@ -108,7 +108,7 @@ static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n)
|
||||
int result;
|
||||
|
||||
result = riscv_csrrw_debug(env, n, &val, 0, 0);
|
||||
if (result == 0) {
|
||||
if (result == RISCV_EXCP_NONE) {
|
||||
return gdb_get_regl(buf, val);
|
||||
}
|
||||
}
|
||||
@ -122,7 +122,7 @@ static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||
int result;
|
||||
|
||||
result = riscv_csrrw_debug(env, n, NULL, val, -1);
|
||||
if (result == 0) {
|
||||
if (result == RISCV_EXCP_NONE) {
|
||||
return sizeof(target_ulong);
|
||||
}
|
||||
}
|
||||
|
@ -27,12 +27,12 @@ DEF_HELPER_FLAGS_3(flt_s, TCG_CALL_NO_RWG, tl, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(feq_s, TCG_CALL_NO_RWG, tl, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_w_s, TCG_CALL_NO_RWG, tl, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_wu_s, TCG_CALL_NO_RWG, tl, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_l_s, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_lu_s, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_l_s, TCG_CALL_NO_RWG, tl, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_lu_s, TCG_CALL_NO_RWG, tl, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_s_w, TCG_CALL_NO_RWG, i64, env, tl)
|
||||
DEF_HELPER_FLAGS_2(fcvt_s_wu, TCG_CALL_NO_RWG, i64, env, tl)
|
||||
DEF_HELPER_FLAGS_2(fcvt_s_l, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_s_lu, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_s_l, TCG_CALL_NO_RWG, i64, env, tl)
|
||||
DEF_HELPER_FLAGS_2(fcvt_s_lu, TCG_CALL_NO_RWG, i64, env, tl)
|
||||
DEF_HELPER_FLAGS_1(fclass_s, TCG_CALL_NO_RWG_SE, tl, i64)
|
||||
|
||||
/* Floating Point - Double Precision */
|
||||
@ -50,12 +50,12 @@ DEF_HELPER_FLAGS_3(flt_d, TCG_CALL_NO_RWG, tl, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(feq_d, TCG_CALL_NO_RWG, tl, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_w_d, TCG_CALL_NO_RWG, tl, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_wu_d, TCG_CALL_NO_RWG, tl, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_l_d, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_lu_d, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_l_d, TCG_CALL_NO_RWG, tl, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_lu_d, TCG_CALL_NO_RWG, tl, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_d_w, TCG_CALL_NO_RWG, i64, env, tl)
|
||||
DEF_HELPER_FLAGS_2(fcvt_d_wu, TCG_CALL_NO_RWG, i64, env, tl)
|
||||
DEF_HELPER_FLAGS_2(fcvt_d_l, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, i64)
|
||||
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)
|
||||
|
||||
/* Special functions */
|
||||
@ -241,7 +241,6 @@ DEF_HELPER_5(vlhuff_v_w, void, ptr, ptr, tl, env, i32)
|
||||
DEF_HELPER_5(vlhuff_v_d, void, ptr, ptr, tl, env, i32)
|
||||
DEF_HELPER_5(vlwuff_v_w, void, ptr, ptr, tl, env, i32)
|
||||
DEF_HELPER_5(vlwuff_v_d, void, ptr, ptr, tl, env, i32)
|
||||
#ifdef TARGET_RISCV64
|
||||
DEF_HELPER_6(vamoswapw_v_d, void, ptr, ptr, tl, ptr, env, i32)
|
||||
DEF_HELPER_6(vamoswapd_v_d, void, ptr, ptr, tl, ptr, env, i32)
|
||||
DEF_HELPER_6(vamoaddw_v_d, void, ptr, ptr, tl, ptr, env, i32)
|
||||
@ -260,7 +259,6 @@ DEF_HELPER_6(vamominuw_v_d, void, ptr, ptr, tl, ptr, env, i32)
|
||||
DEF_HELPER_6(vamominud_v_d, void, ptr, ptr, tl, ptr, env, i32)
|
||||
DEF_HELPER_6(vamomaxuw_v_d, void, ptr, ptr, tl, ptr, env, i32)
|
||||
DEF_HELPER_6(vamomaxud_v_d, void, ptr, ptr, tl, ptr, env, i32)
|
||||
#endif
|
||||
DEF_HELPER_6(vamoswapw_v_w, void, ptr, ptr, tl, ptr, env, i32)
|
||||
DEF_HELPER_6(vamoaddw_v_w, void, ptr, ptr, tl, ptr, env, i32)
|
||||
DEF_HELPER_6(vamoxorw_v_w, void, ptr, ptr, tl, ptr, env, i32)
|
||||
|
@ -1,28 +0,0 @@
|
||||
#
|
||||
# RISC-V translation routines for the RVXI Base Integer Instruction Set.
|
||||
#
|
||||
# Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
|
||||
# Bastian Koppelmann, kbastian@mail.uni-paderborn.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms and conditions of the GNU General Public License,
|
||||
# version 2 or later, as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# *** RV32C Standard Extension (Quadrant 0) ***
|
||||
flw 011 ... ... .. ... 00 @cl_w
|
||||
fsw 111 ... ... .. ... 00 @cs_w
|
||||
|
||||
# *** RV32C Standard Extension (Quadrant 1) ***
|
||||
jal 001 ........... 01 @cj rd=1 # C.JAL
|
||||
|
||||
# *** RV32C Standard Extension (Quadrant 2) ***
|
||||
flw 011 . ..... ..... 10 @c_lwsp
|
||||
fsw 111 . ..... ..... 10 @c_swsp
|
@ -1,36 +0,0 @@
|
||||
#
|
||||
# RISC-V translation routines for the RVXI Base Integer Instruction Set.
|
||||
#
|
||||
# Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
|
||||
# Bastian Koppelmann, kbastian@mail.uni-paderborn.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms and conditions of the GNU General Public License,
|
||||
# version 2 or later, as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# *** RV64C Standard Extension (Quadrant 0) ***
|
||||
ld 011 ... ... .. ... 00 @cl_d
|
||||
sd 111 ... ... .. ... 00 @cs_d
|
||||
|
||||
# *** RV64C Standard Extension (Quadrant 1) ***
|
||||
{
|
||||
illegal 001 - 00000 ----- 01 # c.addiw, RES rd=0
|
||||
addiw 001 . ..... ..... 01 @ci
|
||||
}
|
||||
subw 100 1 11 ... 00 ... 01 @cs_2
|
||||
addw 100 1 11 ... 01 ... 01 @cs_2
|
||||
|
||||
# *** RV64C Standard Extension (Quadrant 2) ***
|
||||
{
|
||||
illegal 011 - 00000 ----- 10 # c.ldsp, RES rd=0
|
||||
ld 011 . ..... ..... 10 @c_ldsp
|
||||
}
|
||||
sd 111 . ..... ..... 10 @c_sdsp
|
@ -92,6 +92,16 @@ lw 010 ... ... .. ... 00 @cl_w
|
||||
fsd 101 ... ... .. ... 00 @cs_d
|
||||
sw 110 ... ... .. ... 00 @cs_w
|
||||
|
||||
# *** RV32C and RV64C specific Standard Extension (Quadrant 0) ***
|
||||
{
|
||||
ld 011 ... ... .. ... 00 @cl_d
|
||||
flw 011 ... ... .. ... 00 @cl_w
|
||||
}
|
||||
{
|
||||
sd 111 ... ... .. ... 00 @cs_d
|
||||
fsw 111 ... ... .. ... 00 @cs_w
|
||||
}
|
||||
|
||||
# *** RV32/64C Standard Extension (Quadrant 1) ***
|
||||
addi 000 . ..... ..... 01 @ci
|
||||
addi 010 . ..... ..... 01 @c_li
|
||||
@ -111,6 +121,15 @@ jal 101 ........... 01 @cj rd=0 # C.J
|
||||
beq 110 ... ... ..... 01 @cb_z
|
||||
bne 111 ... ... ..... 01 @cb_z
|
||||
|
||||
# *** RV64C and RV32C specific Standard Extension (Quadrant 1) ***
|
||||
{
|
||||
c64_illegal 001 - 00000 ----- 01 # c.addiw, RES rd=0
|
||||
addiw 001 . ..... ..... 01 @ci
|
||||
jal 001 ........... 01 @cj rd=1 # C.JAL
|
||||
}
|
||||
subw 100 1 11 ... 00 ... 01 @cs_2
|
||||
addw 100 1 11 ... 01 ... 01 @cs_2
|
||||
|
||||
# *** RV32/64C Standard Extension (Quadrant 2) ***
|
||||
slli 000 . ..... ..... 10 @c_shift2
|
||||
fld 001 . ..... ..... 10 @c_ldsp
|
||||
@ -130,3 +149,14 @@ fld 001 . ..... ..... 10 @c_ldsp
|
||||
}
|
||||
fsd 101 ...... ..... 10 @c_sdsp
|
||||
sw 110 . ..... ..... 10 @c_swsp
|
||||
|
||||
# *** RV32C and RV64C specific Standard Extension (Quadrant 2) ***
|
||||
{
|
||||
c64_illegal 011 - 00000 ----- 10 # c.ldsp, RES rd=0
|
||||
ld 011 . ..... ..... 10 @c_ldsp
|
||||
flw 011 . ..... ..... 10 @c_lwsp
|
||||
}
|
||||
{
|
||||
sd 111 . ..... ..... 10 @c_sdsp
|
||||
fsw 111 . ..... ..... 10 @c_swsp
|
||||
}
|
||||
|
@ -1,88 +0,0 @@
|
||||
#
|
||||
# RISC-V translation routines for the RV Instruction Set.
|
||||
#
|
||||
# Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
|
||||
# Bastian Koppelmann, kbastian@mail.uni-paderborn.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms and conditions of the GNU General Public License,
|
||||
# version 2 or later, as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This is concatenated with insn32.decode for risc64 targets.
|
||||
# Most of the fields and formats are there.
|
||||
|
||||
%sh5 20:5
|
||||
|
||||
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
|
||||
|
||||
# *** RV64I Base Instruction Set (in addition to RV32I) ***
|
||||
lwu ............ ..... 110 ..... 0000011 @i
|
||||
ld ............ ..... 011 ..... 0000011 @i
|
||||
sd ....... ..... ..... 011 ..... 0100011 @s
|
||||
addiw ............ ..... 000 ..... 0011011 @i
|
||||
slliw 0000000 ..... ..... 001 ..... 0011011 @sh5
|
||||
srliw 0000000 ..... ..... 101 ..... 0011011 @sh5
|
||||
sraiw 0100000 ..... ..... 101 ..... 0011011 @sh5
|
||||
addw 0000000 ..... ..... 000 ..... 0111011 @r
|
||||
subw 0100000 ..... ..... 000 ..... 0111011 @r
|
||||
sllw 0000000 ..... ..... 001 ..... 0111011 @r
|
||||
srlw 0000000 ..... ..... 101 ..... 0111011 @r
|
||||
sraw 0100000 ..... ..... 101 ..... 0111011 @r
|
||||
|
||||
# *** RV64M Standard Extension (in addition to RV32M) ***
|
||||
mulw 0000001 ..... ..... 000 ..... 0111011 @r
|
||||
divw 0000001 ..... ..... 100 ..... 0111011 @r
|
||||
divuw 0000001 ..... ..... 101 ..... 0111011 @r
|
||||
remw 0000001 ..... ..... 110 ..... 0111011 @r
|
||||
remuw 0000001 ..... ..... 111 ..... 0111011 @r
|
||||
|
||||
# *** RV64A Standard Extension (in addition to RV32A) ***
|
||||
lr_d 00010 . . 00000 ..... 011 ..... 0101111 @atom_ld
|
||||
sc_d 00011 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoswap_d 00001 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoadd_d 00000 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoxor_d 00100 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoand_d 01100 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoor_d 01000 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amomin_d 10000 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amomax_d 10100 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amominu_d 11000 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amomaxu_d 11100 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
|
||||
#*** Vector AMO operations (in addition to Zvamo) ***
|
||||
vamoswapd_v 00001 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
vamoaddd_v 00000 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
vamoxord_v 00100 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
vamoandd_v 01100 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
vamoord_v 01000 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
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
|
||||
|
||||
# *** RV64F Standard Extension (in addition to RV32F) ***
|
||||
fcvt_l_s 1100000 00010 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_lu_s 1100000 00011 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_s_l 1101000 00010 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_s_lu 1101000 00011 ..... ... ..... 1010011 @r2_rm
|
||||
|
||||
# *** RV64D Standard Extension (in addition to RV32D) ***
|
||||
fcvt_l_d 1100001 00010 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_lu_d 1100001 00011 ..... ... ..... 1010011 @r2_rm
|
||||
fmv_x_d 1110001 00000 ..... 000 ..... 1010011 @r2
|
||||
fcvt_d_l 1101001 00010 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_d_lu 1101001 00011 ..... ... ..... 1010011 @r2_rm
|
||||
fmv_d_x 1111001 00000 ..... 000 ..... 1010011 @r2
|
||||
|
||||
# *** RV32H Base Instruction Set ***
|
||||
hlv_wu 0110100 00001 ..... 100 ..... 1110011 @r2
|
||||
hlv_d 0110110 00000 ..... 100 ..... 1110011 @r2
|
||||
hsv_d 0110111 ..... ..... 100 00000 1110011 @r2_s
|
@ -21,6 +21,7 @@
|
||||
%rs2 20:5
|
||||
%rs1 15:5
|
||||
%rd 7:5
|
||||
%sh5 20:5
|
||||
|
||||
%sh10 20:10
|
||||
%csr 20:12
|
||||
@ -86,6 +87,8 @@
|
||||
@sfence_vma ....... ..... ..... ... ..... ....... %rs2 %rs1
|
||||
@sfence_vm ....... ..... ..... ... ..... ....... %rs1
|
||||
|
||||
# Formats 64:
|
||||
@sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd
|
||||
|
||||
# *** Privileged Instructions ***
|
||||
ecall 000000000000 00000 000 00000 1110011
|
||||
@ -144,6 +147,20 @@ csrrwi ............ ..... 101 ..... 1110011 @csr
|
||||
csrrsi ............ ..... 110 ..... 1110011 @csr
|
||||
csrrci ............ ..... 111 ..... 1110011 @csr
|
||||
|
||||
# *** RV64I Base Instruction Set (in addition to RV32I) ***
|
||||
lwu ............ ..... 110 ..... 0000011 @i
|
||||
ld ............ ..... 011 ..... 0000011 @i
|
||||
sd ....... ..... ..... 011 ..... 0100011 @s
|
||||
addiw ............ ..... 000 ..... 0011011 @i
|
||||
slliw 0000000 ..... ..... 001 ..... 0011011 @sh5
|
||||
srliw 0000000 ..... ..... 101 ..... 0011011 @sh5
|
||||
sraiw 0100000 ..... ..... 101 ..... 0011011 @sh5
|
||||
addw 0000000 ..... ..... 000 ..... 0111011 @r
|
||||
subw 0100000 ..... ..... 000 ..... 0111011 @r
|
||||
sllw 0000000 ..... ..... 001 ..... 0111011 @r
|
||||
srlw 0000000 ..... ..... 101 ..... 0111011 @r
|
||||
sraw 0100000 ..... ..... 101 ..... 0111011 @r
|
||||
|
||||
# *** RV32M Standard Extension ***
|
||||
mul 0000001 ..... ..... 000 ..... 0110011 @r
|
||||
mulh 0000001 ..... ..... 001 ..... 0110011 @r
|
||||
@ -154,6 +171,13 @@ divu 0000001 ..... ..... 101 ..... 0110011 @r
|
||||
rem 0000001 ..... ..... 110 ..... 0110011 @r
|
||||
remu 0000001 ..... ..... 111 ..... 0110011 @r
|
||||
|
||||
# *** RV64M Standard Extension (in addition to RV32M) ***
|
||||
mulw 0000001 ..... ..... 000 ..... 0111011 @r
|
||||
divw 0000001 ..... ..... 100 ..... 0111011 @r
|
||||
divuw 0000001 ..... ..... 101 ..... 0111011 @r
|
||||
remw 0000001 ..... ..... 110 ..... 0111011 @r
|
||||
remuw 0000001 ..... ..... 111 ..... 0111011 @r
|
||||
|
||||
# *** RV32A Standard Extension ***
|
||||
lr_w 00010 . . 00000 ..... 010 ..... 0101111 @atom_ld
|
||||
sc_w 00011 . . ..... ..... 010 ..... 0101111 @atom_st
|
||||
@ -167,6 +191,19 @@ amomax_w 10100 . . ..... ..... 010 ..... 0101111 @atom_st
|
||||
amominu_w 11000 . . ..... ..... 010 ..... 0101111 @atom_st
|
||||
amomaxu_w 11100 . . ..... ..... 010 ..... 0101111 @atom_st
|
||||
|
||||
# *** RV64A Standard Extension (in addition to RV32A) ***
|
||||
lr_d 00010 . . 00000 ..... 011 ..... 0101111 @atom_ld
|
||||
sc_d 00011 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoswap_d 00001 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoadd_d 00000 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoxor_d 00100 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoand_d 01100 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amoor_d 01000 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amomin_d 10000 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amomax_d 10100 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amominu_d 11000 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
amomaxu_d 11100 . . ..... ..... 011 ..... 0101111 @atom_st
|
||||
|
||||
# *** RV32F Standard Extension ***
|
||||
flw ............ ..... 010 ..... 0000111 @i
|
||||
fsw ....... ..... ..... 010 ..... 0100111 @s
|
||||
@ -195,6 +232,12 @@ fcvt_s_w 1101000 00000 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_s_wu 1101000 00001 ..... ... ..... 1010011 @r2_rm
|
||||
fmv_w_x 1111000 00000 ..... 000 ..... 1010011 @r2
|
||||
|
||||
# *** RV64F Standard Extension (in addition to RV32F) ***
|
||||
fcvt_l_s 1100000 00010 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_lu_s 1100000 00011 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_s_l 1101000 00010 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_s_lu 1101000 00011 ..... ... ..... 1010011 @r2_rm
|
||||
|
||||
# *** RV32D Standard Extension ***
|
||||
fld ............ ..... 011 ..... 0000111 @i
|
||||
fsd ....... ..... ..... 011 ..... 0100111 @s
|
||||
@ -223,6 +266,14 @@ fcvt_wu_d 1100001 00001 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_d_w 1101001 00000 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_d_wu 1101001 00001 ..... ... ..... 1010011 @r2_rm
|
||||
|
||||
# *** RV64D Standard Extension (in addition to RV32D) ***
|
||||
fcvt_l_d 1100001 00010 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_lu_d 1100001 00011 ..... ... ..... 1010011 @r2_rm
|
||||
fmv_x_d 1110001 00000 ..... 000 ..... 1010011 @r2
|
||||
fcvt_d_l 1101001 00010 ..... ... ..... 1010011 @r2_rm
|
||||
fcvt_d_lu 1101001 00011 ..... ... ..... 1010011 @r2_rm
|
||||
fmv_d_x 1111001 00000 ..... 000 ..... 1010011 @r2
|
||||
|
||||
# *** RV32H Base Instruction Set ***
|
||||
hlv_b 0110000 00000 ..... 100 ..... 1110011 @r2
|
||||
hlv_bu 0110000 00001 ..... 100 ..... 1110011 @r2
|
||||
@ -237,7 +288,10 @@ hsv_w 0110101 ..... ..... 100 00000 1110011 @r2_s
|
||||
hfence_gvma 0110001 ..... ..... 000 00000 1110011 @hfence_gvma
|
||||
hfence_vvma 0010001 ..... ..... 000 00000 1110011 @hfence_vvma
|
||||
|
||||
# *** RV32V Extension ***
|
||||
# *** RV64H Base Instruction Set ***
|
||||
hlv_wu 0110100 00001 ..... 100 ..... 1110011 @r2
|
||||
hlv_d 0110110 00000 ..... 100 ..... 1110011 @r2
|
||||
hsv_d 0110111 ..... ..... 100 00000 1110011 @r2_s
|
||||
|
||||
# *** Vector loads and stores are encoded within LOADFP/STORE-FP ***
|
||||
vlb_v ... 100 . 00000 ..... 000 ..... 0000111 @r2_nfvm
|
||||
@ -592,3 +646,14 @@ vcompress_vm 010111 - ..... ..... 010 ..... 1010111 @r
|
||||
|
||||
vsetvli 0 ........... ..... 111 ..... 1010111 @r2_zimm
|
||||
vsetvl 1000000 ..... ..... 111 ..... 1010111 @r
|
||||
|
||||
#*** Vector AMO operations (in addition to Zvamo) ***
|
||||
vamoswapd_v 00001 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
vamoaddd_v 00000 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
vamoxord_v 00100 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
vamoandd_v 01100 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
vamoord_v 01000 . . ..... ..... 111 ..... 0101111 @r_wdvm
|
||||
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
|
||||
|
@ -165,60 +165,68 @@ static bool trans_amomaxu_w(DisasContext *ctx, arg_amomaxu_w *a)
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TESL));
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
|
||||
static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_lr(ctx, a, MO_ALIGN | MO_TEQ);
|
||||
}
|
||||
|
||||
static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_sc(ctx, a, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amoswap_d(DisasContext *ctx, arg_amoswap_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amoadd_d(DisasContext *ctx, arg_amoadd_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amoxor_d(DisasContext *ctx, arg_amoxor_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amoand_d(DisasContext *ctx, arg_amoand_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amoor_d(DisasContext *ctx, arg_amoor_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amomin_d(DisasContext *ctx, arg_amomin_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amomax_d(DisasContext *ctx, arg_amomax_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amominu_d(DisasContext *ctx, arg_amominu_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
|
||||
static bool trans_amomaxu_d(DisasContext *ctx, arg_amomaxu_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TEQ));
|
||||
}
|
||||
#endif
|
||||
|
@ -358,10 +358,9 @@ static bool trans_fcvt_d_wu(DisasContext *ctx, arg_fcvt_d_wu *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
|
||||
static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
|
||||
@ -375,6 +374,7 @@ static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a)
|
||||
|
||||
static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
|
||||
@ -388,15 +388,21 @@ static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a)
|
||||
|
||||
static bool trans_fmv_x_d(DisasContext *ctx, arg_fmv_x_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
gen_set_gpr(a->rd, cpu_fpr[a->rs1]);
|
||||
return true;
|
||||
#else
|
||||
qemu_build_not_reached();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
|
||||
@ -412,6 +418,7 @@ static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a)
|
||||
|
||||
static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
|
||||
@ -427,9 +434,11 @@ static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a)
|
||||
|
||||
static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
TCGv t0 = tcg_temp_new();
|
||||
gen_get_gpr(t0, a->rs1);
|
||||
|
||||
@ -437,5 +446,7 @@ static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a)
|
||||
tcg_temp_free(t0);
|
||||
mark_fs_dirty(ctx);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
qemu_build_not_reached();
|
||||
#endif
|
||||
}
|
||||
|
@ -415,9 +415,9 @@ static bool trans_fmv_w_x(DisasContext *ctx, arg_fmv_w_x *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
static bool trans_fcvt_l_s(DisasContext *ctx, arg_fcvt_l_s *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
@ -431,6 +431,7 @@ static bool trans_fcvt_l_s(DisasContext *ctx, arg_fcvt_l_s *a)
|
||||
|
||||
static bool trans_fcvt_lu_s(DisasContext *ctx, arg_fcvt_lu_s *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
@ -444,6 +445,7 @@ static bool trans_fcvt_lu_s(DisasContext *ctx, arg_fcvt_lu_s *a)
|
||||
|
||||
static bool trans_fcvt_s_l(DisasContext *ctx, arg_fcvt_s_l *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
@ -460,6 +462,7 @@ static bool trans_fcvt_s_l(DisasContext *ctx, arg_fcvt_s_l *a)
|
||||
|
||||
static bool trans_fcvt_s_lu(DisasContext *ctx, arg_fcvt_s_lu *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
@ -473,4 +476,3 @@ static bool trans_fcvt_s_lu(DisasContext *ctx, arg_fcvt_s_lu *a)
|
||||
tcg_temp_free(t0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -203,10 +203,11 @@ static bool trans_hsv_w(DisasContext *ctx, arg_hsv_w *a)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVH);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
@ -228,7 +229,9 @@ static bool trans_hlv_wu(DisasContext *ctx, arg_hlv_wu *a)
|
||||
|
||||
static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVH);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
@ -250,7 +253,9 @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a)
|
||||
|
||||
static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVH);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv dat = tcg_temp_new();
|
||||
@ -269,7 +274,6 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool trans_hlvx_hu(DisasContext *ctx, arg_hlvx_hu *a)
|
||||
{
|
||||
|
@ -24,6 +24,12 @@ static bool trans_illegal(DisasContext *ctx, arg_empty *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return trans_illegal(ctx, a);
|
||||
}
|
||||
|
||||
static bool trans_lui(DisasContext *ctx, arg_lui *a)
|
||||
{
|
||||
if (a->rd != 0) {
|
||||
@ -204,22 +210,23 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a)
|
||||
return gen_store(ctx, a, MO_TESL);
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load(ctx, a, MO_TEUL);
|
||||
}
|
||||
|
||||
static bool trans_ld(DisasContext *ctx, arg_ld *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load(ctx, a, MO_TEQ);
|
||||
}
|
||||
|
||||
static bool trans_sd(DisasContext *ctx, arg_sd *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_store(ctx, a, MO_TEQ);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool trans_addi(DisasContext *ctx, arg_addi *a)
|
||||
{
|
||||
@ -361,14 +368,15 @@ static bool trans_and(DisasContext *ctx, arg_and *a)
|
||||
return gen_arith(ctx, a, &tcg_gen_and_tl);
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_arith_imm_tl(ctx, a, &gen_addw);
|
||||
}
|
||||
|
||||
static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
TCGv source1;
|
||||
source1 = tcg_temp_new();
|
||||
gen_get_gpr(source1, a->rs1);
|
||||
@ -383,6 +391,7 @@ static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
|
||||
|
||||
static bool trans_srliw(DisasContext *ctx, arg_srliw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
TCGv t = tcg_temp_new();
|
||||
gen_get_gpr(t, a->rs1);
|
||||
tcg_gen_extract_tl(t, t, a->shamt, 32 - a->shamt);
|
||||
@ -395,6 +404,7 @@ static bool trans_srliw(DisasContext *ctx, arg_srliw *a)
|
||||
|
||||
static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
TCGv t = tcg_temp_new();
|
||||
gen_get_gpr(t, a->rs1);
|
||||
tcg_gen_sextract_tl(t, t, a->shamt, 32 - a->shamt);
|
||||
@ -405,16 +415,19 @@ static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a)
|
||||
|
||||
static bool trans_addw(DisasContext *ctx, arg_addw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_arith(ctx, a, &gen_addw);
|
||||
}
|
||||
|
||||
static bool trans_subw(DisasContext *ctx, arg_subw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_arith(ctx, a, &gen_subw);
|
||||
}
|
||||
|
||||
static bool trans_sllw(DisasContext *ctx, arg_sllw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
TCGv source1 = tcg_temp_new();
|
||||
TCGv source2 = tcg_temp_new();
|
||||
|
||||
@ -433,6 +446,7 @@ static bool trans_sllw(DisasContext *ctx, arg_sllw *a)
|
||||
|
||||
static bool trans_srlw(DisasContext *ctx, arg_srlw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
TCGv source1 = tcg_temp_new();
|
||||
TCGv source2 = tcg_temp_new();
|
||||
|
||||
@ -453,6 +467,7 @@ static bool trans_srlw(DisasContext *ctx, arg_srlw *a)
|
||||
|
||||
static bool trans_sraw(DisasContext *ctx, arg_sraw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
TCGv source1 = tcg_temp_new();
|
||||
TCGv source2 = tcg_temp_new();
|
||||
|
||||
@ -473,7 +488,6 @@ static bool trans_sraw(DisasContext *ctx, arg_sraw *a)
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool trans_fence(DisasContext *ctx, arg_fence *a)
|
||||
{
|
||||
|
@ -87,34 +87,42 @@ static bool trans_remu(DisasContext *ctx, arg_remu *a)
|
||||
return gen_arith(ctx, a, &gen_remu);
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
static bool trans_mulw(DisasContext *ctx, arg_mulw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
|
||||
return gen_arith(ctx, a, &gen_mulw);
|
||||
}
|
||||
|
||||
static bool trans_divw(DisasContext *ctx, arg_divw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
|
||||
return gen_arith_div_w(ctx, a, &gen_div);
|
||||
}
|
||||
|
||||
static bool trans_divuw(DisasContext *ctx, arg_divuw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
|
||||
return gen_arith_div_uw(ctx, a, &gen_divu);
|
||||
}
|
||||
|
||||
static bool trans_remw(DisasContext *ctx, arg_remw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
|
||||
return gen_arith_div_w(ctx, a, &gen_rem);
|
||||
}
|
||||
|
||||
static bool trans_remuw(DisasContext *ctx, arg_remuw *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_EXT(ctx, RVM);
|
||||
|
||||
return gen_arith_div_uw(ctx, a, &gen_remu);
|
||||
}
|
||||
#endif
|
||||
|
@ -705,7 +705,6 @@ static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq)
|
||||
gen_helper_vamominuw_v_w,
|
||||
gen_helper_vamomaxuw_v_w
|
||||
};
|
||||
#ifdef TARGET_RISCV64
|
||||
static gen_helper_amo *const fnsd[18] = {
|
||||
gen_helper_vamoswapw_v_d,
|
||||
gen_helper_vamoaddw_v_d,
|
||||
@ -726,7 +725,6 @@ static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq)
|
||||
gen_helper_vamominud_v_d,
|
||||
gen_helper_vamomaxud_v_d
|
||||
};
|
||||
#endif
|
||||
|
||||
if (tb_cflags(s->base.tb) & CF_PARALLEL) {
|
||||
gen_helper_exit_atomic(cpu_env);
|
||||
@ -734,12 +732,12 @@ static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq)
|
||||
return true;
|
||||
} else {
|
||||
if (s->sew == 3) {
|
||||
#ifdef TARGET_RISCV64
|
||||
fn = fnsd[seq];
|
||||
#else
|
||||
/* Check done in amo_check(). */
|
||||
g_assert_not_reached();
|
||||
#endif
|
||||
if (!is_32bit(s)) {
|
||||
fn = fnsd[seq];
|
||||
} else {
|
||||
/* Check done in amo_check(). */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
} else {
|
||||
assert(seq < ARRAY_SIZE(fnsw));
|
||||
fn = fnsw[seq];
|
||||
@ -769,6 +767,11 @@ static bool amo_check(DisasContext *s, arg_rwdvm* a)
|
||||
((1 << s->sew) >= 4));
|
||||
}
|
||||
|
||||
static bool amo_check64(DisasContext *s, arg_rwdvm* a)
|
||||
{
|
||||
return !is_32bit(s) && amo_check(s, a);
|
||||
}
|
||||
|
||||
GEN_VEXT_TRANS(vamoswapw_v, 0, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamoaddw_v, 1, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamoxorw_v, 2, rwdvm, amo_op, amo_check)
|
||||
@ -778,17 +781,15 @@ GEN_VEXT_TRANS(vamominw_v, 5, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamomaxw_v, 6, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamominuw_v, 7, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamomaxuw_v, 8, rwdvm, amo_op, amo_check)
|
||||
#ifdef TARGET_RISCV64
|
||||
GEN_VEXT_TRANS(vamoswapd_v, 9, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamoaddd_v, 10, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamoxord_v, 11, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamoandd_v, 12, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamoord_v, 13, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamomind_v, 14, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamomaxd_v, 15, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamominud_v, 16, rwdvm, amo_op, amo_check)
|
||||
GEN_VEXT_TRANS(vamomaxud_v, 17, rwdvm, amo_op, amo_check)
|
||||
#endif
|
||||
GEN_VEXT_TRANS(vamoswapd_v, 9, rwdvm, amo_op, amo_check64)
|
||||
GEN_VEXT_TRANS(vamoaddd_v, 10, rwdvm, amo_op, amo_check64)
|
||||
GEN_VEXT_TRANS(vamoxord_v, 11, rwdvm, amo_op, amo_check64)
|
||||
GEN_VEXT_TRANS(vamoandd_v, 12, rwdvm, amo_op, amo_check64)
|
||||
GEN_VEXT_TRANS(vamoord_v, 13, rwdvm, amo_op, amo_check64)
|
||||
GEN_VEXT_TRANS(vamomind_v, 14, rwdvm, amo_op, amo_check64)
|
||||
GEN_VEXT_TRANS(vamomaxd_v, 15, rwdvm, amo_op, amo_check64)
|
||||
GEN_VEXT_TRANS(vamominud_v, 16, rwdvm, amo_op, amo_check64)
|
||||
GEN_VEXT_TRANS(vamomaxud_v, 17, rwdvm, amo_op, amo_check64)
|
||||
|
||||
/*
|
||||
*** Vector Integer Arithmetic Instructions
|
||||
|
@ -140,8 +140,8 @@ static const VMStateDescription vmstate_hyper = {
|
||||
|
||||
const VMStateDescription vmstate_riscv_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
|
||||
VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),
|
||||
@ -165,10 +165,8 @@ const VMStateDescription vmstate_riscv_cpu = {
|
||||
VMSTATE_UINT32(env.miclaim, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.mie, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.mideleg, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.sptbr, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.satp, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.sbadaddr, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.mbadaddr, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.stval, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.medeleg, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.stvec, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.sepc, RISCVCPU),
|
||||
|
@ -1,18 +1,13 @@
|
||||
# FIXME extra_args should accept files()
|
||||
dir = meson.current_source_dir()
|
||||
gen32 = [
|
||||
decodetree.process('insn16.decode', extra_args: [dir / 'insn16-32.decode', '--static-decode=decode_insn16', '--insnwidth=16']),
|
||||
|
||||
gen = [
|
||||
decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']),
|
||||
decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'),
|
||||
]
|
||||
|
||||
gen64 = [
|
||||
decodetree.process('insn16.decode', extra_args: [dir / 'insn16-64.decode', '--static-decode=decode_insn16', '--insnwidth=16']),
|
||||
decodetree.process('insn32.decode', extra_args: [dir / 'insn32-64.decode', '--static-decode=decode_insn32']),
|
||||
]
|
||||
|
||||
riscv_ss = ss.source_set()
|
||||
riscv_ss.add(when: 'TARGET_RISCV32', if_true: gen32)
|
||||
riscv_ss.add(when: 'TARGET_RISCV64', if_true: gen64)
|
||||
riscv_ss.add(gen)
|
||||
riscv_ss.add(files(
|
||||
'cpu.c',
|
||||
'cpu_helper.c',
|
||||
|
@ -150,9 +150,14 @@ static void mem_info_svxx(Monitor *mon, CPUArchState *env)
|
||||
target_ulong last_size;
|
||||
int last_attr;
|
||||
|
||||
base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
|
||||
if (riscv_cpu_is_32bit(env)) {
|
||||
base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT;
|
||||
vm = get_field(env->satp, SATP32_MODE);
|
||||
} else {
|
||||
base = (hwaddr)get_field(env->satp, SATP64_PPN) << PGSHIFT;
|
||||
vm = get_field(env->satp, SATP64_MODE);
|
||||
}
|
||||
|
||||
vm = get_field(env->satp, SATP_MODE);
|
||||
switch (vm) {
|
||||
case VM_1_10_SV32:
|
||||
levels = 2;
|
||||
@ -215,9 +220,16 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(env->satp & SATP_MODE)) {
|
||||
monitor_printf(mon, "No translation or protection\n");
|
||||
return;
|
||||
if (riscv_cpu_is_32bit(env)) {
|
||||
if (!(env->satp & SATP32_MODE)) {
|
||||
monitor_printf(mon, "No translation or protection\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!(env->satp & SATP64_MODE)) {
|
||||
monitor_printf(mon, "No translation or protection\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mem_info_svxx(mon, env);
|
||||
|
@ -41,10 +41,10 @@ target_ulong helper_csrrw(CPURISCVState *env, target_ulong src,
|
||||
target_ulong csr)
|
||||
{
|
||||
target_ulong val = 0;
|
||||
int ret = riscv_csrrw(env, csr, &val, src, -1);
|
||||
RISCVException ret = riscv_csrrw(env, csr, &val, src, -1);
|
||||
|
||||
if (ret < 0) {
|
||||
riscv_raise_exception(env, -ret, GETPC());
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
riscv_raise_exception(env, ret, GETPC());
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@ -53,10 +53,10 @@ target_ulong helper_csrrs(CPURISCVState *env, target_ulong src,
|
||||
target_ulong csr, target_ulong rs1_pass)
|
||||
{
|
||||
target_ulong val = 0;
|
||||
int ret = riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0);
|
||||
RISCVException ret = riscv_csrrw(env, csr, &val, -1, rs1_pass ? src : 0);
|
||||
|
||||
if (ret < 0) {
|
||||
riscv_raise_exception(env, -ret, GETPC());
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
riscv_raise_exception(env, ret, GETPC());
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@ -65,10 +65,10 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
|
||||
target_ulong csr, target_ulong rs1_pass)
|
||||
{
|
||||
target_ulong val = 0;
|
||||
int ret = riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0);
|
||||
RISCVException ret = riscv_csrrw(env, csr, &val, 0, rs1_pass ? src : 0);
|
||||
|
||||
if (ret < 0) {
|
||||
riscv_raise_exception(env, -ret, GETPC());
|
||||
if (ret != RISCV_EXCP_NONE) {
|
||||
riscv_raise_exception(env, ret, GETPC());
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
@ -19,10 +19,6 @@
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PMP (Physical Memory Protection) is as-of-yet unused and needs testing.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qapi/error.h"
|
||||
@ -59,16 +55,6 @@ static inline int pmp_is_locked(CPURISCVState *env, uint32_t pmp_index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In TOR mode, need to check the lock bit of the next pmp
|
||||
* (if there is a next)
|
||||
*/
|
||||
const uint8_t a_field =
|
||||
pmp_get_a_field(env->pmp_state.pmp[pmp_index + 1].cfg_reg);
|
||||
if ((env->pmp_state.pmp[pmp_index + 1u].cfg_reg & PMP_LOCK) &&
|
||||
(PMP_AMATCH_TOR == a_field)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -100,11 +86,42 @@ static inline uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t pmp_index)
|
||||
static void pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
|
||||
{
|
||||
if (pmp_index < MAX_RISCV_PMPS) {
|
||||
if (!pmp_is_locked(env, pmp_index)) {
|
||||
bool locked = true;
|
||||
|
||||
if (riscv_feature(env, RISCV_FEATURE_EPMP)) {
|
||||
/* mseccfg.RLB is set */
|
||||
if (MSECCFG_RLB_ISSET(env)) {
|
||||
locked = false;
|
||||
}
|
||||
|
||||
/* mseccfg.MML is not set */
|
||||
if (!MSECCFG_MML_ISSET(env) && !pmp_is_locked(env, pmp_index)) {
|
||||
locked = false;
|
||||
}
|
||||
|
||||
/* mseccfg.MML is set */
|
||||
if (MSECCFG_MML_ISSET(env)) {
|
||||
/* not adding execute bit */
|
||||
if ((val & PMP_LOCK) != 0 && (val & PMP_EXEC) != PMP_EXEC) {
|
||||
locked = false;
|
||||
}
|
||||
/* shared region and not adding X bit */
|
||||
if ((val & PMP_LOCK) != PMP_LOCK &&
|
||||
(val & 0x7) != (PMP_WRITE | PMP_EXEC)) {
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!pmp_is_locked(env, pmp_index)) {
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "ignoring pmpcfg write - locked\n");
|
||||
} else {
|
||||
env->pmp_state.pmp[pmp_index].cfg_reg = val;
|
||||
pmp_update_rule(env, pmp_index);
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "ignoring pmpcfg write - locked\n");
|
||||
}
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
@ -227,6 +244,32 @@ static bool pmp_hart_has_privs_default(CPURISCVState *env, target_ulong addr,
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (riscv_feature(env, RISCV_FEATURE_EPMP)) {
|
||||
if (MSECCFG_MMWP_ISSET(env)) {
|
||||
/*
|
||||
* The Machine Mode Whitelist Policy (mseccfg.MMWP) is set
|
||||
* so we default to deny all, even for M-mode.
|
||||
*/
|
||||
*allowed_privs = 0;
|
||||
return false;
|
||||
} else if (MSECCFG_MML_ISSET(env)) {
|
||||
/*
|
||||
* The Machine Mode Lockdown (mseccfg.MML) bit is set
|
||||
* so we can only execute code in M-mode with an applicable
|
||||
* rule. Other modes are disabled.
|
||||
*/
|
||||
if (mode == PRV_M && !(privs & PMP_EXEC)) {
|
||||
ret = true;
|
||||
*allowed_privs = PMP_READ | PMP_WRITE;
|
||||
} else {
|
||||
ret = false;
|
||||
*allowed_privs = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!riscv_feature(env, RISCV_FEATURE_PMP)) || (mode == PRV_M)) {
|
||||
/*
|
||||
* Privileged spec v1.10 states if HW doesn't implement any PMP entry
|
||||
@ -304,13 +347,94 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
|
||||
pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg);
|
||||
|
||||
/*
|
||||
* If the PMP entry is not off and the address is in range, do the priv
|
||||
* check
|
||||
* Convert the PMP permissions to match the truth table in the
|
||||
* ePMP spec.
|
||||
*/
|
||||
const uint8_t epmp_operation =
|
||||
((env->pmp_state.pmp[i].cfg_reg & PMP_LOCK) >> 4) |
|
||||
((env->pmp_state.pmp[i].cfg_reg & PMP_READ) << 2) |
|
||||
(env->pmp_state.pmp[i].cfg_reg & PMP_WRITE) |
|
||||
((env->pmp_state.pmp[i].cfg_reg & PMP_EXEC) >> 2);
|
||||
|
||||
if (((s + e) == 2) && (PMP_AMATCH_OFF != a_field)) {
|
||||
*allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
|
||||
if ((mode != PRV_M) || pmp_is_locked(env, i)) {
|
||||
*allowed_privs &= env->pmp_state.pmp[i].cfg_reg;
|
||||
/*
|
||||
* If the PMP entry is not off and the address is in range,
|
||||
* do the priv check
|
||||
*/
|
||||
if (!MSECCFG_MML_ISSET(env)) {
|
||||
/*
|
||||
* If mseccfg.MML Bit is not set, do pmp priv check
|
||||
* This will always apply to regular PMP.
|
||||
*/
|
||||
*allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
|
||||
if ((mode != PRV_M) || pmp_is_locked(env, i)) {
|
||||
*allowed_privs &= env->pmp_state.pmp[i].cfg_reg;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If mseccfg.MML Bit set, do the enhanced pmp priv check
|
||||
*/
|
||||
if (mode == PRV_M) {
|
||||
switch (epmp_operation) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
*allowed_privs = 0;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 14:
|
||||
*allowed_privs = PMP_READ | PMP_WRITE;
|
||||
break;
|
||||
case 9:
|
||||
case 10:
|
||||
*allowed_privs = PMP_EXEC;
|
||||
break;
|
||||
case 11:
|
||||
case 13:
|
||||
*allowed_privs = PMP_READ | PMP_EXEC;
|
||||
break;
|
||||
case 12:
|
||||
case 15:
|
||||
*allowed_privs = PMP_READ;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (epmp_operation) {
|
||||
case 0:
|
||||
case 8:
|
||||
case 9:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
*allowed_privs = 0;
|
||||
break;
|
||||
case 1:
|
||||
case 10:
|
||||
case 11:
|
||||
*allowed_privs = PMP_EXEC;
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
case 15:
|
||||
*allowed_privs = PMP_READ;
|
||||
break;
|
||||
case 3:
|
||||
case 6:
|
||||
*allowed_privs = PMP_READ | PMP_WRITE;
|
||||
break;
|
||||
case 5:
|
||||
*allowed_privs = PMP_READ | PMP_EXEC;
|
||||
break;
|
||||
case 7:
|
||||
*allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = ((privs & *allowed_privs) == privs);
|
||||
@ -380,7 +504,23 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
|
||||
target_ulong val)
|
||||
{
|
||||
trace_pmpaddr_csr_write(env->mhartid, addr_index, val);
|
||||
|
||||
if (addr_index < MAX_RISCV_PMPS) {
|
||||
/*
|
||||
* In TOR mode, need to check the lock bit of the next pmp
|
||||
* (if there is a next).
|
||||
*/
|
||||
if (addr_index + 1 < MAX_RISCV_PMPS) {
|
||||
uint8_t pmp_cfg = env->pmp_state.pmp[addr_index + 1].cfg_reg;
|
||||
|
||||
if (pmp_cfg & PMP_LOCK &&
|
||||
PMP_AMATCH_TOR == pmp_get_a_field(pmp_cfg)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"ignoring pmpaddr write - pmpcfg + 1 locked\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pmp_is_locked(env, addr_index)) {
|
||||
env->pmp_state.pmp[addr_index].addr_reg = val;
|
||||
pmp_update_rule(env, addr_index);
|
||||
@ -413,6 +553,40 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index)
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a write to a mseccfg CSR
|
||||
*/
|
||||
void mseccfg_csr_write(CPURISCVState *env, target_ulong val)
|
||||
{
|
||||
int i;
|
||||
|
||||
trace_mseccfg_csr_write(env->mhartid, val);
|
||||
|
||||
/* RLB cannot be enabled if it's already 0 and if any regions are locked */
|
||||
if (!MSECCFG_RLB_ISSET(env)) {
|
||||
for (i = 0; i < MAX_RISCV_PMPS; i++) {
|
||||
if (pmp_is_locked(env, i)) {
|
||||
val &= ~MSECCFG_RLB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sticky bits */
|
||||
val |= (env->mseccfg & (MSECCFG_MMWP | MSECCFG_MML));
|
||||
|
||||
env->mseccfg = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a read from a mseccfg CSR
|
||||
*/
|
||||
target_ulong mseccfg_csr_read(CPURISCVState *env)
|
||||
{
|
||||
trace_mseccfg_csr_read(env->mhartid, env->mseccfg);
|
||||
return env->mseccfg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the TLB size if the start address or the end address of
|
||||
* PMP entry is presented in thie TLB page.
|
||||
|
@ -36,6 +36,12 @@ typedef enum {
|
||||
PMP_AMATCH_NAPOT /* Naturally aligned power-of-two region */
|
||||
} pmp_am_t;
|
||||
|
||||
typedef enum {
|
||||
MSECCFG_MML = 1 << 0,
|
||||
MSECCFG_MMWP = 1 << 1,
|
||||
MSECCFG_RLB = 1 << 2
|
||||
} mseccfg_field_t;
|
||||
|
||||
typedef struct {
|
||||
target_ulong addr_reg;
|
||||
uint8_t cfg_reg;
|
||||
@ -55,6 +61,10 @@ typedef struct {
|
||||
void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index,
|
||||
target_ulong val);
|
||||
target_ulong pmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index);
|
||||
|
||||
void mseccfg_csr_write(CPURISCVState *env, target_ulong val);
|
||||
target_ulong mseccfg_csr_read(CPURISCVState *env);
|
||||
|
||||
void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
|
||||
target_ulong val);
|
||||
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index);
|
||||
@ -68,4 +78,8 @@ void pmp_update_rule_nums(CPURISCVState *env);
|
||||
uint32_t pmp_get_num_rules(CPURISCVState *env);
|
||||
int pmp_priv_to_page_prot(pmp_priv_t pmp_priv);
|
||||
|
||||
#define MSECCFG_MML_ISSET(env) get_field(env->mseccfg, MSECCFG_MML)
|
||||
#define MSECCFG_MMWP_ISSET(env) get_field(env->mseccfg, MSECCFG_MMWP)
|
||||
#define MSECCFG_RLB_ISSET(env) get_field(env->mseccfg, MSECCFG_RLB)
|
||||
|
||||
#endif
|
||||
|
@ -6,3 +6,6 @@ pmpcfg_csr_read(uint64_t mhartid, uint32_t reg_index, uint64_t val) "hart %" PRI
|
||||
pmpcfg_csr_write(uint64_t mhartid, uint32_t reg_index, uint64_t val) "hart %" PRIu64 ": write reg%" PRIu32", val: 0x%" PRIx64
|
||||
pmpaddr_csr_read(uint64_t mhartid, uint32_t addr_index, uint64_t val) "hart %" PRIu64 ": read addr%" PRIu32", val: 0x%" PRIx64
|
||||
pmpaddr_csr_write(uint64_t mhartid, uint32_t addr_index, uint64_t val) "hart %" PRIu64 ": write addr%" PRIu32", val: 0x%" PRIx64
|
||||
|
||||
mseccfg_csr_read(uint64_t mhartid, uint64_t val) "hart %" PRIu64 ": read mseccfg, val: 0x%" PRIx64
|
||||
mseccfg_csr_write(uint64_t mhartid, uint64_t val) "hart %" PRIu64 ": write mseccfg, val: 0x%" PRIx64
|
||||
|
@ -67,17 +67,22 @@ typedef struct DisasContext {
|
||||
CPUState *cs;
|
||||
} DisasContext;
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
#define CASE_OP_32_64(X) case X: case glue(X, W)
|
||||
#else
|
||||
#define CASE_OP_32_64(X) case X
|
||||
#endif
|
||||
|
||||
static inline bool has_ext(DisasContext *ctx, uint32_t ext)
|
||||
{
|
||||
return ctx->misa & ext;
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV32
|
||||
# define is_32bit(ctx) true
|
||||
#elif defined(CONFIG_USER_ONLY)
|
||||
# define is_32bit(ctx) false
|
||||
#else
|
||||
static inline bool is_32bit(DisasContext *ctx)
|
||||
{
|
||||
return (ctx->misa & RV32) == RV32;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RISC-V requires NaN-boxing of narrower width floating point values.
|
||||
* This applies when a 32-bit value is assigned to a 64-bit FP register.
|
||||
@ -116,7 +121,7 @@ static void generate_exception(DisasContext *ctx, int excp)
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
static void generate_exception_mbadaddr(DisasContext *ctx, int excp)
|
||||
static void generate_exception_mtval(DisasContext *ctx, int excp)
|
||||
{
|
||||
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
|
||||
tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
|
||||
@ -160,7 +165,7 @@ static void gen_exception_illegal(DisasContext *ctx)
|
||||
|
||||
static void gen_exception_inst_addr_mis(DisasContext *ctx)
|
||||
{
|
||||
generate_exception_mbadaddr(ctx, RISCV_EXCP_INST_ADDR_MIS);
|
||||
generate_exception_mtval(ctx, RISCV_EXCP_INST_ADDR_MIS);
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
||||
@ -369,6 +374,8 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
|
||||
static void mark_fs_dirty(DisasContext *ctx)
|
||||
{
|
||||
TCGv tmp;
|
||||
target_ulong sd;
|
||||
|
||||
if (ctx->mstatus_fs == MSTATUS_FS) {
|
||||
return;
|
||||
}
|
||||
@ -376,13 +383,15 @@ static void mark_fs_dirty(DisasContext *ctx)
|
||||
ctx->mstatus_fs = MSTATUS_FS;
|
||||
|
||||
tmp = tcg_temp_new();
|
||||
sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
|
||||
|
||||
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
|
||||
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | MSTATUS_SD);
|
||||
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
|
||||
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
|
||||
|
||||
if (ctx->virt_enabled) {
|
||||
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
|
||||
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | MSTATUS_SD);
|
||||
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
|
||||
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
|
||||
}
|
||||
tcg_temp_free(tmp);
|
||||
@ -426,6 +435,12 @@ EX_SH(12)
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define REQUIRE_64BIT(ctx) do { \
|
||||
if (is_32bit(ctx)) { \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int ex_rvc_register(DisasContext *ctx, int reg)
|
||||
{
|
||||
return 8 + reg;
|
||||
@ -473,7 +488,6 @@ static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
static void gen_addw(TCGv ret, TCGv arg1, TCGv arg2)
|
||||
{
|
||||
tcg_gen_add_tl(ret, arg1, arg2);
|
||||
@ -534,8 +548,6 @@ static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a,
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool gen_arith(DisasContext *ctx, arg_r *a,
|
||||
void(*func)(TCGv, TCGv, TCGv))
|
||||
{
|
||||
|
@ -751,7 +751,6 @@ GEN_VEXT_AMO_NOATOMIC_OP(vamominw_v_w, 32, 32, H4, DO_MIN, l)
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamomaxw_v_w, 32, 32, H4, DO_MAX, l)
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamominuw_v_w, 32, 32, H4, DO_MINU, l)
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamomaxuw_v_w, 32, 32, H4, DO_MAXU, l)
|
||||
#ifdef TARGET_RISCV64
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamoswapw_v_d, 64, 32, H8, DO_SWAP, l)
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamoswapd_v_d, 64, 64, H8, DO_SWAP, q)
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamoaddw_v_d, 64, 32, H8, DO_ADD, l)
|
||||
@ -770,7 +769,6 @@ GEN_VEXT_AMO_NOATOMIC_OP(vamominuw_v_d, 64, 32, H8, DO_MINU, l)
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamominud_v_d, 64, 64, H8, DO_MINU, q)
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamomaxuw_v_d, 64, 32, H8, DO_MAXU, l)
|
||||
GEN_VEXT_AMO_NOATOMIC_OP(vamomaxud_v_d, 64, 64, H8, DO_MAXU, q)
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
vext_amo_noatomic(void *vs3, void *v0, target_ulong base,
|
||||
@ -814,7 +812,6 @@ void HELPER(NAME)(void *vs3, void *v0, target_ulong base, \
|
||||
GETPC()); \
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV64
|
||||
GEN_VEXT_AMO(vamoswapw_v_d, int32_t, int64_t, idx_d, clearq)
|
||||
GEN_VEXT_AMO(vamoswapd_v_d, int64_t, int64_t, idx_d, clearq)
|
||||
GEN_VEXT_AMO(vamoaddw_v_d, int32_t, int64_t, idx_d, clearq)
|
||||
@ -833,7 +830,6 @@ GEN_VEXT_AMO(vamominuw_v_d, uint32_t, uint64_t, idx_d, clearq)
|
||||
GEN_VEXT_AMO(vamominud_v_d, uint64_t, uint64_t, idx_d, clearq)
|
||||
GEN_VEXT_AMO(vamomaxuw_v_d, uint32_t, uint64_t, idx_d, clearq)
|
||||
GEN_VEXT_AMO(vamomaxud_v_d, uint64_t, uint64_t, idx_d, clearq)
|
||||
#endif
|
||||
GEN_VEXT_AMO(vamoswapw_v_w, int32_t, int32_t, idx_w, clearl)
|
||||
GEN_VEXT_AMO(vamoaddw_v_w, int32_t, int32_t, idx_w, clearl)
|
||||
GEN_VEXT_AMO(vamoxorw_v_w, int32_t, int32_t, idx_w, clearl)
|
||||
@ -2451,7 +2447,7 @@ static inline int8_t ssub8(CPURISCVState *env, int vxrm, int8_t a, int8_t b)
|
||||
{
|
||||
int8_t res = a - b;
|
||||
if ((res ^ a) & (a ^ b) & INT8_MIN) {
|
||||
res = a > 0 ? INT8_MAX : INT8_MIN;
|
||||
res = a >= 0 ? INT8_MAX : INT8_MIN;
|
||||
env->vxsat = 0x1;
|
||||
}
|
||||
return res;
|
||||
@ -2461,7 +2457,7 @@ static inline int16_t ssub16(CPURISCVState *env, int vxrm, int16_t a, int16_t b)
|
||||
{
|
||||
int16_t res = a - b;
|
||||
if ((res ^ a) & (a ^ b) & INT16_MIN) {
|
||||
res = a > 0 ? INT16_MAX : INT16_MIN;
|
||||
res = a >= 0 ? INT16_MAX : INT16_MIN;
|
||||
env->vxsat = 0x1;
|
||||
}
|
||||
return res;
|
||||
@ -2471,7 +2467,7 @@ static inline int32_t ssub32(CPURISCVState *env, int vxrm, int32_t a, int32_t b)
|
||||
{
|
||||
int32_t res = a - b;
|
||||
if ((res ^ a) & (a ^ b) & INT32_MIN) {
|
||||
res = a > 0 ? INT32_MAX : INT32_MIN;
|
||||
res = a >= 0 ? INT32_MAX : INT32_MIN;
|
||||
env->vxsat = 0x1;
|
||||
}
|
||||
return res;
|
||||
@ -2481,7 +2477,7 @@ static inline int64_t ssub64(CPURISCVState *env, int vxrm, int64_t a, int64_t b)
|
||||
{
|
||||
int64_t res = a - b;
|
||||
if ((res ^ a) & (a ^ b) & INT64_MIN) {
|
||||
res = a > 0 ? INT64_MAX : INT64_MIN;
|
||||
res = a >= 0 ? INT64_MAX : INT64_MIN;
|
||||
env->vxsat = 0x1;
|
||||
}
|
||||
return res;
|
||||
@ -4796,7 +4792,8 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
|
||||
uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \
|
||||
uint32_t vm = vext_vm(desc); \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t index, i; \
|
||||
uint64_t index; \
|
||||
uint32_t i; \
|
||||
\
|
||||
for (i = 0; i < vl; i++) { \
|
||||
if (!vm && !vext_elem_mask(v0, mlen, i)) { \
|
||||
@ -4826,7 +4823,8 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
|
||||
uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \
|
||||
uint32_t vm = vext_vm(desc); \
|
||||
uint32_t vl = env->vl; \
|
||||
uint32_t index = s1, i; \
|
||||
uint64_t index = s1; \
|
||||
uint32_t i; \
|
||||
\
|
||||
for (i = 0; i < vl; i++) { \
|
||||
if (!vm && !vext_elem_mask(v0, mlen, i)) { \
|
||||
|
Loading…
Reference in New Issue
Block a user