Second RISC-V PR for 10.2
* Correct mmu-type property of sifive_u harts in device tree * Centralize MO_TE uses in a pair of helpers * Fix Ethernet interface support for microchip-icicle-kit * Fix mask for smsiaddrcfgh * Fix env->priv setting in reset_regs_csr() * Coverity-related fixes * Fix riscv_cpu_sirq_pending() mask * Fix a uninitialized variable warning * Make PMP granularity configurable -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEaukCtqfKh31tZZKWr3yVEwxTgBMFAmj6vn4ACgkQr3yVEwxT gBORBg/9HMcPIWY4TweyZXcVkcB/4LY3XboBCcumTUO3dEkiVMYc5TDauO++YiyJ YPRzFSAgwNxoF2ndtNLSc6OCu6LPRzWpt9a/MavTzfNLOQZ5vUbYCd3g24uR4Plz AOt7Jn9l8+95MxGeTq5NfDdOnyC+mF4EiIjhplbZz7UcMpouKRysAibSjuyXlYGD DutmQ/bctyDsASNFIl3xwT4po1M4EgMX4nL01ZbfYw2sTjPH2Vj53E0eQ9iZCsP6 l8L8PEz4Jiad2rapJdm2OS6mirMd3PZbYWqvRga/NQiTs4jGYSxiIhlpqR3Ez2id UBGjLKcbsgvyaX1ILq3n6nfftjrXpSEnCMh86/H3xZ8dhA8eBMrGTJvYXAX33ao5 d3ClcT+E7FTduc+hWl/B/l3eb6fOcEIQ172slBiPEfJJqwJgkXgOfftlxRJQ3iGs FbpCL0zEeB1/0SUvgI8Wv5652GiaAljWhhIM7FhWpohc2DxV2iUXuxhhXgHkztwL EIddIo9FLQqY7wxlQhvQKRT0hCm/9mtokq6jiQUTuVMn7gf4fWdvDSozRvX1b0DB CiJcPnKgM/M4UQHci8rboADWPSJ8oOSdz5dheQfXVNJczFnDqzMMVFbkFicXidJU aT+1sPuuSYE6hquR1p4yvxeyyfIQCdffzRBr3WZ2iq7GQ+I4/64= =P0/u -----END PGP SIGNATURE----- Merge tag 'pull-riscv-to-apply-20251024' of https://github.com/alistair23/qemu into staging Second RISC-V PR for 10.2 * Correct mmu-type property of sifive_u harts in device tree * Centralize MO_TE uses in a pair of helpers * Fix Ethernet interface support for microchip-icicle-kit * Fix mask for smsiaddrcfgh * Fix env->priv setting in reset_regs_csr() * Coverity-related fixes * Fix riscv_cpu_sirq_pending() mask * Fix a uninitialized variable warning * Make PMP granularity configurable # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEEaukCtqfKh31tZZKWr3yVEwxTgBMFAmj6vn4ACgkQr3yVEwxT # gBORBg/9HMcPIWY4TweyZXcVkcB/4LY3XboBCcumTUO3dEkiVMYc5TDauO++YiyJ # YPRzFSAgwNxoF2ndtNLSc6OCu6LPRzWpt9a/MavTzfNLOQZ5vUbYCd3g24uR4Plz # AOt7Jn9l8+95MxGeTq5NfDdOnyC+mF4EiIjhplbZz7UcMpouKRysAibSjuyXlYGD # DutmQ/bctyDsASNFIl3xwT4po1M4EgMX4nL01ZbfYw2sTjPH2Vj53E0eQ9iZCsP6 # l8L8PEz4Jiad2rapJdm2OS6mirMd3PZbYWqvRga/NQiTs4jGYSxiIhlpqR3Ez2id # UBGjLKcbsgvyaX1ILq3n6nfftjrXpSEnCMh86/H3xZ8dhA8eBMrGTJvYXAX33ao5 # d3ClcT+E7FTduc+hWl/B/l3eb6fOcEIQ172slBiPEfJJqwJgkXgOfftlxRJQ3iGs # FbpCL0zEeB1/0SUvgI8Wv5652GiaAljWhhIM7FhWpohc2DxV2iUXuxhhXgHkztwL # EIddIo9FLQqY7wxlQhvQKRT0hCm/9mtokq6jiQUTuVMn7gf4fWdvDSozRvX1b0DB # CiJcPnKgM/M4UQHci8rboADWPSJ8oOSdz5dheQfXVNJczFnDqzMMVFbkFicXidJU # aT+1sPuuSYE6hquR1p4yvxeyyfIQCdffzRBr3WZ2iq7GQ+I4/64= # =P0/u # -----END PGP SIGNATURE----- # gpg: Signature made Fri 24 Oct 2025 01:47:10 AM CEST # gpg: using RSA key 6AE902B6A7CA877D6D659296AF7C95130C538013 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 6AE9 02B6 A7CA 877D 6D65 9296 AF7C 9513 0C53 8013 * tag 'pull-riscv-to-apply-20251024' of https://github.com/alistair23/qemu: (25 commits) target/riscv: Make PMP CSRs conform to WARL constraints target/riscv: Make PMP granularity configurable target/riscv: Fix a uninitialized variable warning target/riscv: fix riscv_cpu_sirq_pending() mask target/riscv/riscv-qmp-cmds.c: coverity-related fixes target/riscv/kvm: fix env->priv setting in reset_regs_csr() hw/intc: Allow gaps in hartids for aclint and aplic aplic: fix mask for smsiaddrcfgh microchip icicle: Enable PCS on Cadence Ethernet hw/net/cadence_gem: Add pcs-enabled property hw/riscv: microchip_pfsoc: Connect Ethernet PHY channels hw/net/cadence_gem: Support two Ethernet interfaces connected to single MDIO bus target/riscv: Introduce mo_endian_env() helper target/riscv: Introduce mo_endian() helper target/riscv: Factor MemOp variable out when MO_TE is set target/riscv: Conceal MO_TE|MO_ALIGN within gen_lr() / gen_sc() target/riscv: Conceal MO_TE within gen_cmpxchg*() target/riscv: Conceal MO_TE within gen_storepair_tl() target/riscv: Conceal MO_TE within gen_fload_idx() / gen_fstore_idx() target/riscv: Conceal MO_TE within gen_load_idx() / gen_store_idx() ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
e8779f3d15
26 changed files with 361 additions and 159 deletions
|
|
@ -297,7 +297,12 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp)
|
|||
s->timecmp = g_new0(uint64_t, s->num_harts);
|
||||
/* Claim timer interrupt bits */
|
||||
for (i = 0; i < s->num_harts; i++) {
|
||||
RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(s->hartid_base + i));
|
||||
CPUState *cpu_by_hartid = cpu_by_arch_id(s->hartid_base + i);
|
||||
if (cpu_by_hartid == NULL) {
|
||||
/* Valid for sparse hart layouts - skip this hart ID */
|
||||
continue;
|
||||
}
|
||||
RISCVCPU *cpu = RISCV_CPU(cpu_by_hartid);
|
||||
if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) {
|
||||
error_report("MTIP already claimed");
|
||||
exit(1);
|
||||
|
|
@ -489,7 +494,12 @@ static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
/* Claim software interrupt bits */
|
||||
for (i = 0; i < swi->num_harts; i++) {
|
||||
RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(swi->hartid_base + i));
|
||||
CPUState *cpu_by_hartid = cpu_by_arch_id(swi->hartid_base + i);
|
||||
if (cpu_by_hartid == NULL) {
|
||||
/* Valid for sparse hart layouts - skip this hart ID */
|
||||
continue;
|
||||
}
|
||||
RISCVCPU *cpu = RISCV_CPU(cpu_by_hartid);
|
||||
/* We don't claim mip.SSIP because it is writable by software */
|
||||
if (riscv_cpu_claim_interrupts(cpu, swi->sswi ? 0 : MIP_MSIP) < 0) {
|
||||
error_report("MSIP already claimed");
|
||||
|
|
@ -553,6 +563,10 @@ DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
|
|||
|
||||
for (i = 0; i < num_harts; i++) {
|
||||
CPUState *cpu = cpu_by_arch_id(hartid_base + i);
|
||||
if (cpu == NULL) {
|
||||
/* Valid for sparse hart layouts - skip this hart ID */
|
||||
continue;
|
||||
}
|
||||
RISCVCPU *rvcpu = RISCV_CPU(cpu);
|
||||
|
||||
qdev_connect_gpio_out(dev, i,
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@
|
|||
(APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) << \
|
||||
APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs))
|
||||
|
||||
#define APLIC_xMSICFGADDRH_VALID_MASK \
|
||||
#define APLIC_MMSICFGADDRH_VALID_MASK \
|
||||
(APLIC_xMSICFGADDRH_L | \
|
||||
(APLIC_xMSICFGADDRH_HHXS_MASK << APLIC_xMSICFGADDRH_HHXS_SHIFT) | \
|
||||
(APLIC_xMSICFGADDRH_LHXS_MASK << APLIC_xMSICFGADDRH_LHXS_SHIFT) | \
|
||||
|
|
@ -104,6 +104,10 @@
|
|||
(APLIC_xMSICFGADDRH_LHXW_MASK << APLIC_xMSICFGADDRH_LHXW_SHIFT) | \
|
||||
APLIC_xMSICFGADDRH_BAPPN_MASK)
|
||||
|
||||
#define APLIC_SMSICFGADDRH_VALID_MASK \
|
||||
((APLIC_xMSICFGADDRH_LHXS_MASK << APLIC_xMSICFGADDRH_LHXS_SHIFT) | \
|
||||
APLIC_xMSICFGADDRH_BAPPN_MASK)
|
||||
|
||||
#define APLIC_SETIP_BASE 0x1c00
|
||||
#define APLIC_SETIPNUM 0x1cdc
|
||||
|
||||
|
|
@ -184,7 +188,7 @@ void riscv_aplic_set_kvm_msicfgaddr(RISCVAPLICState *aplic, hwaddr addr)
|
|||
addr >>= APLIC_xMSICFGADDR_PPN_SHIFT;
|
||||
aplic->kvm_msicfgaddr = extract64(addr, 0, 32);
|
||||
aplic->kvm_msicfgaddrH = extract64(addr, 32, 32) &
|
||||
APLIC_xMSICFGADDRH_VALID_MASK;
|
||||
APLIC_MMSICFGADDRH_VALID_MASK;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -409,13 +413,8 @@ static void riscv_aplic_msi_send(RISCVAPLICState *aplic,
|
|||
msicfgaddr = aplic->kvm_msicfgaddr;
|
||||
msicfgaddrH = ((uint64_t)aplic->kvm_msicfgaddrH << 32);
|
||||
} else {
|
||||
if (aplic->mmode) {
|
||||
msicfgaddr = aplic_m->mmsicfgaddr;
|
||||
msicfgaddrH = aplic_m->mmsicfgaddrH;
|
||||
} else {
|
||||
msicfgaddr = aplic_m->smsicfgaddr;
|
||||
msicfgaddrH = aplic_m->smsicfgaddrH;
|
||||
}
|
||||
msicfgaddr = aplic_m->mmsicfgaddr;
|
||||
msicfgaddrH = aplic_m->mmsicfgaddrH;
|
||||
}
|
||||
|
||||
lhxs = (msicfgaddrH >> APLIC_xMSICFGADDRH_LHXS_SHIFT) &
|
||||
|
|
@ -427,6 +426,14 @@ static void riscv_aplic_msi_send(RISCVAPLICState *aplic,
|
|||
hhxw = (msicfgaddrH >> APLIC_xMSICFGADDRH_HHXW_SHIFT) &
|
||||
APLIC_xMSICFGADDRH_HHXW_MASK;
|
||||
|
||||
if (!aplic->kvm_splitmode && !aplic->mmode) {
|
||||
msicfgaddrH = aplic_m->smsicfgaddrH;
|
||||
msicfgaddr = aplic_m->smsicfgaddr;
|
||||
|
||||
lhxs = (msicfgaddrH >> APLIC_xMSICFGADDRH_LHXS_SHIFT) &
|
||||
APLIC_xMSICFGADDRH_LHXS_MASK;
|
||||
}
|
||||
|
||||
group_idx = hart_idx >> lhxw;
|
||||
|
||||
addr = msicfgaddr;
|
||||
|
|
@ -771,7 +778,7 @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value,
|
|||
} else if (aplic->mmode && aplic->msimode &&
|
||||
(addr == APLIC_MMSICFGADDRH)) {
|
||||
if (!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
|
||||
aplic->mmsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK;
|
||||
aplic->mmsicfgaddrH = value & APLIC_MMSICFGADDRH_VALID_MASK;
|
||||
}
|
||||
} else if (aplic->mmode && aplic->msimode &&
|
||||
(addr == APLIC_SMSICFGADDR)) {
|
||||
|
|
@ -792,7 +799,7 @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value,
|
|||
(addr == APLIC_SMSICFGADDRH)) {
|
||||
if (aplic->num_children &&
|
||||
!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
|
||||
aplic->smsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK;
|
||||
aplic->smsicfgaddrH = value & APLIC_SMSICFGADDRH_VALID_MASK;
|
||||
}
|
||||
} else if ((APLIC_SETIP_BASE <= addr) &&
|
||||
(addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) {
|
||||
|
|
@ -903,9 +910,12 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
|
|||
if (!aplic->msimode) {
|
||||
/* Claim the CPU interrupt to be triggered by this APLIC */
|
||||
for (i = 0; i < aplic->num_harts; i++) {
|
||||
RISCVCPU *cpu;
|
||||
|
||||
cpu = RISCV_CPU(cpu_by_arch_id(aplic->hartid_base + i));
|
||||
CPUState *temp = cpu_by_arch_id(aplic->hartid_base + i);
|
||||
if (temp == NULL) {
|
||||
/* Valid for sparse hart layouts - skip this hart ID */
|
||||
continue;
|
||||
}
|
||||
RISCVCPU *cpu = RISCV_CPU(temp);
|
||||
if (riscv_cpu_claim_interrupts(cpu,
|
||||
(aplic->mmode) ? MIP_MEIP : MIP_SEIP) < 0) {
|
||||
error_report("%s already claimed",
|
||||
|
|
@ -1088,6 +1098,10 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
|
|||
if (!msimode) {
|
||||
for (i = 0; i < num_harts; i++) {
|
||||
CPUState *cpu = cpu_by_arch_id(hartid_base + i);
|
||||
if (cpu == NULL) {
|
||||
/* Valid for sparse hart layouts - skip this hart ID */
|
||||
continue;
|
||||
}
|
||||
|
||||
qdev_connect_gpio_out_named(dev, NULL, i,
|
||||
qdev_get_gpio_in(DEVICE(cpu),
|
||||
|
|
|
|||
|
|
@ -1477,7 +1477,10 @@ static void gem_reset(DeviceState *d)
|
|||
s->regs[R_TXPARTIALSF] = 0x000003ff;
|
||||
s->regs[R_RXPARTIALSF] = 0x000003ff;
|
||||
s->regs[R_MODID] = s->revision;
|
||||
s->regs[R_DESCONF] = 0x02D00111;
|
||||
s->regs[R_DESCONF] = 0x02D00110;
|
||||
if (!s->pcs_enabled) {
|
||||
s->regs[R_DESCONF] |= 0x00000001;
|
||||
}
|
||||
s->regs[R_DESCONF2] = 0x2ab10000 | s->jumbo_max_len;
|
||||
s->regs[R_DESCONF5] = 0x002f2045;
|
||||
s->regs[R_DESCONF6] = R_DESCONF6_DMA_ADDR_64B_MASK;
|
||||
|
|
@ -1541,12 +1544,20 @@ static void gem_handle_phy_access(CadenceGEMState *s)
|
|||
{
|
||||
uint32_t val = s->regs[R_PHYMNTNC];
|
||||
uint32_t phy_addr, reg_num;
|
||||
CadenceGEMState *ps = s;
|
||||
uint32_t op;
|
||||
|
||||
phy_addr = FIELD_EX32(val, PHYMNTNC, PHY_ADDR);
|
||||
op = FIELD_EX32(val, PHYMNTNC, OP);
|
||||
|
||||
if (phy_addr != s->phy_addr) {
|
||||
/* no phy at this address */
|
||||
if (FIELD_EX32(val, PHYMNTNC, OP) == MDIO_OP_READ) {
|
||||
/* Switch phy to consumer interface if there is an address match */
|
||||
if (s->phy_consumer && phy_addr == s->phy_consumer->phy_addr) {
|
||||
ps = s->phy_consumer;
|
||||
}
|
||||
|
||||
if (!s->phy_connected || phy_addr != ps->phy_addr) {
|
||||
/* phy not connected or no phy at this address */
|
||||
if (op == MDIO_OP_READ) {
|
||||
s->regs[R_PHYMNTNC] = FIELD_DP32(val, PHYMNTNC, DATA, 0xffff);
|
||||
}
|
||||
return;
|
||||
|
|
@ -1554,14 +1565,14 @@ static void gem_handle_phy_access(CadenceGEMState *s)
|
|||
|
||||
reg_num = FIELD_EX32(val, PHYMNTNC, REG_ADDR);
|
||||
|
||||
switch (FIELD_EX32(val, PHYMNTNC, OP)) {
|
||||
switch (op) {
|
||||
case MDIO_OP_READ:
|
||||
s->regs[R_PHYMNTNC] = FIELD_DP32(val, PHYMNTNC, DATA,
|
||||
gem_phy_read(s, reg_num));
|
||||
gem_phy_read(ps, reg_num));
|
||||
break;
|
||||
|
||||
case MDIO_OP_WRITE:
|
||||
gem_phy_write(s, reg_num, val);
|
||||
gem_phy_write(ps, reg_num, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -1813,6 +1824,12 @@ static const Property gem_properties[] = {
|
|||
num_type2_screeners, 4),
|
||||
DEFINE_PROP_UINT16("jumbo-max-len", CadenceGEMState,
|
||||
jumbo_max_len, 10240),
|
||||
DEFINE_PROP_BOOL("pcs-enabled", CadenceGEMState,
|
||||
pcs_enabled, false),
|
||||
DEFINE_PROP_BOOL("phy-connected", CadenceGEMState, phy_connected, true),
|
||||
DEFINE_PROP_LINK("phy-consumer", CadenceGEMState, phy_consumer,
|
||||
TYPE_CADENCE_GEM, CadenceGEMState *),
|
||||
|
||||
DEFINE_PROP_LINK("dma", CadenceGEMState, dma_mr,
|
||||
TYPE_MEMORY_REGION, MemoryRegion *),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -414,6 +414,9 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
object_property_set_int(OBJECT(&s->gem0), "revision", GEM_REVISION, errp);
|
||||
object_property_set_int(OBJECT(&s->gem0), "phy-addr", 8, errp);
|
||||
object_property_set_bool(OBJECT(&s->gem0), "phy-connected", false, errp);
|
||||
object_property_set_bool(OBJECT(&s->gem0), "pcs-enabled", true, errp);
|
||||
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->gem0), errp);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem0), 0,
|
||||
memmap[MICROCHIP_PFSOC_GEM0].base);
|
||||
|
|
@ -422,6 +425,9 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
object_property_set_int(OBJECT(&s->gem1), "revision", GEM_REVISION, errp);
|
||||
object_property_set_int(OBJECT(&s->gem1), "phy-addr", 9, errp);
|
||||
object_property_set_link(OBJECT(&s->gem1), "phy-consumer",
|
||||
OBJECT(&s->gem0), errp);
|
||||
object_property_set_bool(OBJECT(&s->gem1), "pcs-enabled", true, errp);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->gem1), errp);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem1), 0,
|
||||
memmap[MICROCHIP_PFSOC_GEM1].base);
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
|
|||
if (is_32_bit) {
|
||||
qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
|
||||
} else {
|
||||
qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
|
||||
qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv39");
|
||||
}
|
||||
riscv_isa_write_fdt(&s->soc.u_cpus.harts[cpu - 1], fdt, nodename);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ struct CadenceGEMState {
|
|||
uint8_t num_type2_screeners;
|
||||
uint32_t revision;
|
||||
uint16_t jumbo_max_len;
|
||||
bool pcs_enabled;
|
||||
|
||||
/* GEM registers backing store */
|
||||
uint32_t regs[CADENCE_GEM_MAXREG];
|
||||
|
|
@ -81,6 +82,9 @@ struct CadenceGEMState {
|
|||
|
||||
uint8_t phy_loop; /* Are we in phy loopback? */
|
||||
|
||||
bool phy_connected; /* true if connected */
|
||||
struct CadenceGEMState *phy_consumer;
|
||||
|
||||
/* The current DMA descriptor pointers */
|
||||
uint32_t rx_desc_addr[MAX_PRIORITY_QUEUES];
|
||||
uint32_t tx_desc_addr[MAX_PRIORITY_QUEUES];
|
||||
|
|
|
|||
|
|
@ -1121,6 +1121,7 @@ static void riscv_cpu_init(Object *obj)
|
|||
cpu->cfg.cbop_blocksize = 64;
|
||||
cpu->cfg.cboz_blocksize = 64;
|
||||
cpu->cfg.pmp_regions = 16;
|
||||
cpu->cfg.pmp_granularity = MIN_RISCV_PMP_GRANULARITY;
|
||||
cpu->env.vext_ver = VEXT_VERSION_1_00_0;
|
||||
cpu->cfg.max_satp_mode = -1;
|
||||
|
||||
|
|
@ -1606,6 +1607,43 @@ static const PropertyInfo prop_num_pmp_regions = {
|
|||
.set = prop_num_pmp_regions_set,
|
||||
};
|
||||
|
||||
static void prop_pmp_granularity_set(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
RISCVCPU *cpu = RISCV_CPU(obj);
|
||||
uint32_t value;
|
||||
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
|
||||
if ((value < MIN_RISCV_PMP_GRANULARITY) && (value & (value - 1))) {
|
||||
error_setg(errp, "PMP granularity must be a power of 2 and at least %d",
|
||||
MIN_RISCV_PMP_GRANULARITY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpu->cfg.pmp_granularity != value && riscv_cpu_is_vendor(obj)) {
|
||||
cpu_set_prop_err(cpu, name, errp);
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_option_add_user_setting(name, value);
|
||||
cpu->cfg.pmp_granularity = value;
|
||||
}
|
||||
|
||||
static void prop_pmp_granularity_get(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
uint32_t value = RISCV_CPU(obj)->cfg.pmp_granularity;
|
||||
|
||||
visit_type_uint32(v, name, &value, errp);
|
||||
}
|
||||
|
||||
static const PropertyInfo prop_pmp_granularity = {
|
||||
.description = "pmp-granularity",
|
||||
.get = prop_pmp_granularity_get,
|
||||
.set = prop_pmp_granularity_set,
|
||||
};
|
||||
|
||||
static int priv_spec_from_str(const char *priv_spec_str)
|
||||
{
|
||||
int priv_version = -1;
|
||||
|
|
@ -2606,6 +2644,7 @@ static const Property riscv_cpu_properties[] = {
|
|||
{.name = "mmu", .info = &prop_mmu},
|
||||
{.name = "pmp", .info = &prop_pmp},
|
||||
{.name = "num-pmp-regions", .info = &prop_num_pmp_regions},
|
||||
{.name = "pmp-granularity", .info = &prop_pmp_granularity},
|
||||
|
||||
{.name = "priv_spec", .info = &prop_priv_spec},
|
||||
{.name = "vext_spec", .info = &prop_vext_spec},
|
||||
|
|
|
|||
|
|
@ -176,6 +176,7 @@ extern RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[];
|
|||
|
||||
#define MAX_RISCV_PMPS (64)
|
||||
#define OLD_MAX_RISCV_PMPS (16)
|
||||
#define MIN_RISCV_PMP_GRANULARITY 4
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#include "pmp.h"
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ TYPED_FIELD(uint16_t, cbom_blocksize, 0)
|
|||
TYPED_FIELD(uint16_t, cbop_blocksize, 0)
|
||||
TYPED_FIELD(uint16_t, cboz_blocksize, 0)
|
||||
TYPED_FIELD(uint8_t, pmp_regions, 0)
|
||||
TYPED_FIELD(uint32_t, pmp_granularity, 0)
|
||||
|
||||
TYPED_FIELD(int8_t, max_satp_mode, -1)
|
||||
|
||||
|
|
|
|||
|
|
@ -443,8 +443,7 @@ int riscv_cpu_mirq_pending(CPURISCVState *env)
|
|||
|
||||
int riscv_cpu_sirq_pending(CPURISCVState *env)
|
||||
{
|
||||
uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg &
|
||||
~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
|
||||
uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & ~env->hideleg;
|
||||
uint64_t irqs_f = env->mvip & env->mvien & ~env->mideleg & env->sie;
|
||||
|
||||
return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop)
|
|||
{
|
||||
TCGv src1;
|
||||
|
||||
mop |= MO_ALIGN;
|
||||
mop |= mo_endian(ctx);
|
||||
|
||||
decode_save_opc(ctx, 0);
|
||||
src1 = get_address(ctx, a->rs1, 0);
|
||||
if (a->rl) {
|
||||
|
|
@ -61,6 +64,9 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop)
|
|||
TCGLabel *l1 = gen_new_label();
|
||||
TCGLabel *l2 = gen_new_label();
|
||||
|
||||
mop |= MO_ALIGN;
|
||||
mop |= mo_endian(ctx);
|
||||
|
||||
decode_save_opc(ctx, 0);
|
||||
src1 = get_address(ctx, a->rs1, 0);
|
||||
tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1);
|
||||
|
|
@ -99,142 +105,142 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop)
|
|||
static bool trans_lr_w(DisasContext *ctx, arg_lr_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZALRSC(ctx);
|
||||
return gen_lr(ctx, a, (MO_ALIGN | MO_TESL));
|
||||
return gen_lr(ctx, a, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZALRSC(ctx);
|
||||
return gen_sc(ctx, a, (MO_ALIGN | MO_TESL));
|
||||
return gen_sc(ctx, a, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amomin_w(DisasContext *ctx, arg_amomin_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amomax_w(DisasContext *ctx, arg_amomax_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amominu_w(DisasContext *ctx, arg_amominu_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_amomaxu_w(DisasContext *ctx, arg_amomaxu_w *a)
|
||||
{
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TESL);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZALRSC(ctx);
|
||||
return gen_lr(ctx, a, MO_ALIGN | MO_TEUQ);
|
||||
return gen_lr(ctx, a, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZALRSC(ctx);
|
||||
return gen_sc(ctx, a, (MO_ALIGN | MO_TEUQ));
|
||||
return gen_sc(ctx, a, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amoswap_d(DisasContext *ctx, arg_amoswap_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amoadd_d(DisasContext *ctx, arg_amoadd_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amoxor_d(DisasContext *ctx, arg_amoxor_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amoand_d(DisasContext *ctx, arg_amoand_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amoor_d(DisasContext *ctx, arg_amoor_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amomin_d(DisasContext *ctx, arg_amomin_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amomax_d(DisasContext *ctx, arg_amomax_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amominu_d(DisasContext *ctx, arg_amominu_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_amomaxu_d(DisasContext *ctx, arg_amomaxu_d *a)
|
||||
{
|
||||
REQUIRE_64BIT(ctx);
|
||||
REQUIRE_A_OR_ZAAMO(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TEUQ);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_UQ);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
static bool trans_fld(DisasContext *ctx, arg_fld *a)
|
||||
{
|
||||
TCGv addr;
|
||||
MemOp memop = MO_TEUQ;
|
||||
MemOp memop = MO_UQ;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
|
|
@ -60,6 +60,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a)
|
|||
} else {
|
||||
memop |= MO_ATOM_IFALIGN;
|
||||
}
|
||||
memop |= mo_endian(ctx);
|
||||
|
||||
decode_save_opc(ctx, 0);
|
||||
addr = get_address(ctx, a->rs1, a->imm);
|
||||
|
|
@ -72,7 +73,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a)
|
|||
static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
|
||||
{
|
||||
TCGv addr;
|
||||
MemOp memop = MO_TEUQ;
|
||||
MemOp memop = MO_UQ;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
|
|
@ -84,6 +85,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
|
|||
} else {
|
||||
memop |= MO_ATOM_IFALIGN;
|
||||
}
|
||||
memop |= mo_endian(ctx);
|
||||
|
||||
decode_save_opc(ctx, 0);
|
||||
addr = get_address(ctx, a->rs1, a->imm);
|
||||
|
|
|
|||
|
|
@ -43,11 +43,12 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a)
|
|||
{
|
||||
TCGv_i64 dest;
|
||||
TCGv addr;
|
||||
MemOp memop = MO_TEUL;
|
||||
MemOp memop = MO_UL;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
if (ctx->cfg_ptr->ext_zama16b) {
|
||||
memop |= MO_ATOM_WITHIN16;
|
||||
}
|
||||
|
|
@ -65,11 +66,12 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a)
|
|||
static bool trans_fsw(DisasContext *ctx, arg_fsw *a)
|
||||
{
|
||||
TCGv addr;
|
||||
MemOp memop = MO_TEUL;
|
||||
MemOp memop = MO_UL;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
if (ctx->cfg_ptr->ext_zama16b) {
|
||||
memop |= MO_ATOM_WITHIN16;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -402,6 +402,7 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
|
|||
{
|
||||
bool out;
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
if (ctx->cfg_ptr->ext_zama16b) {
|
||||
memop |= MO_ATOM_WITHIN16;
|
||||
}
|
||||
|
|
@ -426,24 +427,24 @@ static bool trans_lb(DisasContext *ctx, arg_lb *a)
|
|||
|
||||
static bool trans_lh(DisasContext *ctx, arg_lh *a)
|
||||
{
|
||||
return gen_load(ctx, a, MO_TESW);
|
||||
return gen_load(ctx, a, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_lw(DisasContext *ctx, arg_lw *a)
|
||||
{
|
||||
return gen_load(ctx, a, MO_TESL);
|
||||
return gen_load(ctx, a, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_ld(DisasContext *ctx, arg_ld *a)
|
||||
{
|
||||
REQUIRE_64_OR_128BIT(ctx);
|
||||
return gen_load(ctx, a, MO_TESQ);
|
||||
return gen_load(ctx, a, MO_SQ);
|
||||
}
|
||||
|
||||
static bool trans_lq(DisasContext *ctx, arg_lq *a)
|
||||
{
|
||||
REQUIRE_128BIT(ctx);
|
||||
return gen_load(ctx, a, MO_TEUO);
|
||||
return gen_load(ctx, a, MO_UO);
|
||||
}
|
||||
|
||||
static bool trans_lbu(DisasContext *ctx, arg_lbu *a)
|
||||
|
|
@ -453,19 +454,19 @@ static bool trans_lbu(DisasContext *ctx, arg_lbu *a)
|
|||
|
||||
static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
|
||||
{
|
||||
return gen_load(ctx, a, MO_TEUW);
|
||||
return gen_load(ctx, a, MO_UW);
|
||||
}
|
||||
|
||||
static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
|
||||
{
|
||||
REQUIRE_64_OR_128BIT(ctx);
|
||||
return gen_load(ctx, a, MO_TEUL);
|
||||
return gen_load(ctx, a, MO_UL);
|
||||
}
|
||||
|
||||
static bool trans_ldu(DisasContext *ctx, arg_ldu *a)
|
||||
{
|
||||
REQUIRE_128BIT(ctx);
|
||||
return gen_load(ctx, a, MO_TEUQ);
|
||||
return gen_load(ctx, a, MO_UQ);
|
||||
}
|
||||
|
||||
static bool gen_store_tl(DisasContext *ctx, arg_sb *a, MemOp memop)
|
||||
|
|
@ -503,6 +504,7 @@ static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop)
|
|||
|
||||
static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
|
||||
{
|
||||
memop |= mo_endian(ctx);
|
||||
if (ctx->cfg_ptr->ext_zama16b) {
|
||||
memop |= MO_ATOM_WITHIN16;
|
||||
}
|
||||
|
|
@ -521,24 +523,24 @@ static bool trans_sb(DisasContext *ctx, arg_sb *a)
|
|||
|
||||
static bool trans_sh(DisasContext *ctx, arg_sh *a)
|
||||
{
|
||||
return gen_store(ctx, a, MO_TESW);
|
||||
return gen_store(ctx, a, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_sw(DisasContext *ctx, arg_sw *a)
|
||||
{
|
||||
return gen_store(ctx, a, MO_TESL);
|
||||
return gen_store(ctx, a, MO_SL);
|
||||
}
|
||||
|
||||
static bool trans_sd(DisasContext *ctx, arg_sd *a)
|
||||
{
|
||||
REQUIRE_64_OR_128BIT(ctx);
|
||||
return gen_store(ctx, a, MO_TEUQ);
|
||||
return gen_store(ctx, a, MO_UQ);
|
||||
}
|
||||
|
||||
static bool trans_sq(DisasContext *ctx, arg_sq *a)
|
||||
{
|
||||
REQUIRE_128BIT(ctx);
|
||||
return gen_store(ctx, a, MO_TEUO);
|
||||
return gen_store(ctx, a, MO_UO);
|
||||
}
|
||||
|
||||
static bool trans_addd(DisasContext *ctx, arg_addd *a)
|
||||
|
|
|
|||
|
|
@ -79,55 +79,55 @@ static bool trans_amomaxu_b(DisasContext *ctx, arg_amomaxu_b *a)
|
|||
static bool trans_amoswap_h(DisasContext *ctx, arg_amoswap_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amoadd_h(DisasContext *ctx, arg_amoadd_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amoxor_h(DisasContext *ctx, arg_amoxor_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amoand_h(DisasContext *ctx, arg_amoand_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amoor_h(DisasContext *ctx, arg_amoor_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amomin_h(DisasContext *ctx, arg_amomin_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amomax_h(DisasContext *ctx, arg_amomax_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amominu_h(DisasContext *ctx, arg_amominu_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amomaxu_h(DisasContext *ctx, arg_amomaxu_h *a)
|
||||
{
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TESW);
|
||||
return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_amocas_b(DisasContext *ctx, arg_amocas_b *a)
|
||||
|
|
@ -141,5 +141,5 @@ static bool trans_amocas_h(DisasContext *ctx, arg_amocas_h *a)
|
|||
{
|
||||
REQUIRE_ZACAS(ctx);
|
||||
REQUIRE_ZABHA(ctx);
|
||||
return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESW);
|
||||
return gen_cmpxchg(ctx, a, MO_ALIGN | MO_SW);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a)
|
||||
{
|
||||
REQUIRE_ZACAS(ctx);
|
||||
return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESL);
|
||||
return gen_cmpxchg(ctx, a, MO_ALIGN | MO_SL);
|
||||
}
|
||||
|
||||
static TCGv_i64 get_gpr_pair(DisasContext *ctx, int reg_num)
|
||||
|
|
@ -76,6 +76,7 @@ static bool gen_cmpxchg64(DisasContext *ctx, arg_atomic *a, MemOp mop)
|
|||
TCGv src1 = get_address(ctx, a->rs1, 0);
|
||||
TCGv_i64 src2 = get_gpr_pair(ctx, a->rs2);
|
||||
|
||||
mop |= mo_endian(ctx);
|
||||
decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
|
||||
tcg_gen_atomic_cmpxchg_i64(dest, src1, dest, src2, ctx->mem_idx, mop);
|
||||
|
||||
|
|
@ -88,10 +89,10 @@ static bool trans_amocas_d(DisasContext *ctx, arg_amocas_d *a)
|
|||
REQUIRE_ZACAS(ctx);
|
||||
switch (get_ol(ctx)) {
|
||||
case MXL_RV32:
|
||||
return gen_cmpxchg64(ctx, a, MO_ALIGN | MO_TEUQ);
|
||||
return gen_cmpxchg64(ctx, a, MO_ALIGN | MO_UQ);
|
||||
case MXL_RV64:
|
||||
case MXL_RV128:
|
||||
return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TEUQ);
|
||||
return gen_cmpxchg(ctx, a, MO_ALIGN | MO_UQ);
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
|
@ -118,12 +119,13 @@ static bool trans_amocas_q(DisasContext *ctx, arg_amocas_q *a)
|
|||
TCGv_i64 src2h = get_gpr(ctx, a->rs2 == 0 ? 0 : a->rs2 + 1, EXT_NONE);
|
||||
TCGv_i64 destl = get_gpr(ctx, a->rd, EXT_NONE);
|
||||
TCGv_i64 desth = get_gpr(ctx, a->rd == 0 ? 0 : a->rd + 1, EXT_NONE);
|
||||
MemOp memop = MO_ALIGN | MO_UO;
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_concat_i64_i128(src2, src2l, src2h);
|
||||
tcg_gen_concat_i64_i128(dest, destl, desth);
|
||||
decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
|
||||
tcg_gen_atomic_cmpxchg_i128(dest, src1, dest, src2, ctx->mem_idx,
|
||||
(MO_ALIGN | MO_TEUO));
|
||||
tcg_gen_atomic_cmpxchg_i128(dest, src1, dest, src2, ctx->mem_idx, memop);
|
||||
|
||||
tcg_gen_extr_i128_i64(destl, desth, dest);
|
||||
|
||||
|
|
|
|||
|
|
@ -88,13 +88,13 @@ static bool trans_c_lbu(DisasContext *ctx, arg_c_lbu *a)
|
|||
static bool trans_c_lhu(DisasContext *ctx, arg_c_lhu *a)
|
||||
{
|
||||
REQUIRE_ZCB(ctx);
|
||||
return gen_load(ctx, a, MO_TEUW);
|
||||
return gen_load(ctx, a, MO_UW);
|
||||
}
|
||||
|
||||
static bool trans_c_lh(DisasContext *ctx, arg_c_lh *a)
|
||||
{
|
||||
REQUIRE_ZCB(ctx);
|
||||
return gen_load(ctx, a, MO_TESW);
|
||||
return gen_load(ctx, a, MO_SW);
|
||||
}
|
||||
|
||||
static bool trans_c_sb(DisasContext *ctx, arg_c_sb *a)
|
||||
|
|
@ -106,7 +106,7 @@ static bool trans_c_sb(DisasContext *ctx, arg_c_sb *a)
|
|||
static bool trans_c_sh(DisasContext *ctx, arg_c_sh *a)
|
||||
{
|
||||
REQUIRE_ZCB(ctx);
|
||||
return gen_store(ctx, a, MO_TEUW);
|
||||
return gen_store(ctx, a, MO_UW);
|
||||
}
|
||||
|
||||
#define X_S0 8
|
||||
|
|
@ -175,7 +175,7 @@ static bool gen_pop(DisasContext *ctx, arg_cmpp *a, bool ret, bool ret_val)
|
|||
return false;
|
||||
}
|
||||
|
||||
MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_TEUL : MO_TEUQ;
|
||||
MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_UL : MO_UQ;
|
||||
int reg_size = memop_size(memop);
|
||||
target_ulong stack_adj = ROUND_UP(ctpop32(reg_bitmap) * reg_size, 16) +
|
||||
a->spimm;
|
||||
|
|
@ -185,6 +185,7 @@ static bool gen_pop(DisasContext *ctx, arg_cmpp *a, bool ret, bool ret_val)
|
|||
|
||||
tcg_gen_addi_tl(addr, sp, stack_adj - reg_size);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
for (i = X_Sn + 11; i >= 0; i--) {
|
||||
if (reg_bitmap & (1 << i)) {
|
||||
TCGv dest = dest_gpr(ctx, i);
|
||||
|
|
@ -228,7 +229,7 @@ static bool trans_cm_push(DisasContext *ctx, arg_cm_push *a)
|
|||
return false;
|
||||
}
|
||||
|
||||
MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_TEUL : MO_TEUQ;
|
||||
MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_UL : MO_UQ;
|
||||
int reg_size = memop_size(memop);
|
||||
target_ulong stack_adj = ROUND_UP(ctpop32(reg_bitmap) * reg_size, 16) +
|
||||
a->spimm;
|
||||
|
|
@ -238,6 +239,7 @@ static bool trans_cm_push(DisasContext *ctx, arg_cm_push *a)
|
|||
|
||||
tcg_gen_subi_tl(addr, sp, reg_size);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
for (i = X_Sn + 11; i >= 0; i--) {
|
||||
if (reg_bitmap & (1 << i)) {
|
||||
TCGv val = get_gpr(ctx, i, EXT_NONE);
|
||||
|
|
|
|||
|
|
@ -42,12 +42,14 @@
|
|||
|
||||
static bool trans_flh(DisasContext *ctx, arg_flh *a)
|
||||
{
|
||||
MemOp memop = MO_UW;
|
||||
TCGv_i64 dest;
|
||||
TCGv t0;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
decode_save_opc(ctx, 0);
|
||||
t0 = get_gpr(ctx, a->rs1, EXT_NONE);
|
||||
if (a->imm) {
|
||||
|
|
@ -57,7 +59,7 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a)
|
|||
}
|
||||
|
||||
dest = cpu_fpr[a->rd];
|
||||
tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, MO_TEUW);
|
||||
tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, memop);
|
||||
gen_nanbox_h(dest, dest);
|
||||
|
||||
mark_fs_dirty(ctx);
|
||||
|
|
@ -66,11 +68,13 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a)
|
|||
|
||||
static bool trans_fsh(DisasContext *ctx, arg_fsh *a)
|
||||
{
|
||||
MemOp memop = MO_UW;
|
||||
TCGv t0;
|
||||
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
decode_save_opc(ctx, 0);
|
||||
t0 = get_gpr(ctx, a->rs1, EXT_NONE);
|
||||
if (a->imm) {
|
||||
|
|
@ -79,7 +83,7 @@ static bool trans_fsh(DisasContext *ctx, arg_fsh *a)
|
|||
t0 = temp;
|
||||
}
|
||||
|
||||
tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUW);
|
||||
tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, memop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,12 +100,13 @@ static bool trans_ssamoswap_w(DisasContext *ctx, arg_amoswap_w *a)
|
|||
|
||||
TCGv dest = dest_gpr(ctx, a->rd);
|
||||
TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
|
||||
MemOp memop = MO_ALIGN | MO_SL;
|
||||
|
||||
decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
|
||||
src1 = get_address(ctx, a->rs1, 0);
|
||||
|
||||
tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx),
|
||||
(MO_ALIGN | MO_TESL));
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), memop);
|
||||
gen_set_gpr(ctx, a->rd, dest);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -129,12 +130,13 @@ static bool trans_ssamoswap_d(DisasContext *ctx, arg_amoswap_w *a)
|
|||
|
||||
TCGv dest = dest_gpr(ctx, a->rd);
|
||||
TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
|
||||
MemOp memop = MO_ALIGN | MO_SQ;
|
||||
|
||||
decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
|
||||
src1 = get_address(ctx, a->rs1, 0);
|
||||
|
||||
tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx),
|
||||
(MO_ALIGN | MO_TESQ));
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), memop);
|
||||
gen_set_gpr(ctx, a->rd, dest);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -349,6 +349,7 @@ static bool gen_fload_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop,
|
|||
TCGv_i64 rd = cpu_fpr[a->rd];
|
||||
TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_qemu_ld_i64(rd, addr, ctx->mem_idx, memop);
|
||||
if ((memop & MO_SIZE) == MO_32) {
|
||||
gen_nanbox_s(rd, rd);
|
||||
|
|
@ -369,6 +370,7 @@ static bool gen_fstore_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop,
|
|||
TCGv_i64 rd = cpu_fpr[a->rd];
|
||||
TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_qemu_st_i64(rd, addr, ctx->mem_idx, memop);
|
||||
|
||||
return true;
|
||||
|
|
@ -379,7 +381,7 @@ static bool trans_th_flrd(DisasContext *ctx, arg_th_memidx *a)
|
|||
REQUIRE_XTHEADFMEMIDX(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
return gen_fload_idx(ctx, a, MO_TEUQ, false);
|
||||
return gen_fload_idx(ctx, a, MO_UQ, false);
|
||||
}
|
||||
|
||||
static bool trans_th_flrw(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -387,7 +389,7 @@ static bool trans_th_flrw(DisasContext *ctx, arg_th_memidx *a)
|
|||
REQUIRE_XTHEADFMEMIDX(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
return gen_fload_idx(ctx, a, MO_TEUL, false);
|
||||
return gen_fload_idx(ctx, a, MO_UL, false);
|
||||
}
|
||||
|
||||
static bool trans_th_flurd(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -395,7 +397,7 @@ static bool trans_th_flurd(DisasContext *ctx, arg_th_memidx *a)
|
|||
REQUIRE_XTHEADFMEMIDX(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
return gen_fload_idx(ctx, a, MO_TEUQ, true);
|
||||
return gen_fload_idx(ctx, a, MO_UQ, true);
|
||||
}
|
||||
|
||||
static bool trans_th_flurw(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -403,7 +405,7 @@ static bool trans_th_flurw(DisasContext *ctx, arg_th_memidx *a)
|
|||
REQUIRE_XTHEADFMEMIDX(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
return gen_fload_idx(ctx, a, MO_TEUL, true);
|
||||
return gen_fload_idx(ctx, a, MO_UL, true);
|
||||
}
|
||||
|
||||
static bool trans_th_fsrd(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -411,7 +413,7 @@ static bool trans_th_fsrd(DisasContext *ctx, arg_th_memidx *a)
|
|||
REQUIRE_XTHEADFMEMIDX(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
return gen_fstore_idx(ctx, a, MO_TEUQ, false);
|
||||
return gen_fstore_idx(ctx, a, MO_UQ, false);
|
||||
}
|
||||
|
||||
static bool trans_th_fsrw(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -419,7 +421,7 @@ static bool trans_th_fsrw(DisasContext *ctx, arg_th_memidx *a)
|
|||
REQUIRE_XTHEADFMEMIDX(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
return gen_fstore_idx(ctx, a, MO_TEUL, false);
|
||||
return gen_fstore_idx(ctx, a, MO_UL, false);
|
||||
}
|
||||
|
||||
static bool trans_th_fsurd(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -427,7 +429,7 @@ static bool trans_th_fsurd(DisasContext *ctx, arg_th_memidx *a)
|
|||
REQUIRE_XTHEADFMEMIDX(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVD);
|
||||
return gen_fstore_idx(ctx, a, MO_TEUQ, true);
|
||||
return gen_fstore_idx(ctx, a, MO_UQ, true);
|
||||
}
|
||||
|
||||
static bool trans_th_fsurw(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -435,7 +437,7 @@ static bool trans_th_fsurw(DisasContext *ctx, arg_th_memidx *a)
|
|||
REQUIRE_XTHEADFMEMIDX(ctx);
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_EXT(ctx, RVF);
|
||||
return gen_fstore_idx(ctx, a, MO_TEUL, true);
|
||||
return gen_fstore_idx(ctx, a, MO_UL, true);
|
||||
}
|
||||
|
||||
/* XTheadFmv */
|
||||
|
|
@ -568,6 +570,7 @@ static bool gen_load_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop,
|
|||
TCGv rd = dest_gpr(ctx, a->rd);
|
||||
TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
|
||||
tcg_gen_addi_tl(rs1, rs1, imm);
|
||||
gen_set_gpr(ctx, a->rd, rd);
|
||||
|
|
@ -588,6 +591,7 @@ static bool gen_store_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop,
|
|||
TCGv data = get_gpr(ctx, a->rd, EXT_NONE);
|
||||
TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop);
|
||||
tcg_gen_addi_tl(rs1, rs1, imm);
|
||||
gen_set_gpr(ctx, a->rs1, rs1);
|
||||
|
|
@ -598,64 +602,64 @@ static bool trans_th_ldia(DisasContext *ctx, arg_th_meminc *a)
|
|||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TESQ, false);
|
||||
return gen_load_inc(ctx, a, MO_SQ, false);
|
||||
}
|
||||
|
||||
static bool trans_th_ldib(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TESQ, true);
|
||||
return gen_load_inc(ctx, a, MO_SQ, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lwia(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TESL, false);
|
||||
return gen_load_inc(ctx, a, MO_SL, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lwib(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TESL, true);
|
||||
return gen_load_inc(ctx, a, MO_SL, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lwuia(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TEUL, false);
|
||||
return gen_load_inc(ctx, a, MO_UL, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lwuib(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TEUL, true);
|
||||
return gen_load_inc(ctx, a, MO_UL, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lhia(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TESW, false);
|
||||
return gen_load_inc(ctx, a, MO_SW, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lhib(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TESW, true);
|
||||
return gen_load_inc(ctx, a, MO_SW, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lhuia(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TEUW, false);
|
||||
return gen_load_inc(ctx, a, MO_UW, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lhuib(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_inc(ctx, a, MO_TEUW, true);
|
||||
return gen_load_inc(ctx, a, MO_UW, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lbia(DisasContext *ctx, arg_th_meminc *a)
|
||||
|
|
@ -686,38 +690,38 @@ static bool trans_th_sdia(DisasContext *ctx, arg_th_meminc *a)
|
|||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_store_inc(ctx, a, MO_TESQ, false);
|
||||
return gen_store_inc(ctx, a, MO_SQ, false);
|
||||
}
|
||||
|
||||
static bool trans_th_sdib(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_store_inc(ctx, a, MO_TESQ, true);
|
||||
return gen_store_inc(ctx, a, MO_SQ, true);
|
||||
}
|
||||
|
||||
static bool trans_th_swia(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_store_inc(ctx, a, MO_TESL, false);
|
||||
return gen_store_inc(ctx, a, MO_SL, false);
|
||||
}
|
||||
|
||||
static bool trans_th_swib(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_store_inc(ctx, a, MO_TESL, true);
|
||||
return gen_store_inc(ctx, a, MO_SL, true);
|
||||
}
|
||||
|
||||
static bool trans_th_shia(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_store_inc(ctx, a, MO_TESW, false);
|
||||
return gen_store_inc(ctx, a, MO_SW, false);
|
||||
}
|
||||
|
||||
static bool trans_th_shib(DisasContext *ctx, arg_th_meminc *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_store_inc(ctx, a, MO_TESW, true);
|
||||
return gen_store_inc(ctx, a, MO_SW, true);
|
||||
}
|
||||
|
||||
static bool trans_th_sbia(DisasContext *ctx, arg_th_meminc *a)
|
||||
|
|
@ -743,6 +747,7 @@ static bool gen_load_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop,
|
|||
TCGv rd = dest_gpr(ctx, a->rd);
|
||||
TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop);
|
||||
gen_set_gpr(ctx, a->rd, rd);
|
||||
|
||||
|
|
@ -760,6 +765,7 @@ static bool gen_store_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop,
|
|||
TCGv data = get_gpr(ctx, a->rd, EXT_NONE);
|
||||
TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop);
|
||||
|
||||
return true;
|
||||
|
|
@ -769,32 +775,32 @@ static bool trans_th_lrd(DisasContext *ctx, arg_th_memidx *a)
|
|||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TESQ, false);
|
||||
return gen_load_idx(ctx, a, MO_SQ, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lrw(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TESL, false);
|
||||
return gen_load_idx(ctx, a, MO_SL, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lrwu(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TEUL, false);
|
||||
return gen_load_idx(ctx, a, MO_UL, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lrh(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TESW, false);
|
||||
return gen_load_idx(ctx, a, MO_SW, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lrhu(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TEUW, false);
|
||||
return gen_load_idx(ctx, a, MO_UW, false);
|
||||
}
|
||||
|
||||
static bool trans_th_lrb(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -813,19 +819,19 @@ static bool trans_th_srd(DisasContext *ctx, arg_th_memidx *a)
|
|||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_store_idx(ctx, a, MO_TESQ, false);
|
||||
return gen_store_idx(ctx, a, MO_SQ, false);
|
||||
}
|
||||
|
||||
static bool trans_th_srw(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_store_idx(ctx, a, MO_TESL, false);
|
||||
return gen_store_idx(ctx, a, MO_SL, false);
|
||||
}
|
||||
|
||||
static bool trans_th_srh(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_store_idx(ctx, a, MO_TESW, false);
|
||||
return gen_store_idx(ctx, a, MO_SW, false);
|
||||
}
|
||||
|
||||
static bool trans_th_srb(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -837,32 +843,32 @@ static bool trans_th_lurd(DisasContext *ctx, arg_th_memidx *a)
|
|||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TESQ, true);
|
||||
return gen_load_idx(ctx, a, MO_SQ, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lurw(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TESL, true);
|
||||
return gen_load_idx(ctx, a, MO_SL, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lurwu(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TEUL, true);
|
||||
return gen_load_idx(ctx, a, MO_UL, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lurh(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TESW, true);
|
||||
return gen_load_idx(ctx, a, MO_SW, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lurhu(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_load_idx(ctx, a, MO_TEUW, true);
|
||||
return gen_load_idx(ctx, a, MO_UW, true);
|
||||
}
|
||||
|
||||
static bool trans_th_lurb(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -881,19 +887,19 @@ static bool trans_th_surd(DisasContext *ctx, arg_th_memidx *a)
|
|||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_store_idx(ctx, a, MO_TESQ, true);
|
||||
return gen_store_idx(ctx, a, MO_SQ, true);
|
||||
}
|
||||
|
||||
static bool trans_th_surw(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_store_idx(ctx, a, MO_TESL, true);
|
||||
return gen_store_idx(ctx, a, MO_SL, true);
|
||||
}
|
||||
|
||||
static bool trans_th_surh(DisasContext *ctx, arg_th_memidx *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMIDX(ctx);
|
||||
return gen_store_idx(ctx, a, MO_TESW, true);
|
||||
return gen_store_idx(ctx, a, MO_SW, true);
|
||||
}
|
||||
|
||||
static bool trans_th_surb(DisasContext *ctx, arg_th_memidx *a)
|
||||
|
|
@ -920,6 +926,7 @@ static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
|
|||
addr1 = get_address(ctx, a->rs, imm);
|
||||
addr2 = get_address(ctx, a->rs, memop_size(memop) + imm);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_qemu_ld_tl(t1, addr1, ctx->mem_idx, memop);
|
||||
tcg_gen_qemu_ld_tl(t2, addr2, ctx->mem_idx, memop);
|
||||
gen_set_gpr(ctx, a->rd1, t1);
|
||||
|
|
@ -931,19 +938,19 @@ static bool trans_th_ldd(DisasContext *ctx, arg_th_pair *a)
|
|||
{
|
||||
REQUIRE_XTHEADMEMPAIR(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_loadpair_tl(ctx, a, MO_TESQ, 4);
|
||||
return gen_loadpair_tl(ctx, a, MO_SQ, 4);
|
||||
}
|
||||
|
||||
static bool trans_th_lwd(DisasContext *ctx, arg_th_pair *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMPAIR(ctx);
|
||||
return gen_loadpair_tl(ctx, a, MO_TESL, 3);
|
||||
return gen_loadpair_tl(ctx, a, MO_SL, 3);
|
||||
}
|
||||
|
||||
static bool trans_th_lwud(DisasContext *ctx, arg_th_pair *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMPAIR(ctx);
|
||||
return gen_loadpair_tl(ctx, a, MO_TEUL, 3);
|
||||
return gen_loadpair_tl(ctx, a, MO_UL, 3);
|
||||
}
|
||||
|
||||
static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
|
||||
|
|
@ -958,6 +965,7 @@ static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
|
|||
addr1 = get_address(ctx, a->rs, imm);
|
||||
addr2 = get_address(ctx, a->rs, memop_size(memop) + imm);
|
||||
|
||||
memop |= mo_endian(ctx);
|
||||
tcg_gen_qemu_st_tl(data1, addr1, ctx->mem_idx, memop);
|
||||
tcg_gen_qemu_st_tl(data2, addr2, ctx->mem_idx, memop);
|
||||
return true;
|
||||
|
|
@ -967,13 +975,13 @@ static bool trans_th_sdd(DisasContext *ctx, arg_th_pair *a)
|
|||
{
|
||||
REQUIRE_XTHEADMEMPAIR(ctx);
|
||||
REQUIRE_64BIT(ctx);
|
||||
return gen_storepair_tl(ctx, a, MO_TESQ, 4);
|
||||
return gen_storepair_tl(ctx, a, MO_SQ, 4);
|
||||
}
|
||||
|
||||
static bool trans_th_swd(DisasContext *ctx, arg_th_pair *a)
|
||||
{
|
||||
REQUIRE_XTHEADMEMPAIR(ctx);
|
||||
return gen_storepair_tl(ctx, a, MO_TESL, 3);
|
||||
return gen_storepair_tl(ctx, a, MO_SL, 3);
|
||||
}
|
||||
|
||||
/* XTheadSync */
|
||||
|
|
|
|||
|
|
@ -705,6 +705,7 @@ static void kvm_riscv_reset_regs_csr(CPURISCVState *env)
|
|||
env->satp = 0;
|
||||
env->scounteren = 0;
|
||||
env->senvcfg = 0;
|
||||
env->priv = PRV_S;
|
||||
}
|
||||
|
||||
static int kvm_riscv_get_regs_fp(CPUState *cs)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,20 @@
|
|||
#include "exec/tlb-flags.h"
|
||||
#include "trace.h"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static inline MemOp mo_endian_env(CPURISCVState *env)
|
||||
{
|
||||
/*
|
||||
* A couple of bits in MSTATUS set the endianness:
|
||||
* - MSTATUS_UBE (User-mode),
|
||||
* - MSTATUS_SBE (Supervisor-mode),
|
||||
* - MSTATUS_MBE (Machine-mode)
|
||||
* but we don't implement that yet.
|
||||
*/
|
||||
return MO_TE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Exceptions processing helpers */
|
||||
G_NORETURN void riscv_raise_exception(CPURISCVState *env,
|
||||
RISCVException exception,
|
||||
|
|
@ -633,7 +647,7 @@ target_ulong helper_hyp_hlv_hu(CPURISCVState *env, target_ulong addr)
|
|||
{
|
||||
uintptr_t ra = GETPC();
|
||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
|
||||
MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UW, mmu_idx);
|
||||
|
||||
return cpu_ldw_mmu(env, adjust_addr_virt(env, addr), oi, ra);
|
||||
}
|
||||
|
|
@ -642,7 +656,7 @@ target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr)
|
|||
{
|
||||
uintptr_t ra = GETPC();
|
||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
|
||||
MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UL, mmu_idx);
|
||||
|
||||
return cpu_ldl_mmu(env, adjust_addr_virt(env, addr), oi, ra);
|
||||
}
|
||||
|
|
@ -651,7 +665,7 @@ target_ulong helper_hyp_hlv_d(CPURISCVState *env, target_ulong addr)
|
|||
{
|
||||
uintptr_t ra = GETPC();
|
||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
|
||||
MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UQ, mmu_idx);
|
||||
|
||||
return cpu_ldq_mmu(env, adjust_addr_virt(env, addr), oi, ra);
|
||||
}
|
||||
|
|
@ -669,7 +683,7 @@ void helper_hyp_hsv_h(CPURISCVState *env, target_ulong addr, target_ulong val)
|
|||
{
|
||||
uintptr_t ra = GETPC();
|
||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
|
||||
MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UW, mmu_idx);
|
||||
|
||||
cpu_stw_mmu(env, adjust_addr_virt(env, addr), val, oi, ra);
|
||||
}
|
||||
|
|
@ -678,7 +692,7 @@ void helper_hyp_hsv_w(CPURISCVState *env, target_ulong addr, target_ulong val)
|
|||
{
|
||||
uintptr_t ra = GETPC();
|
||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
|
||||
MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UL, mmu_idx);
|
||||
|
||||
cpu_stl_mmu(env, adjust_addr_virt(env, addr), val, oi, ra);
|
||||
}
|
||||
|
|
@ -687,7 +701,7 @@ void helper_hyp_hsv_d(CPURISCVState *env, target_ulong addr, target_ulong val)
|
|||
{
|
||||
uintptr_t ra = GETPC();
|
||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
|
||||
MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UQ, mmu_idx);
|
||||
|
||||
cpu_stq_mmu(env, adjust_addr_virt(env, addr), val, oi, ra);
|
||||
}
|
||||
|
|
@ -703,7 +717,7 @@ target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong addr)
|
|||
{
|
||||
uintptr_t ra = GETPC();
|
||||
int mmu_idx = check_access_hlsv(env, true, ra);
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
|
||||
MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UW, mmu_idx);
|
||||
|
||||
return cpu_ldw_code_mmu(env, addr, oi, GETPC());
|
||||
}
|
||||
|
|
@ -712,7 +726,7 @@ target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong addr)
|
|||
{
|
||||
uintptr_t ra = GETPC();
|
||||
int mmu_idx = check_access_hlsv(env, true, ra);
|
||||
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
|
||||
MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UL, mmu_idx);
|
||||
|
||||
return cpu_ldl_code_mmu(env, addr, oi, ra);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,17 @@ static int pmp_is_invalid_smepmp_cfg(CPURISCVState *env, uint8_t val)
|
|||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Calculate PMP granularity value 'g'
|
||||
*
|
||||
* The granularity value 'g' is defined as log2(granularity) - 2, where
|
||||
* granularity is the minimum alignment requirement for PMP regions in bytes.
|
||||
*/
|
||||
static inline int pmp_get_granularity_g(CPURISCVState *env)
|
||||
{
|
||||
return __builtin_ctz(riscv_cpu_cfg(env)->pmp_granularity >> 2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Count the number of active rules.
|
||||
|
|
@ -153,6 +164,15 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
|
|||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"ignoring pmpcfg write - invalid\n");
|
||||
} else {
|
||||
uint8_t a_field = pmp_get_a_field(val);
|
||||
/*
|
||||
* When granularity g >= 1 (i.e., granularity > 4 bytes),
|
||||
* the NA4 (Naturally Aligned 4-byte) mode is not selectable
|
||||
*/
|
||||
if ((riscv_cpu_cfg(env)->pmp_granularity >
|
||||
MIN_RISCV_PMP_GRANULARITY) && (a_field == PMP_AMATCH_NA4)) {
|
||||
return false;
|
||||
}
|
||||
env->pmp_state.pmp[pmp_index].cfg_reg = val;
|
||||
pmp_update_rule_addr(env, pmp_index);
|
||||
return true;
|
||||
|
|
@ -199,6 +219,7 @@ void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index)
|
|||
target_ulong prev_addr = 0u;
|
||||
hwaddr sa = 0u;
|
||||
hwaddr ea = 0u;
|
||||
int g = pmp_get_granularity_g(env);
|
||||
|
||||
if (pmp_index >= 1u) {
|
||||
prev_addr = env->pmp_state.pmp[pmp_index - 1].addr_reg;
|
||||
|
|
@ -211,6 +232,11 @@ void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index)
|
|||
break;
|
||||
|
||||
case PMP_AMATCH_TOR:
|
||||
/* Bits pmpaddr[G-1:0] do not affect the TOR address-matching logic. */
|
||||
if (g >= 1) {
|
||||
prev_addr &= ~((1ULL << g) - 1ULL);
|
||||
this_addr &= ~((1ULL << g) - 1ULL);
|
||||
}
|
||||
if (prev_addr >= this_addr) {
|
||||
sa = ea = 0u;
|
||||
break;
|
||||
|
|
@ -577,6 +603,7 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
|
|||
|
||||
/*
|
||||
* Handle a read from a pmpaddr CSR
|
||||
* Change A field of pmpcfg affects the read value of pmpaddr
|
||||
*/
|
||||
target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index)
|
||||
{
|
||||
|
|
@ -585,6 +612,25 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index)
|
|||
|
||||
if (addr_index < pmp_regions) {
|
||||
val = env->pmp_state.pmp[addr_index].addr_reg;
|
||||
int g = pmp_get_granularity_g(env);
|
||||
switch (pmp_get_a_field(env->pmp_state.pmp[addr_index].cfg_reg)) {
|
||||
case PMP_AMATCH_OFF:
|
||||
/* fallthrough */
|
||||
case PMP_AMATCH_TOR:
|
||||
/* Bit [g-1:0] read all zero */
|
||||
if (g >= 1 && g < TARGET_LONG_BITS) {
|
||||
val &= ~((1ULL << g) - 1ULL);
|
||||
}
|
||||
break;
|
||||
case PMP_AMATCH_NAPOT:
|
||||
/* Bit [g-2:0] read all one */
|
||||
if (g >= 2 && g < TARGET_LONG_BITS) {
|
||||
val |= ((1ULL << (g - 1)) - 1ULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
trace_pmpaddr_csr_read(env->mhartid, addr_index, val);
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
|
|
|
|||
|
|
@ -273,12 +273,13 @@ static bool reg_is_ulong_integer(CPURISCVState *env, const char *name,
|
|||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
g_autofree char *reg_name = g_strdup(reg_names[i]);
|
||||
char *reg1 = strtok(reg_name, "/");
|
||||
char *reg2 = strtok(NULL, "/");
|
||||
g_auto(GStrv) reg_name = g_strsplit(reg_names[i], "/", 2);
|
||||
|
||||
if (strcasecmp(reg1, name) == 0 ||
|
||||
(reg2 && strcasecmp(reg2, name) == 0)) {
|
||||
g_assert(reg_name[0]);
|
||||
g_assert(reg_name[1]);
|
||||
|
||||
if (g_ascii_strcasecmp(reg_name[0], name) == 0 ||
|
||||
g_ascii_strcasecmp(reg_name[1], name) == 0) {
|
||||
*val = vals[i];
|
||||
return true;
|
||||
}
|
||||
|
|
@ -294,12 +295,13 @@ static bool reg_is_u64_fpu(CPURISCVState *env, const char *name, uint64_t *val)
|
|||
}
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
g_autofree char *reg_name = g_strdup(riscv_fpr_regnames[i]);
|
||||
char *reg1 = strtok(reg_name, "/");
|
||||
char *reg2 = strtok(NULL, "/");
|
||||
g_auto(GStrv) reg_name = g_strsplit(riscv_fpr_regnames[i], "/", 2);
|
||||
|
||||
if (strcasecmp(reg1, name) == 0 ||
|
||||
(reg2 && strcasecmp(reg2, name) == 0)) {
|
||||
g_assert(reg_name[0]);
|
||||
g_assert(reg_name[1]);
|
||||
|
||||
if (g_ascii_strcasecmp(reg_name[0], name) == 0 ||
|
||||
g_ascii_strcasecmp(reg_name[1], name) == 0) {
|
||||
*val = env->fpr[i];
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -426,6 +426,8 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
|
|||
min_vlen = 64;
|
||||
} else if (cfg->ext_zve32x) {
|
||||
min_vlen = 32;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vlen > RV_VLEN_MAX || vlen < min_vlen) {
|
||||
|
|
@ -676,12 +678,10 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
if (cpu->cfg.ext_zve32x) {
|
||||
riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The Zve64d extension depends on the Zve64f extension */
|
||||
|
|
|
|||
|
|
@ -126,6 +126,18 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
|
|||
return ctx->misa_ext & ext;
|
||||
}
|
||||
|
||||
static inline MemOp mo_endian(DisasContext *ctx)
|
||||
{
|
||||
/*
|
||||
* A couple of bits in MSTATUS set the endianness:
|
||||
* - MSTATUS_UBE (User-mode),
|
||||
* - MSTATUS_SBE (Supervisor-mode),
|
||||
* - MSTATUS_MBE (Machine-mode)
|
||||
* but we don't implement that yet.
|
||||
*/
|
||||
return MO_TE;
|
||||
}
|
||||
|
||||
#ifdef TARGET_RISCV32
|
||||
#define get_xl(ctx) MXL_RV32
|
||||
#elif defined(CONFIG_USER_ONLY)
|
||||
|
|
@ -142,7 +154,7 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
|
|||
#define get_address_xl(ctx) ((ctx)->address_xl)
|
||||
#endif
|
||||
|
||||
#define mxl_memop(ctx) ((get_xl(ctx) + 1) | MO_TE)
|
||||
#define mxl_memop(ctx) ((get_xl(ctx) + 1) | mo_endian(ctx))
|
||||
|
||||
/* The word size for this machine mode. */
|
||||
static inline int __attribute__((unused)) get_xlen(DisasContext *ctx)
|
||||
|
|
@ -1135,6 +1147,7 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
|
|||
TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
|
||||
MemOp size = mop & MO_SIZE;
|
||||
|
||||
mop |= mo_endian(ctx);
|
||||
if (ctx->cfg_ptr->ext_zama16b && size >= MO_32) {
|
||||
mop |= MO_ATOM_WITHIN16;
|
||||
} else {
|
||||
|
|
@ -1155,6 +1168,7 @@ static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
|
|||
TCGv src1 = get_address(ctx, a->rs1, 0);
|
||||
TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
|
||||
|
||||
mop |= mo_endian(ctx);
|
||||
decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
|
||||
tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue