Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20220303' into staging

Fifth RISC-V PR for QEMU 7.0

 * Fixup checks for ext_zb[abcs]
 * Add AIA support for virt machine
 * Increase maximum number of CPUs in virt machine
 * Fixup OpenTitan SPI address
 * Add support for zfinx, zdinx and zhinx{min} extensions

# gpg: Signature made Thu 03 Mar 2022 05:26:55 GMT
# 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-20220303:
  target/riscv: expose zfinx, zdinx, zhinx{min} properties
  target/riscv: add support for zhinx/zhinxmin
  target/riscv: add support for zdinx
  target/riscv: add support for zfinx
  target/riscv: hardwire mstatus.FS to zero when enable zfinx
  target/riscv: add cfg properties for zfinx, zdinx and zhinx{min}
  hw: riscv: opentitan: fixup SPI addresses
  hw/riscv: virt: Increase maximum number of allowed CPUs
  docs/system: riscv: Document AIA options for virt machine
  hw/riscv: virt: Add optional AIA IMSIC support to virt machine
  hw/intc: Add RISC-V AIA IMSIC device emulation
  hw/riscv: virt: Add optional AIA APLIC support to virt machine
  target/riscv: fix inverted checks for ext_zb[abcs]

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2022-03-03 19:59:38 +00:00
22 changed files with 2145 additions and 500 deletions
+16
View File
@@ -63,6 +63,22 @@ The following machine-specific options are supported:
When this option is "on", ACLINT devices will be emulated instead of
SiFive CLINT. When not specified, this option is assumed to be "off".
- aia=[none|aplic|aplic-imsic]
This option allows selecting interrupt controller defined by the AIA
(advanced interrupt architecture) specification. The "aia=aplic" selects
APLIC (advanced platform level interrupt controller) to handle wired
interrupts whereas the "aia=aplic-imsic" selects APLIC and IMSIC (incoming
message signaled interrupt controller) to handle both wired interrupts and
MSIs. When not specified, this option is assumed to be "none" which selects
SiFive PLIC to handle wired interrupts.
- aia-guests=nnn
The number of per-HART VS-level AIA IMSIC pages to be emulated for a guest
having AIA IMSIC (i.e. "aia=aplic-imsic" selected). When not specified,
the default number of per-HART VS-level AIA IMSIC pages is 0.
Running Linux kernel
--------------------
+3
View File
@@ -73,6 +73,9 @@ config RISCV_ACLINT
config RISCV_APLIC
bool
config RISCV_IMSIC
bool
config SIFIVE_PLIC
bool
+1
View File
@@ -51,6 +51,7 @@ specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: files('s390_flic_kvm.c'))
specific_ss.add(when: 'CONFIG_SH_INTC', if_true: files('sh_intc.c'))
specific_ss.add(when: 'CONFIG_RISCV_ACLINT', if_true: files('riscv_aclint.c'))
specific_ss.add(when: 'CONFIG_RISCV_APLIC', if_true: files('riscv_aplic.c'))
specific_ss.add(when: 'CONFIG_RISCV_IMSIC', if_true: files('riscv_imsic.c'))
specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'))
specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c', 'xive2.c'))
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'],
+448
View File
@@ -0,0 +1,448 @@
/*
* RISC-V IMSIC (Incoming Message Signaled Interrupt Controller)
*
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
*
* 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 "qapi/error.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qemu/error-report.h"
#include "qemu/bswap.h"
#include "exec/address-spaces.h"
#include "hw/sysbus.h"
#include "hw/pci/msi.h"
#include "hw/boards.h"
#include "hw/qdev-properties.h"
#include "hw/intc/riscv_imsic.h"
#include "hw/irq.h"
#include "target/riscv/cpu.h"
#include "target/riscv/cpu_bits.h"
#include "sysemu/sysemu.h"
#include "migration/vmstate.h"
#define IMSIC_MMIO_PAGE_LE 0x00
#define IMSIC_MMIO_PAGE_BE 0x04
#define IMSIC_MIN_ID ((IMSIC_EIPx_BITS * 2) - 1)
#define IMSIC_MAX_ID (IMSIC_TOPEI_IID_MASK)
#define IMSIC_EISTATE_PENDING (1U << 0)
#define IMSIC_EISTATE_ENABLED (1U << 1)
#define IMSIC_EISTATE_ENPEND (IMSIC_EISTATE_ENABLED | \
IMSIC_EISTATE_PENDING)
static uint32_t riscv_imsic_topei(RISCVIMSICState *imsic, uint32_t page)
{
uint32_t i, max_irq, base;
base = page * imsic->num_irqs;
max_irq = (imsic->eithreshold[page] &&
(imsic->eithreshold[page] <= imsic->num_irqs)) ?
imsic->eithreshold[page] : imsic->num_irqs;
for (i = 1; i < max_irq; i++) {
if ((imsic->eistate[base + i] & IMSIC_EISTATE_ENPEND) ==
IMSIC_EISTATE_ENPEND) {
return (i << IMSIC_TOPEI_IID_SHIFT) | i;
}
}
return 0;
}
static void riscv_imsic_update(RISCVIMSICState *imsic, uint32_t page)
{
if (imsic->eidelivery[page] && riscv_imsic_topei(imsic, page)) {
qemu_irq_raise(imsic->external_irqs[page]);
} else {
qemu_irq_lower(imsic->external_irqs[page]);
}
}
static int riscv_imsic_eidelivery_rmw(RISCVIMSICState *imsic, uint32_t page,
target_ulong *val,
target_ulong new_val,
target_ulong wr_mask)
{
target_ulong old_val = imsic->eidelivery[page];
if (val) {
*val = old_val;
}
wr_mask &= 0x1;
imsic->eidelivery[page] = (old_val & ~wr_mask) | (new_val & wr_mask);
riscv_imsic_update(imsic, page);
return 0;
}
static int riscv_imsic_eithreshold_rmw(RISCVIMSICState *imsic, uint32_t page,
target_ulong *val,
target_ulong new_val,
target_ulong wr_mask)
{
target_ulong old_val = imsic->eithreshold[page];
if (val) {
*val = old_val;
}
wr_mask &= IMSIC_MAX_ID;
imsic->eithreshold[page] = (old_val & ~wr_mask) | (new_val & wr_mask);
riscv_imsic_update(imsic, page);
return 0;
}
static int riscv_imsic_topei_rmw(RISCVIMSICState *imsic, uint32_t page,
target_ulong *val, target_ulong new_val,
target_ulong wr_mask)
{
uint32_t base, topei = riscv_imsic_topei(imsic, page);
/* Read pending and enabled interrupt with highest priority */
if (val) {
*val = topei;
}
/* Writes ignore value and clear top pending interrupt */
if (topei && wr_mask) {
topei >>= IMSIC_TOPEI_IID_SHIFT;
base = page * imsic->num_irqs;
if (topei) {
imsic->eistate[base + topei] &= ~IMSIC_EISTATE_PENDING;
}
riscv_imsic_update(imsic, page);
}
return 0;
}
static int riscv_imsic_eix_rmw(RISCVIMSICState *imsic,
uint32_t xlen, uint32_t page,
uint32_t num, bool pend, target_ulong *val,
target_ulong new_val, target_ulong wr_mask)
{
uint32_t i, base;
target_ulong mask;
uint32_t state = (pend) ? IMSIC_EISTATE_PENDING : IMSIC_EISTATE_ENABLED;
if (xlen != 32) {
if (num & 0x1) {
return -EINVAL;
}
num >>= 1;
}
if (num >= (imsic->num_irqs / xlen)) {
return -EINVAL;
}
base = (page * imsic->num_irqs) + (num * xlen);
if (val) {
*val = 0;
for (i = 0; i < xlen; i++) {
mask = (target_ulong)1 << i;
*val |= (imsic->eistate[base + i] & state) ? mask : 0;
}
}
for (i = 0; i < xlen; i++) {
/* Bit0 of eip0 and eie0 are read-only zero */
if (!num && !i) {
continue;
}
mask = (target_ulong)1 << i;
if (wr_mask & mask) {
if (new_val & mask) {
imsic->eistate[base + i] |= state;
} else {
imsic->eistate[base + i] &= ~state;
}
}
}
riscv_imsic_update(imsic, page);
return 0;
}
static int riscv_imsic_rmw(void *arg, target_ulong reg, target_ulong *val,
target_ulong new_val, target_ulong wr_mask)
{
RISCVIMSICState *imsic = arg;
uint32_t isel, priv, virt, vgein, xlen, page;
priv = AIA_IREG_PRIV(reg);
virt = AIA_IREG_VIRT(reg);
isel = AIA_IREG_ISEL(reg);
vgein = AIA_IREG_VGEIN(reg);
xlen = AIA_IREG_XLEN(reg);
if (imsic->mmode) {
if (priv == PRV_M && !virt) {
page = 0;
} else {
goto err;
}
} else {
if (priv == PRV_S) {
if (virt) {
if (vgein && vgein < imsic->num_pages) {
page = vgein;
} else {
goto err;
}
} else {
page = 0;
}
} else {
goto err;
}
}
switch (isel) {
case ISELECT_IMSIC_EIDELIVERY:
return riscv_imsic_eidelivery_rmw(imsic, page, val,
new_val, wr_mask);
case ISELECT_IMSIC_EITHRESHOLD:
return riscv_imsic_eithreshold_rmw(imsic, page, val,
new_val, wr_mask);
case ISELECT_IMSIC_TOPEI:
return riscv_imsic_topei_rmw(imsic, page, val, new_val, wr_mask);
case ISELECT_IMSIC_EIP0 ... ISELECT_IMSIC_EIP63:
return riscv_imsic_eix_rmw(imsic, xlen, page,
isel - ISELECT_IMSIC_EIP0,
true, val, new_val, wr_mask);
case ISELECT_IMSIC_EIE0 ... ISELECT_IMSIC_EIE63:
return riscv_imsic_eix_rmw(imsic, xlen, page,
isel - ISELECT_IMSIC_EIE0,
false, val, new_val, wr_mask);
default:
break;
};
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register priv=%d virt=%d isel=%d vgein=%d\n",
__func__, priv, virt, isel, vgein);
return -EINVAL;
}
static uint64_t riscv_imsic_read(void *opaque, hwaddr addr, unsigned size)
{
RISCVIMSICState *imsic = opaque;
/* Reads must be 4 byte words */
if ((addr & 0x3) != 0) {
goto err;
}
/* Reads cannot be out of range */
if (addr > IMSIC_MMIO_SIZE(imsic->num_pages)) {
goto err;
}
return 0;
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register read 0x%" HWADDR_PRIx "\n",
__func__, addr);
return 0;
}
static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
unsigned size)
{
RISCVIMSICState *imsic = opaque;
uint32_t page;
/* Writes must be 4 byte words */
if ((addr & 0x3) != 0) {
goto err;
}
/* Writes cannot be out of range */
if (addr > IMSIC_MMIO_SIZE(imsic->num_pages)) {
goto err;
}
/* Writes only supported for MSI little-endian registers */
page = addr >> IMSIC_MMIO_PAGE_SHIFT;
if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
if (value && (value < imsic->num_irqs)) {
imsic->eistate[(page * imsic->num_irqs) + value] |=
IMSIC_EISTATE_PENDING;
}
}
/* Update CPU external interrupt status */
riscv_imsic_update(imsic, page);
return;
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register write 0x%" HWADDR_PRIx "\n",
__func__, addr);
}
static const MemoryRegionOps riscv_imsic_ops = {
.read = riscv_imsic_read,
.write = riscv_imsic_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4
}
};
static void riscv_imsic_realize(DeviceState *dev, Error **errp)
{
RISCVIMSICState *imsic = RISCV_IMSIC(dev);
RISCVCPU *rcpu = RISCV_CPU(qemu_get_cpu(imsic->hartid));
CPUState *cpu = qemu_get_cpu(imsic->hartid);
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
memory_region_init_io(&imsic->mmio, OBJECT(dev), &riscv_imsic_ops,
imsic, TYPE_RISCV_IMSIC,
IMSIC_MMIO_SIZE(imsic->num_pages));
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &imsic->mmio);
/* Claim the CPU interrupt to be triggered by this IMSIC */
if (riscv_cpu_claim_interrupts(rcpu,
(imsic->mmode) ? MIP_MEIP : MIP_SEIP) < 0) {
error_setg(errp, "%s already claimed",
(imsic->mmode) ? "MEIP" : "SEIP");
return;
}
/* Create output IRQ lines */
imsic->external_irqs = g_malloc(sizeof(qemu_irq) * imsic->num_pages);
qdev_init_gpio_out(dev, imsic->external_irqs, imsic->num_pages);
/* Force select AIA feature and setup CSR read-modify-write callback */
if (env) {
riscv_set_feature(env, RISCV_FEATURE_AIA);
if (!imsic->mmode) {
riscv_cpu_set_geilen(env, imsic->num_pages - 1);
}
riscv_cpu_set_aia_ireg_rmw_fn(env, (imsic->mmode) ? PRV_M : PRV_S,
riscv_imsic_rmw, imsic);
}
msi_nonbroken = true;
}
static Property riscv_imsic_properties[] = {
DEFINE_PROP_BOOL("mmode", RISCVIMSICState, mmode, 0),
DEFINE_PROP_UINT32("hartid", RISCVIMSICState, hartid, 0),
DEFINE_PROP_UINT32("num-pages", RISCVIMSICState, num_pages, 0),
DEFINE_PROP_UINT32("num-irqs", RISCVIMSICState, num_irqs, 0),
DEFINE_PROP_END_OF_LIST(),
};
static const VMStateDescription vmstate_riscv_imsic = {
.name = "riscv_imsic",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_VARRAY_UINT32(eidelivery, RISCVIMSICState,
num_pages, 0,
vmstate_info_uint32, uint32_t),
VMSTATE_VARRAY_UINT32(eithreshold, RISCVIMSICState,
num_pages, 0,
vmstate_info_uint32, uint32_t),
VMSTATE_VARRAY_UINT32(eistate, RISCVIMSICState,
num_eistate, 0,
vmstate_info_uint32, uint32_t),
VMSTATE_END_OF_LIST()
}
};
static void riscv_imsic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
device_class_set_props(dc, riscv_imsic_properties);
dc->realize = riscv_imsic_realize;
dc->vmsd = &vmstate_riscv_imsic;
}
static const TypeInfo riscv_imsic_info = {
.name = TYPE_RISCV_IMSIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(RISCVIMSICState),
.class_init = riscv_imsic_class_init,
};
static void riscv_imsic_register_types(void)
{
type_register_static(&riscv_imsic_info);
}
type_init(riscv_imsic_register_types)
/*
* Create IMSIC device.
*/
DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
uint32_t num_pages, uint32_t num_ids)
{
DeviceState *dev = qdev_new(TYPE_RISCV_IMSIC);
CPUState *cpu = qemu_get_cpu(hartid);
uint32_t i;
assert(!(addr & (IMSIC_MMIO_PAGE_SZ - 1)));
if (mmode) {
assert(num_pages == 1);
} else {
assert(num_pages >= 1 && num_pages <= (IRQ_LOCAL_GUEST_MAX + 1));
}
assert(IMSIC_MIN_ID <= num_ids);
assert(num_ids <= IMSIC_MAX_ID);
assert((num_ids & IMSIC_MIN_ID) == IMSIC_MIN_ID);
qdev_prop_set_bit(dev, "mmode", mmode);
qdev_prop_set_uint32(dev, "hartid", hartid);
qdev_prop_set_uint32(dev, "num-pages", num_pages);
qdev_prop_set_uint32(dev, "num-irqs", num_ids + 1);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
for (i = 0; i < num_pages; i++) {
if (!i) {
qdev_connect_gpio_out_named(dev, NULL, i,
qdev_get_gpio_in(DEVICE(cpu),
(mmode) ? IRQ_M_EXT : IRQ_S_EXT));
} else {
qdev_connect_gpio_out_named(dev, NULL, i,
qdev_get_gpio_in(DEVICE(cpu),
IRQ_LOCAL_MAX + i - 1));
}
}
return dev;
}
+2
View File
@@ -42,6 +42,8 @@ config RISCV_VIRT
select PFLASH_CFI01
select SERIAL
select RISCV_ACLINT
select RISCV_APLIC
select RISCV_IMSIC
select SIFIVE_PLIC
select SIFIVE_TEST
select VIRTIO_MMIO
+9 -3
View File
@@ -34,13 +34,15 @@ static const MemMapEntry ibex_memmap[] = {
[IBEX_DEV_FLASH] = { 0x20000000, 0x80000 },
[IBEX_DEV_UART] = { 0x40000000, 0x1000 },
[IBEX_DEV_GPIO] = { 0x40040000, 0x1000 },
[IBEX_DEV_SPI] = { 0x40050000, 0x1000 },
[IBEX_DEV_SPI_DEVICE] = { 0x40050000, 0x1000 },
[IBEX_DEV_I2C] = { 0x40080000, 0x1000 },
[IBEX_DEV_PATTGEN] = { 0x400e0000, 0x1000 },
[IBEX_DEV_TIMER] = { 0x40100000, 0x1000 },
[IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 },
[IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 },
[IBEX_DEV_USBDEV] = { 0x40150000, 0x1000 },
[IBEX_DEV_SPI_HOST0] = { 0x40300000, 0x1000 },
[IBEX_DEV_SPI_HOST1] = { 0x40310000, 0x1000 },
[IBEX_DEV_PWRMGR] = { 0x40400000, 0x1000 },
[IBEX_DEV_RSTMGR] = { 0x40410000, 0x1000 },
[IBEX_DEV_CLKMGR] = { 0x40420000, 0x1000 },
@@ -209,8 +211,12 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
create_unimplemented_device("riscv.lowrisc.ibex.gpio",
memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size);
create_unimplemented_device("riscv.lowrisc.ibex.spi",
memmap[IBEX_DEV_SPI].base, memmap[IBEX_DEV_SPI].size);
create_unimplemented_device("riscv.lowrisc.ibex.spi_device",
memmap[IBEX_DEV_SPI_DEVICE].base, memmap[IBEX_DEV_SPI_DEVICE].size);
create_unimplemented_device("riscv.lowrisc.ibex.spi_host0",
memmap[IBEX_DEV_SPI_HOST0].base, memmap[IBEX_DEV_SPI_HOST0].size);
create_unimplemented_device("riscv.lowrisc.ibex.spi_host1",
memmap[IBEX_DEV_SPI_HOST1].base, memmap[IBEX_DEV_SPI_HOST1].size);
create_unimplemented_device("riscv.lowrisc.ibex.i2c",
memmap[IBEX_DEV_I2C].base, memmap[IBEX_DEV_I2C].size);
create_unimplemented_device("riscv.lowrisc.ibex.pattgen",
+587 -115
View File
File diff suppressed because it is too large Load Diff
+68
View File
@@ -0,0 +1,68 @@
/*
* RISC-V IMSIC (Incoming Message Signal Interrupt Controller) interface
*
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
*
* 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_RISCV_IMSIC_H
#define HW_RISCV_IMSIC_H
#include "hw/sysbus.h"
#include "qom/object.h"
#define TYPE_RISCV_IMSIC "riscv.imsic"
typedef struct RISCVIMSICState RISCVIMSICState;
DECLARE_INSTANCE_CHECKER(RISCVIMSICState, RISCV_IMSIC, TYPE_RISCV_IMSIC)
#define IMSIC_MMIO_PAGE_SHIFT 12
#define IMSIC_MMIO_PAGE_SZ (1UL << IMSIC_MMIO_PAGE_SHIFT)
#define IMSIC_MMIO_SIZE(__num_pages) ((__num_pages) * IMSIC_MMIO_PAGE_SZ)
#define IMSIC_MMIO_HART_GUEST_MAX_BTIS 6
#define IMSIC_MMIO_GROUP_MIN_SHIFT 24
#define IMSIC_HART_NUM_GUESTS(__guest_bits) \
(1U << (__guest_bits))
#define IMSIC_HART_SIZE(__guest_bits) \
(IMSIC_HART_NUM_GUESTS(__guest_bits) * IMSIC_MMIO_PAGE_SZ)
#define IMSIC_GROUP_NUM_HARTS(__hart_bits) \
(1U << (__hart_bits))
#define IMSIC_GROUP_SIZE(__hart_bits, __guest_bits) \
(IMSIC_GROUP_NUM_HARTS(__hart_bits) * IMSIC_HART_SIZE(__guest_bits))
struct RISCVIMSICState {
/*< private >*/
SysBusDevice parent_obj;
qemu_irq *external_irqs;
/*< public >*/
MemoryRegion mmio;
uint32_t num_eistate;
uint32_t *eidelivery;
uint32_t *eithreshold;
uint32_t *eistate;
/* config */
bool mmode;
uint32_t hartid;
uint32_t num_pages;
uint32_t num_irqs;
};
DeviceState *riscv_imsic_create(hwaddr addr, uint32_t hartid, bool mmode,
uint32_t num_pages, uint32_t num_ids);
#endif
+3 -1
View File
@@ -57,8 +57,10 @@ enum {
IBEX_DEV_FLASH,
IBEX_DEV_FLASH_VIRTUAL,
IBEX_DEV_UART,
IBEX_DEV_SPI_DEVICE,
IBEX_DEV_SPI_HOST0,
IBEX_DEV_SPI_HOST1,
IBEX_DEV_GPIO,
IBEX_DEV_SPI,
IBEX_DEV_I2C,
IBEX_DEV_PATTGEN,
IBEX_DEV_TIMER,
+33 -8
View File
@@ -24,26 +24,36 @@
#include "hw/block/flash.h"
#include "qom/object.h"
#define VIRT_CPUS_MAX 32
#define VIRT_SOCKETS_MAX 8
#define VIRT_CPUS_MAX_BITS 9
#define VIRT_CPUS_MAX (1 << VIRT_CPUS_MAX_BITS)
#define VIRT_SOCKETS_MAX_BITS 2
#define VIRT_SOCKETS_MAX (1 << VIRT_SOCKETS_MAX_BITS)
#define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
typedef struct RISCVVirtState RISCVVirtState;
DECLARE_INSTANCE_CHECKER(RISCVVirtState, RISCV_VIRT_MACHINE,
TYPE_RISCV_VIRT_MACHINE)
typedef enum RISCVVirtAIAType {
VIRT_AIA_TYPE_NONE = 0,
VIRT_AIA_TYPE_APLIC,
VIRT_AIA_TYPE_APLIC_IMSIC,
} RISCVVirtAIAType;
struct RISCVVirtState {
/*< private >*/
MachineState parent;
/*< public >*/
RISCVHartArrayState soc[VIRT_SOCKETS_MAX];
DeviceState *plic[VIRT_SOCKETS_MAX];
DeviceState *irqchip[VIRT_SOCKETS_MAX];
PFlashCFI01 *flash[2];
FWCfgState *fw_cfg;
int fdt_size;
bool have_aclint;
RISCVVirtAIAType aia_type;
int aia_guests;
};
enum {
@@ -54,9 +64,13 @@ enum {
VIRT_CLINT,
VIRT_ACLINT_SSWI,
VIRT_PLIC,
VIRT_APLIC_M,
VIRT_APLIC_S,
VIRT_UART0,
VIRT_VIRTIO,
VIRT_FW_CFG,
VIRT_IMSIC_M,
VIRT_IMSIC_S,
VIRT_FLASH,
VIRT_DRAM,
VIRT_PCIE_MMIO,
@@ -73,8 +87,13 @@ enum {
VIRTIO_NDEV = 0x35 /* Arbitrary maximum number of interrupts */
};
#define VIRT_PLIC_NUM_SOURCES 127
#define VIRT_PLIC_NUM_PRIORITIES 7
#define VIRT_IRQCHIP_IPI_MSI 1
#define VIRT_IRQCHIP_NUM_MSIS 255
#define VIRT_IRQCHIP_NUM_SOURCES VIRTIO_NDEV
#define VIRT_IRQCHIP_NUM_PRIO_BITS 3
#define VIRT_IRQCHIP_MAX_GUESTS_BITS 3
#define VIRT_IRQCHIP_MAX_GUESTS ((1U << VIRT_IRQCHIP_MAX_GUESTS_BITS) - 1U)
#define VIRT_PLIC_PRIORITY_BASE 0x04
#define VIRT_PLIC_PENDING_BASE 0x1000
#define VIRT_PLIC_ENABLE_BASE 0x2000
@@ -86,9 +105,15 @@ enum {
#define FDT_PCI_ADDR_CELLS 3
#define FDT_PCI_INT_CELLS 1
#define FDT_PLIC_ADDR_CELLS 0
#define FDT_PLIC_INT_CELLS 1
#define FDT_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + 1 + \
FDT_PLIC_ADDR_CELLS + FDT_PLIC_INT_CELLS)
#define FDT_APLIC_INT_CELLS 2
#define FDT_IMSIC_INT_CELLS 0
#define FDT_MAX_INT_CELLS 2
#define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
1 + FDT_MAX_INT_CELLS)
#define FDT_PLIC_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
1 + FDT_PLIC_INT_CELLS)
#define FDT_APLIC_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
1 + FDT_APLIC_INT_CELLS)
#endif
+17
View File
@@ -587,6 +587,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
cpu->cfg.ext_d = true;
}
if (cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinx ||
cpu->cfg.ext_zhinxmin) {
cpu->cfg.ext_zfinx = true;
}
/* Set the ISA extensions, checks should have happened above */
if (cpu->cfg.ext_i) {
ext |= RVI;
@@ -665,6 +670,13 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
if (cpu->cfg.ext_j) {
ext |= RVJ;
}
if (cpu->cfg.ext_zfinx && ((ext & (RVF | RVD)) || cpu->cfg.ext_zfh ||
cpu->cfg.ext_zfhmin)) {
error_setg(errp,
"'Zfinx' cannot be supported together with 'F', 'D', 'Zfh',"
" 'Zfhmin'");
return;
}
set_misa(env, env->misa_mxl, ext);
}
@@ -783,6 +795,11 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
DEFINE_PROP_BOOL("zdinx", RISCVCPU, cfg.ext_zdinx, false),
DEFINE_PROP_BOOL("zfinx", RISCVCPU, cfg.ext_zfinx, false),
DEFINE_PROP_BOOL("zhinx", RISCVCPU, cfg.ext_zhinx, false),
DEFINE_PROP_BOOL("zhinxmin", RISCVCPU, cfg.ext_zhinxmin, false),
/* Vendor-specific custom extensions */
DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
+4
View File
@@ -362,8 +362,12 @@ struct RISCVCPUConfig {
bool ext_svinval;
bool ext_svnapot;
bool ext_svpbmt;
bool ext_zdinx;
bool ext_zfh;
bool ext_zfhmin;
bool ext_zfinx;
bool ext_zhinx;
bool ext_zhinxmin;
bool ext_zve32f;
bool ext_zve64f;
+5 -1
View File
@@ -466,9 +466,13 @@ bool riscv_cpu_vector_enabled(CPURISCVState *env)
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
{
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM |
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
MSTATUS64_UXL | MSTATUS_VS;
if (riscv_has_ext(env, RVF)) {
mstatus_mask |= MSTATUS_FS;
}
bool current_virt = riscv_cpu_virt_enabled(env);
g_assert(riscv_has_ext(env, RVH));
+20 -5
View File
@@ -39,7 +39,8 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops)
static RISCVException fs(CPURISCVState *env, int csrno)
{
#if !defined(CONFIG_USER_ONLY)
if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
if (!env->debugger && !riscv_cpu_fp_enabled(env) &&
!RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) {
return RISCV_EXCP_ILLEGAL_INST;
}
#endif
@@ -302,7 +303,9 @@ static RISCVException write_fflags(CPURISCVState *env, int csrno,
target_ulong val)
{
#if !defined(CONFIG_USER_ONLY)
env->mstatus |= MSTATUS_FS;
if (riscv_has_ext(env, RVF)) {
env->mstatus |= MSTATUS_FS;
}
#endif
riscv_cpu_set_fflags(env, val & (FSR_AEXC >> FSR_AEXC_SHIFT));
return RISCV_EXCP_NONE;
@@ -319,7 +322,9 @@ static RISCVException write_frm(CPURISCVState *env, int csrno,
target_ulong val)
{
#if !defined(CONFIG_USER_ONLY)
env->mstatus |= MSTATUS_FS;
if (riscv_has_ext(env, RVF)) {
env->mstatus |= MSTATUS_FS;
}
#endif
env->frm = val & (FSR_RD >> FSR_RD_SHIFT);
return RISCV_EXCP_NONE;
@@ -337,7 +342,9 @@ static RISCVException write_fcsr(CPURISCVState *env, int csrno,
target_ulong val)
{
#if !defined(CONFIG_USER_ONLY)
env->mstatus |= MSTATUS_FS;
if (riscv_has_ext(env, RVF)) {
env->mstatus |= MSTATUS_FS;
}
#endif
env->frm = (val & FSR_RD) >> FSR_RD_SHIFT;
riscv_cpu_set_fflags(env, (val & FSR_AEXC) >> FSR_AEXC_SHIFT);
@@ -653,10 +660,14 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
tlb_flush(env_cpu(env));
}
mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM |
MSTATUS_SPP | MSTATUS_MPRV | MSTATUS_SUM |
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
MSTATUS_TW | MSTATUS_VS;
if (riscv_has_ext(env, RVF)) {
mask |= MSTATUS_FS;
}
if (xl != MXL_RV32 || env->debugger) {
/*
* RV32: MPV and GVA are not in mstatus. The current plan is to
@@ -788,6 +799,10 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
if (!(val & RVF)) {
env->mstatus &= ~MSTATUS_FS;
}
/* flush translation cache */
tb_flush(env_cpu(env));
env->misa_ext = val;
+90 -88
View File
@@ -89,19 +89,21 @@ void helper_set_rod_rounding_mode(CPURISCVState *env)
static uint64_t do_fmadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
uint64_t rs3, int flags)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
float16 frs3 = check_nanbox_h(rs3);
return nanbox_h(float16_muladd(frs1, frs2, frs3, flags, &env->fp_status));
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
float16 frs3 = check_nanbox_h(env, rs3);
return nanbox_h(env, float16_muladd(frs1, frs2, frs3, flags,
&env->fp_status));
}
static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
uint64_t rs3, int flags)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
float32 frs3 = check_nanbox_s(rs3);
return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, &env->fp_status));
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
float32 frs3 = check_nanbox_s(env, rs3);
return nanbox_s(env, float32_muladd(frs1, frs2, frs3, flags,
&env->fp_status));
}
uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
@@ -183,124 +185,124 @@ uint64_t helper_fnmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
return nanbox_s(float32_add(frs1, frs2, &env->fp_status));
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return nanbox_s(env, float32_add(frs1, frs2, &env->fp_status));
}
uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
return nanbox_s(float32_sub(frs1, frs2, &env->fp_status));
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return nanbox_s(env, float32_sub(frs1, frs2, &env->fp_status));
}
uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
return nanbox_s(float32_mul(frs1, frs2, &env->fp_status));
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return nanbox_s(env, float32_mul(frs1, frs2, &env->fp_status));
}
uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
return nanbox_s(float32_div(frs1, frs2, &env->fp_status));
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return nanbox_s(env, float32_div(frs1, frs2, &env->fp_status));
}
uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
return nanbox_s(env->priv_ver < PRIV_VERSION_1_11_0 ?
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
float32_minnum(frs1, frs2, &env->fp_status) :
float32_minimum_number(frs1, frs2, &env->fp_status));
}
uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
return nanbox_s(env->priv_ver < PRIV_VERSION_1_11_0 ?
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
float32_maxnum(frs1, frs2, &env->fp_status) :
float32_maximum_number(frs1, frs2, &env->fp_status));
}
uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
return nanbox_s(float32_sqrt(frs1, &env->fp_status));
float32 frs1 = check_nanbox_s(env, rs1);
return nanbox_s(env, float32_sqrt(frs1, &env->fp_status));
}
target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return float32_le(frs1, frs2, &env->fp_status);
}
target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return float32_lt(frs1, frs2, &env->fp_status);
}
target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs2 = check_nanbox_s(rs2);
float32 frs1 = check_nanbox_s(env, rs1);
float32 frs2 = check_nanbox_s(env, rs2);
return float32_eq_quiet(frs1, frs2, &env->fp_status);
}
target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs1 = check_nanbox_s(env, rs1);
return float32_to_int32(frs1, &env->fp_status);
}
target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs1 = check_nanbox_s(env, rs1);
return (int32_t)float32_to_uint32(frs1, &env->fp_status);
}
target_ulong helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs1 = check_nanbox_s(env, rs1);
return float32_to_int64(frs1, &env->fp_status);
}
target_ulong helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs1 = check_nanbox_s(env, rs1);
return float32_to_uint64(frs1, &env->fp_status);
}
uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
{
return nanbox_s(int32_to_float32((int32_t)rs1, &env->fp_status));
return nanbox_s(env, int32_to_float32((int32_t)rs1, &env->fp_status));
}
uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
{
return nanbox_s(uint32_to_float32((uint32_t)rs1, &env->fp_status));
return nanbox_s(env, uint32_to_float32((uint32_t)rs1, &env->fp_status));
}
uint64_t helper_fcvt_s_l(CPURISCVState *env, target_ulong rs1)
{
return nanbox_s(int64_to_float32(rs1, &env->fp_status));
return nanbox_s(env, int64_to_float32(rs1, &env->fp_status));
}
uint64_t helper_fcvt_s_lu(CPURISCVState *env, target_ulong rs1)
{
return nanbox_s(uint64_to_float32(rs1, &env->fp_status));
return nanbox_s(env, uint64_to_float32(rs1, &env->fp_status));
}
target_ulong helper_fclass_s(uint64_t rs1)
target_ulong helper_fclass_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs1 = check_nanbox_s(env, rs1);
return fclass_s(frs1);
}
@@ -340,12 +342,12 @@ uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
{
return nanbox_s(float64_to_float32(rs1, &env->fp_status));
return nanbox_s(env, float64_to_float32(rs1, &env->fp_status));
}
uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
float32 frs1 = check_nanbox_s(env, rs1);
return float32_to_float64(frs1, &env->fp_status);
}
@@ -416,146 +418,146 @@ target_ulong helper_fclass_d(uint64_t frs1)
uint64_t helper_fadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
return nanbox_h(float16_add(frs1, frs2, &env->fp_status));
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return nanbox_h(env, float16_add(frs1, frs2, &env->fp_status));
}
uint64_t helper_fsub_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
return nanbox_h(float16_sub(frs1, frs2, &env->fp_status));
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return nanbox_h(env, float16_sub(frs1, frs2, &env->fp_status));
}
uint64_t helper_fmul_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
return nanbox_h(float16_mul(frs1, frs2, &env->fp_status));
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return nanbox_h(env, float16_mul(frs1, frs2, &env->fp_status));
}
uint64_t helper_fdiv_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
return nanbox_h(float16_div(frs1, frs2, &env->fp_status));
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return nanbox_h(env, float16_div(frs1, frs2, &env->fp_status));
}
uint64_t helper_fmin_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
return nanbox_h(env->priv_ver < PRIV_VERSION_1_11_0 ?
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
float16_minnum(frs1, frs2, &env->fp_status) :
float16_minimum_number(frs1, frs2, &env->fp_status));
}
uint64_t helper_fmax_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
return nanbox_h(env->priv_ver < PRIV_VERSION_1_11_0 ?
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
float16_maxnum(frs1, frs2, &env->fp_status) :
float16_maximum_number(frs1, frs2, &env->fp_status));
}
uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs1)
{
float16 frs1 = check_nanbox_h(rs1);
return nanbox_h(float16_sqrt(frs1, &env->fp_status));
float16 frs1 = check_nanbox_h(env, rs1);
return nanbox_h(env, float16_sqrt(frs1, &env->fp_status));
}
target_ulong helper_fle_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return float16_le(frs1, frs2, &env->fp_status);
}
target_ulong helper_flt_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return float16_lt(frs1, frs2, &env->fp_status);
}
target_ulong helper_feq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs2 = check_nanbox_h(rs2);
float16 frs1 = check_nanbox_h(env, rs1);
float16 frs2 = check_nanbox_h(env, rs2);
return float16_eq_quiet(frs1, frs2, &env->fp_status);
}
target_ulong helper_fclass_h(uint64_t rs1)
target_ulong helper_fclass_h(CPURISCVState *env, uint64_t rs1)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs1 = check_nanbox_h(env, rs1);
return fclass_h(frs1);
}
target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs1 = check_nanbox_h(env, rs1);
return float16_to_int32(frs1, &env->fp_status);
}
target_ulong helper_fcvt_wu_h(CPURISCVState *env, uint64_t rs1)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs1 = check_nanbox_h(env, rs1);
return (int32_t)float16_to_uint32(frs1, &env->fp_status);
}
target_ulong helper_fcvt_l_h(CPURISCVState *env, uint64_t rs1)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs1 = check_nanbox_h(env, rs1);
return float16_to_int64(frs1, &env->fp_status);
}
target_ulong helper_fcvt_lu_h(CPURISCVState *env, uint64_t rs1)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs1 = check_nanbox_h(env, rs1);
return float16_to_uint64(frs1, &env->fp_status);
}
uint64_t helper_fcvt_h_w(CPURISCVState *env, target_ulong rs1)
{
return nanbox_h(int32_to_float16((int32_t)rs1, &env->fp_status));
return nanbox_h(env, int32_to_float16((int32_t)rs1, &env->fp_status));
}
uint64_t helper_fcvt_h_wu(CPURISCVState *env, target_ulong rs1)
{
return nanbox_h(uint32_to_float16((uint32_t)rs1, &env->fp_status));
return nanbox_h(env, uint32_to_float16((uint32_t)rs1, &env->fp_status));
}
uint64_t helper_fcvt_h_l(CPURISCVState *env, target_ulong rs1)
{
return nanbox_h(int64_to_float16(rs1, &env->fp_status));
return nanbox_h(env, int64_to_float16(rs1, &env->fp_status));
}
uint64_t helper_fcvt_h_lu(CPURISCVState *env, target_ulong rs1)
{
return nanbox_h(uint64_to_float16(rs1, &env->fp_status));
return nanbox_h(env, uint64_to_float16(rs1, &env->fp_status));
}
uint64_t helper_fcvt_h_s(CPURISCVState *env, uint64_t rs1)
{
float32 frs1 = check_nanbox_s(rs1);
return nanbox_h(float32_to_float16(frs1, true, &env->fp_status));
float32 frs1 = check_nanbox_s(env, rs1);
return nanbox_h(env, float32_to_float16(frs1, true, &env->fp_status));
}
uint64_t helper_fcvt_s_h(CPURISCVState *env, uint64_t rs1)
{
float16 frs1 = check_nanbox_h(rs1);
return nanbox_s(float16_to_float32(frs1, true, &env->fp_status));
float16 frs1 = check_nanbox_h(env, rs1);
return nanbox_s(env, float16_to_float32(frs1, true, &env->fp_status));
}
uint64_t helper_fcvt_h_d(CPURISCVState *env, uint64_t rs1)
{
return nanbox_h(float64_to_float16(rs1, true, &env->fp_status));
return nanbox_h(env, float64_to_float16(rs1, true, &env->fp_status));
}
uint64_t helper_fcvt_d_h(CPURISCVState *env, uint64_t rs1)
{
float16 frs1 = check_nanbox_h(rs1);
float16 frs1 = check_nanbox_h(env, rs1);
return float16_to_float64(frs1, true, &env->fp_status);
}
+2 -2
View File
@@ -38,7 +38,7 @@ 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, 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)
DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, tl, env, i64)
/* Floating Point - Double Precision */
DEF_HELPER_FLAGS_3(fadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64)
@@ -90,7 +90,7 @@ DEF_HELPER_FLAGS_2(fcvt_h_w, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_2(fcvt_h_wu, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_2(fcvt_h_l, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_2(fcvt_h_lu, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_1(fclass_h, TCG_CALL_NO_RWG_SE, tl, i64)
DEF_HELPER_FLAGS_2(fclass_h, TCG_CALL_NO_RWG_SE, tl, env, i64)
/* Special functions */
DEF_HELPER_2(csrr, tl, env, int)
+4 -4
View File
@@ -19,25 +19,25 @@
*/
#define REQUIRE_ZBA(ctx) do { \
if (ctx->cfg_ptr->ext_zba) { \
if (!ctx->cfg_ptr->ext_zba) { \
return false; \
} \
} while (0)
#define REQUIRE_ZBB(ctx) do { \
if (ctx->cfg_ptr->ext_zbb) { \
if (!ctx->cfg_ptr->ext_zbb) { \
return false; \
} \
} while (0)
#define REQUIRE_ZBC(ctx) do { \
if (ctx->cfg_ptr->ext_zbc) { \
if (!ctx->cfg_ptr->ext_zbc) { \
return false; \
} \
} while (0)
#define REQUIRE_ZBS(ctx) do { \
if (ctx->cfg_ptr->ext_zbs) { \
if (!ctx->cfg_ptr->ext_zbs) { \
return false; \
} \
} while (0)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More