Third RISC-V PR for QEMU 6.2

- Add Zb[abcs] instruction support
  - Remove RVB support
  - Bug fix of setting mstatus_hs.[SD|FS] bits
  - Mark some UART devices as 'input'
  - QOMify PolarFire MMUART
  - Fixes for sifive PDMA
  - Mark shakti_c as not user creatable
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmFelu0ACgkQIeENKd+X
 cFQ1vQf/a0QNMv/q9shDX8IzX6zPKMHpdhgqqfqsdL3bPqjhXBbpZuSQOlq2UsPv
 6LwvEqvMq5Il8UHrFGaY87d08NWY+QMXNJml2oe8k5tU80DIR3Iv91Kz6RnGLsR9
 iaEFbYZNWax4lIFnW5h543EU4szOuNO+U+egJjvjQARIodbRjsfBMQJzlUHQ7Oqr
 2n44165IDUyah3QDXk25SSH1RXoeD1OjrbJ/NLFIY6LE7x9NJZm5GDQr3fIi3E5j
 CBBG116huejif9NmaI+xefzi696iZWrbJvhCD9nIlbYnwq4ENgjf4GPb7TEzVPWc
 t3yRrWVlUB4t9mD54ur+wPrCw9GXtA==
 =vnL1
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/alistair23/tags/pull-riscv-to-apply-20211007' into staging

Third RISC-V PR for QEMU 6.2

 - Add Zb[abcs] instruction support
 - Remove RVB support
 - Bug fix of setting mstatus_hs.[SD|FS] bits
 - Mark some UART devices as 'input'
 - QOMify PolarFire MMUART
 - Fixes for sifive PDMA
 - Mark shakti_c as not user creatable

# gpg: Signature made Wed 06 Oct 2021 11:42:53 PM PDT
# gpg:                using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [full]

* remotes/alistair23/tags/pull-riscv-to-apply-20211007: (26 commits)
  hw/riscv: shakti_c: Mark as not user creatable
  hw/dma: sifive_pdma: Don't run DMA when channel is disclaimed
  hw/dma: sifive_pdma: Fix Control.claim bit detection
  hw/char/mchp_pfsoc_mmuart: QOM'ify PolarFire MMUART
  hw/char/mchp_pfsoc_mmuart: Use a MemoryRegion container
  hw/char/mchp_pfsoc_mmuart: Simplify MCHP_PFSOC_MMUART_REG definition
  hw/char: sifive_uart: Register device in 'input' category
  hw/char: shakti_uart: Register device in 'input' category
  hw/char: ibex_uart: Register device in 'input' category
  target/riscv: Set mstatus_hs.[SD|FS] bits if Clean and V=1 in mark_fs_dirty()
  disas/riscv: Add Zb[abcs] instructions
  target/riscv: Remove RVB (replaced by Zb[abcs])
  target/riscv: Add zext.h instructions to Zbb, removing pack/packu/packh
  target/riscv: Add rev8 instruction, removing grev/grevi
  target/riscv: Add a REQUIRE_32BIT macro
  target/riscv: Add orc.b instruction for Zbb, removing gorc/gorci
  target/riscv: Reassign instructions to the Zbb-extension
  target/riscv: Add instructions of the Zbc-extension
  target/riscv: Reassign instructions to the Zbs-extension
  target/riscv: Remove shift-one instructions (proposed Zbo in pre-0.93 draft-B)
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-10-07 07:18:39 -07:00
commit 3c01933983
15 changed files with 524 additions and 487 deletions

View file

@ -478,6 +478,49 @@ typedef enum {
rv_op_fsflags = 316,
rv_op_fsrmi = 317,
rv_op_fsflagsi = 318,
rv_op_bseti = 319,
rv_op_bclri = 320,
rv_op_binvi = 321,
rv_op_bexti = 322,
rv_op_rori = 323,
rv_op_clz = 324,
rv_op_ctz = 325,
rv_op_cpop = 326,
rv_op_sext_h = 327,
rv_op_sext_b = 328,
rv_op_xnor = 329,
rv_op_orn = 330,
rv_op_andn = 331,
rv_op_rol = 332,
rv_op_ror = 333,
rv_op_sh1add = 334,
rv_op_sh2add = 335,
rv_op_sh3add = 336,
rv_op_sh1add_uw = 337,
rv_op_sh2add_uw = 338,
rv_op_sh3add_uw = 339,
rv_op_clmul = 340,
rv_op_clmulr = 341,
rv_op_clmulh = 342,
rv_op_min = 343,
rv_op_minu = 344,
rv_op_max = 345,
rv_op_maxu = 346,
rv_op_clzw = 347,
rv_op_ctzw = 348,
rv_op_cpopw = 349,
rv_op_slli_uw = 350,
rv_op_add_uw = 351,
rv_op_rolw = 352,
rv_op_rorw = 353,
rv_op_rev8 = 354,
rv_op_zext_h = 355,
rv_op_roriw = 356,
rv_op_orc_b = 357,
rv_op_bset = 358,
rv_op_bclr = 359,
rv_op_binv = 360,
rv_op_bext = 361,
} rv_op;
/* structures */
@ -1117,6 +1160,49 @@ const rv_opcode_data opcode_data[] = {
{ "fsflags", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "fsrmi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 },
{ "fsflagsi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 },
{ "bseti", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
{ "bclri", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
{ "binvi", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
{ "bexti", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
{ "rori", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
{ "clz", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "ctz", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "cpop", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "sext.h", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "sext.b", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "xnor", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "orn", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "andn", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "rol", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "ror", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "sh1add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "sh2add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "sh3add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "sh1add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "sh2add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "sh3add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "clmul", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "clmulr", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "clmulh", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "min", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "minu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "max", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "maxu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "slli.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "rolw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "rorw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "rev8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "zext.h", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "roriw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
{ "orc.b", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "bset", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "bclr", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "binv", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "bext", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
};
/* CSR names */
@ -1507,7 +1593,20 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
case 0: op = rv_op_addi; break;
case 1:
switch (((inst >> 27) & 0b11111)) {
case 0: op = rv_op_slli; break;
case 0b00000: op = rv_op_slli; break;
case 0b00101: op = rv_op_bseti; break;
case 0b01001: op = rv_op_bclri; break;
case 0b01101: op = rv_op_binvi; break;
case 0b01100:
switch (((inst >> 20) & 0b1111111)) {
case 0b0000000: op = rv_op_clz; break;
case 0b0000001: op = rv_op_ctz; break;
case 0b0000010: op = rv_op_cpop; break;
/* 0b0000011 */
case 0b0000100: op = rv_op_sext_b; break;
case 0b0000101: op = rv_op_sext_h; break;
}
break;
}
break;
case 2: op = rv_op_slti; break;
@ -1515,8 +1614,16 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
case 4: op = rv_op_xori; break;
case 5:
switch (((inst >> 27) & 0b11111)) {
case 0: op = rv_op_srli; break;
case 8: op = rv_op_srai; break;
case 0b00000: op = rv_op_srli; break;
case 0b00101: op = rv_op_orc_b; break;
case 0b01000: op = rv_op_srai; break;
case 0b01001: op = rv_op_bexti; break;
case 0b01100: op = rv_op_rori; break;
case 0b01101:
switch ((inst >> 20) & 0b1111111) {
case 0b0111000: op = rv_op_rev8; break;
}
break;
}
break;
case 6: op = rv_op_ori; break;
@ -1530,12 +1637,21 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
case 1:
switch (((inst >> 25) & 0b1111111)) {
case 0: op = rv_op_slliw; break;
case 4: op = rv_op_slli_uw; break;
case 48:
switch ((inst >> 20) & 0b11111) {
case 0b00000: op = rv_op_clzw; break;
case 0b00001: op = rv_op_ctzw; break;
case 0b00010: op = rv_op_cpopw; break;
}
break;
}
break;
case 5:
switch (((inst >> 25) & 0b1111111)) {
case 0: op = rv_op_srliw; break;
case 32: op = rv_op_sraiw; break;
case 48: op = rv_op_roriw; break;
}
break;
}
@ -1623,8 +1739,32 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
case 13: op = rv_op_divu; break;
case 14: op = rv_op_rem; break;
case 15: op = rv_op_remu; break;
case 36:
switch ((inst >> 20) & 0b11111) {
case 0: op = rv_op_zext_h; break;
}
break;
case 41: op = rv_op_clmul; break;
case 42: op = rv_op_clmulr; break;
case 43: op = rv_op_clmulh; break;
case 44: op = rv_op_min; break;
case 45: op = rv_op_minu; break;
case 46: op = rv_op_max; break;
case 47: op = rv_op_maxu; break;
case 130: op = rv_op_sh1add; break;
case 132: op = rv_op_sh2add; break;
case 134: op = rv_op_sh3add; break;
case 161: op = rv_op_bset; break;
case 256: op = rv_op_sub; break;
case 260: op = rv_op_xnor; break;
case 261: op = rv_op_sra; break;
case 262: op = rv_op_orn; break;
case 263: op = rv_op_andn; break;
case 289: op = rv_op_bclr; break;
case 293: op = rv_op_bext; break;
case 385: op = rv_op_rol; break;
case 386: op = rv_op_ror; break;
case 417: op = rv_op_binv; break;
}
break;
case 13: op = rv_op_lui; break;
@ -1638,8 +1778,19 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
case 13: op = rv_op_divuw; break;
case 14: op = rv_op_remw; break;
case 15: op = rv_op_remuw; break;
case 32: op = rv_op_add_uw; break;
case 36:
switch ((inst >> 20) & 0b11111) {
case 0: op = rv_op_zext_h; break;
}
break;
case 130: op = rv_op_sh1add_uw; break;
case 132: op = rv_op_sh2add_uw; break;
case 134: op = rv_op_sh3add_uw; break;
case 256: op = rv_op_subw; break;
case 261: op = rv_op_sraw; break;
case 385: op = rv_op_rolw; break;
case 389: op = rv_op_rorw; break;
}
break;
case 16:

View file

@ -550,6 +550,7 @@ static void ibex_uart_class_init(ObjectClass *klass, void *data)
dc->realize = ibex_uart_realize;
dc->vmsd = &vmstate_ibex_uart;
device_class_set_props(dc, ibex_uart_properties);
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo ibex_uart_info = {

View file

@ -22,20 +22,25 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "chardev/char.h"
#include "qapi/error.h"
#include "migration/vmstate.h"
#include "hw/char/mchp_pfsoc_mmuart.h"
#include "hw/qdev-properties.h"
#define REGS_OFFSET 0x20
static uint64_t mchp_pfsoc_mmuart_read(void *opaque, hwaddr addr, unsigned size)
{
MchpPfSoCMMUartState *s = opaque;
if (addr >= MCHP_PFSOC_MMUART_REG_SIZE) {
addr >>= 2;
if (addr >= MCHP_PFSOC_MMUART_REG_COUNT) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n",
__func__, addr);
__func__, addr << 2);
return 0;
}
return s->reg[addr / sizeof(uint32_t)];
return s->reg[addr];
}
static void mchp_pfsoc_mmuart_write(void *opaque, hwaddr addr,
@ -44,13 +49,14 @@ static void mchp_pfsoc_mmuart_write(void *opaque, hwaddr addr,
MchpPfSoCMMUartState *s = opaque;
uint32_t val32 = (uint32_t)value;
if (addr >= MCHP_PFSOC_MMUART_REG_SIZE) {
addr >>= 2;
if (addr >= MCHP_PFSOC_MMUART_REG_COUNT) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
" v=0x%x\n", __func__, addr, val32);
" v=0x%x\n", __func__, addr << 2, val32);
return;
}
s->reg[addr / sizeof(uint32_t)] = val32;
s->reg[addr] = val32;
}
static const MemoryRegionOps mchp_pfsoc_mmuart_ops = {
@ -63,23 +69,95 @@ static const MemoryRegionOps mchp_pfsoc_mmuart_ops = {
},
};
MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem,
hwaddr base, qemu_irq irq, Chardev *chr)
static void mchp_pfsoc_mmuart_reset(DeviceState *dev)
{
MchpPfSoCMMUartState *s;
MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(dev);
s = g_new0(MchpPfSoCMMUartState, 1);
memory_region_init_io(&s->iomem, NULL, &mchp_pfsoc_mmuart_ops, s,
"mchp.pfsoc.mmuart", 0x1000);
s->base = base;
s->irq = irq;
s->serial = serial_mm_init(sysmem, base, 2, irq, 399193, chr,
DEVICE_LITTLE_ENDIAN);
memory_region_add_subregion(sysmem, base + 0x20, &s->iomem);
return s;
memset(s->reg, 0, sizeof(s->reg));
device_cold_reset(DEVICE(&s->serial_mm));
}
static void mchp_pfsoc_mmuart_init(Object *obj)
{
MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(obj);
object_initialize_child(obj, "serial-mm", &s->serial_mm, TYPE_SERIAL_MM);
object_property_add_alias(obj, "chardev", OBJECT(&s->serial_mm), "chardev");
}
static void mchp_pfsoc_mmuart_realize(DeviceState *dev, Error **errp)
{
MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(dev);
qdev_prop_set_uint8(DEVICE(&s->serial_mm), "regshift", 2);
qdev_prop_set_uint32(DEVICE(&s->serial_mm), "baudbase", 399193);
qdev_prop_set_uint8(DEVICE(&s->serial_mm), "endianness",
DEVICE_LITTLE_ENDIAN);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->serial_mm), errp)) {
return;
}
sysbus_pass_irq(SYS_BUS_DEVICE(dev), SYS_BUS_DEVICE(&s->serial_mm));
memory_region_init(&s->container, OBJECT(s), "mchp.pfsoc.mmuart", 0x1000);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
memory_region_add_subregion(&s->container, 0,
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->serial_mm), 0));
memory_region_init_io(&s->iomem, OBJECT(s), &mchp_pfsoc_mmuart_ops, s,
"mchp.pfsoc.mmuart.regs", 0x1000 - REGS_OFFSET);
memory_region_add_subregion(&s->container, REGS_OFFSET, &s->iomem);
}
static const VMStateDescription mchp_pfsoc_mmuart_vmstate = {
.name = "mchp.pfsoc.uart",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(reg, MchpPfSoCMMUartState,
MCHP_PFSOC_MMUART_REG_COUNT),
VMSTATE_END_OF_LIST()
}
};
static void mchp_pfsoc_mmuart_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = mchp_pfsoc_mmuart_realize;
dc->reset = mchp_pfsoc_mmuart_reset;
dc->vmsd = &mchp_pfsoc_mmuart_vmstate;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo mchp_pfsoc_mmuart_info = {
.name = TYPE_MCHP_PFSOC_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MchpPfSoCMMUartState),
.instance_init = mchp_pfsoc_mmuart_init,
.class_init = mchp_pfsoc_mmuart_class_init,
};
static void mchp_pfsoc_mmuart_register_types(void)
{
type_register_static(&mchp_pfsoc_mmuart_info);
}
type_init(mchp_pfsoc_mmuart_register_types)
MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem,
hwaddr base,
qemu_irq irq, Chardev *chr)
{
DeviceState *dev = qdev_new(TYPE_MCHP_PFSOC_UART);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
qdev_prop_set_chr(dev, "chardev", chr);
sysbus_realize(sbd, &error_fatal);
memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(sbd, 0));
sysbus_connect_irq(sbd, 0, irq);
return MCHP_PFSOC_UART(dev);
}

View file

@ -168,6 +168,7 @@ static void shakti_uart_class_init(ObjectClass *klass, void *data)
dc->reset = shakti_uart_reset;
dc->realize = shakti_uart_realize;
device_class_set_props(dc, shakti_uart_properties);
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo shakti_uart_info = {

View file

@ -248,6 +248,7 @@ static void sifive_uart_class_init(ObjectClass *oc, void *data)
rc->phases.enter = sifive_uart_reset_enter;
rc->phases.hold = sifive_uart_reset_hold;
device_class_set_props(dc, sifive_uart_properties);
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo sifive_uart_info = {

View file

@ -232,7 +232,7 @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
{
SiFivePDMAState *s = opaque;
int ch = SIFIVE_PDMA_CHAN_NO(offset);
bool claimed;
bool claimed, run;
if (ch >= SIFIVE_PDMA_CHANS) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
@ -243,7 +243,8 @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
offset &= 0xfff;
switch (offset) {
case DMA_CONTROL:
claimed = !!s->chan[ch].control & CONTROL_CLAIM;
claimed = !!(s->chan[ch].control & CONTROL_CLAIM);
run = !!(s->chan[ch].control & CONTROL_RUN);
if (!claimed && (value & CONTROL_CLAIM)) {
/* reset Next* registers */
@ -254,13 +255,19 @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
s->chan[ch].next_src = 0;
}
/* claim bit can only be cleared when run is low */
if (run && !(value & CONTROL_CLAIM)) {
value |= CONTROL_CLAIM;
}
s->chan[ch].control = value;
/*
* If channel was not claimed before run bit is set,
* or if the channel is disclaimed when run was low,
* DMA won't run.
*/
if (!claimed) {
if (!claimed || (!run && !(value & CONTROL_CLAIM))) {
s->chan[ch].control &= ~CONTROL_RUN;
return;
}

View file

@ -150,6 +150,13 @@ static void shakti_c_soc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = shakti_c_soc_state_realize;
/*
* Reasons:
* - Creates CPUS in riscv_hart_realize(), and can create unintended
* CPUs
* - Uses serial_hds in realize function, thus can't be used twice
*/
dc->user_creatable = false;
}
static void shakti_c_soc_instance_init(Object *obj)

View file

@ -28,18 +28,25 @@
#ifndef HW_MCHP_PFSOC_MMUART_H
#define HW_MCHP_PFSOC_MMUART_H
#include "hw/sysbus.h"
#include "hw/char/serial.h"
#define MCHP_PFSOC_MMUART_REG_SIZE 52
#define MCHP_PFSOC_MMUART_REG_COUNT 13
#define TYPE_MCHP_PFSOC_UART "mchp.pfsoc.uart"
OBJECT_DECLARE_SIMPLE_TYPE(MchpPfSoCMMUartState, MCHP_PFSOC_UART)
typedef struct MchpPfSoCMMUartState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion container;
MemoryRegion iomem;
hwaddr base;
qemu_irq irq;
SerialMM *serial;
SerialMM serial_mm;
uint32_t reg[MCHP_PFSOC_MMUART_REG_SIZE / sizeof(uint32_t)];
uint32_t reg[MCHP_PFSOC_MMUART_REG_COUNT];
} MchpPfSoCMMUartState;
/**

View file

@ -3,6 +3,7 @@
*
* Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com
* Copyright (c) 2020 Frank Chang, frank.chang@sifive.com
* Copyright (c) 2021 Philipp Tomsich, philipp.tomsich@vrull.eu
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -23,68 +24,28 @@
#include "exec/helper-proto.h"
#include "tcg/tcg.h"
static const uint64_t adjacent_masks[] = {
dup_const(MO_8, 0x55),
dup_const(MO_8, 0x33),
dup_const(MO_8, 0x0f),
dup_const(MO_16, 0xff),
dup_const(MO_32, 0xffff),
UINT32_MAX
};
static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift)
target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2)
{
return ((x & mask) << shift) | ((x & ~mask) >> shift);
}
target_ulong result = 0;
static target_ulong do_grev(target_ulong rs1,
target_ulong rs2,
int bits)
{
target_ulong x = rs1;
int i, shift;
for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) {
if (rs2 & shift) {
x = do_swap(x, adjacent_masks[i], shift);
for (int i = 0; i < TARGET_LONG_BITS; i++) {
if ((rs2 >> i) & 1) {
result ^= (rs1 << i);
}
}
return x;
return result;
}
target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2)
target_ulong HELPER(clmulr)(target_ulong rs1, target_ulong rs2)
{
return do_grev(rs1, rs2, TARGET_LONG_BITS);
}
target_ulong result = 0;
target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2)
{
return do_grev(rs1, rs2, 32);
}
static target_ulong do_gorc(target_ulong rs1,
target_ulong rs2,
int bits)
{
target_ulong x = rs1;
int i, shift;
for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) {
if (rs2 & shift) {
x |= do_swap(x, adjacent_masks[i], shift);
for (int i = 0; i < TARGET_LONG_BITS; i++) {
if ((rs2 >> i) & 1) {
result ^= (rs1 >> (TARGET_LONG_BITS - i - 1));
}
}
return x;
}
target_ulong HELPER(gorc)(target_ulong rs1, target_ulong rs2)
{
return do_gorc(rs1, rs2, TARGET_LONG_BITS);
}
target_ulong HELPER(gorcw)(target_ulong rs1, target_ulong rs2)
{
return do_gorc(rs1, rs2, 32);
return result;
}

View file

@ -127,11 +127,6 @@ static void set_priv_version(CPURISCVState *env, int priv_ver)
env->priv_ver = priv_ver;
}
static void set_bext_version(CPURISCVState *env, int bext_ver)
{
env->bext_ver = bext_ver;
}
static void set_vext_version(CPURISCVState *env, int vext_ver)
{
env->vext_ver = vext_ver;
@ -496,25 +491,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
if (cpu->cfg.ext_h) {
target_misa |= RVH;
}
if (cpu->cfg.ext_b) {
int bext_version = BEXT_VERSION_0_93_0;
target_misa |= RVB;
if (cpu->cfg.bext_spec) {
if (!g_strcmp0(cpu->cfg.bext_spec, "v0.93")) {
bext_version = BEXT_VERSION_0_93_0;
} else {
error_setg(errp,
"Unsupported bitmanip spec version '%s'",
cpu->cfg.bext_spec);
return;
}
} else {
qemu_log("bitmanip version is not specified, "
"use the default value v0.93\n");
}
set_bext_version(env, bext_version);
}
if (cpu->cfg.ext_v) {
int vext_version = VEXT_VERSION_0_07_1;
target_misa |= RVV;
@ -616,14 +592,16 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
/* This is experimental so mark with 'x-' */
DEFINE_PROP_BOOL("x-b", RISCVCPU, cfg.ext_b, false),
DEFINE_PROP_BOOL("x-zba", RISCVCPU, cfg.ext_zba, false),
DEFINE_PROP_BOOL("x-zbb", RISCVCPU, cfg.ext_zbb, false),
DEFINE_PROP_BOOL("x-zbc", RISCVCPU, cfg.ext_zbc, false),
DEFINE_PROP_BOOL("x-zbs", RISCVCPU, cfg.ext_zbs, false),
DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false),
DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
DEFINE_PROP_STRING("bext_spec", RISCVCPU, cfg.bext_spec),
DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),

View file

@ -67,7 +67,6 @@
#define RVS RV('S')
#define RVU RV('U')
#define RVH RV('H')
#define RVB RV('B')
/* S extension denotes that Supervisor mode exists, however it is possible
to have a core that support S mode but does not have an MMU and there
@ -83,7 +82,6 @@ enum {
#define PRIV_VERSION_1_10_0 0x00011000
#define PRIV_VERSION_1_11_0 0x00011100
#define BEXT_VERSION_0_93_0 0x00009300
#define VEXT_VERSION_0_07_1 0x00000701
enum {
@ -288,11 +286,14 @@ struct RISCVCPU {
bool ext_f;
bool ext_d;
bool ext_c;
bool ext_b;
bool ext_s;
bool ext_u;
bool ext_h;
bool ext_v;
bool ext_zba;
bool ext_zbb;
bool ext_zbc;
bool ext_zbs;
bool ext_counters;
bool ext_ifencei;
bool ext_icsr;
@ -392,6 +393,7 @@ FIELD(TB_FLAGS, SEW, 5, 3)
FIELD(TB_FLAGS, VILL, 8, 1)
/* Is a Hypervisor instruction load/store allowed? */
FIELD(TB_FLAGS, HLSX, 9, 1)
FIELD(TB_FLAGS, MSTATUS_HS_FS, 10, 2)
bool riscv_cpu_is_32bit(CPURISCVState *env);
@ -448,6 +450,9 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
get_field(env->hstatus, HSTATUS_HU))) {
flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
}
flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
get_field(env->mstatus_hs, MSTATUS_FS));
}
#endif

View file

@ -59,10 +59,8 @@ DEF_HELPER_FLAGS_2(fcvt_d_lu, TCG_CALL_NO_RWG, i64, env, tl)
DEF_HELPER_FLAGS_1(fclass_d, TCG_CALL_NO_RWG_SE, tl, i64)
/* Bitmanip */
DEF_HELPER_FLAGS_2(grev, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(grevw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(gorc, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(gorcw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(clmul, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_2(clmulr, TCG_CALL_NO_RWG_SE, tl, tl, tl)
/* Special functions */
DEF_HELPER_2(csrr, tl, env, int)

View file

@ -660,76 +660,69 @@ vamomaxd_v 10100 . . ..... ..... 111 ..... 0101111 @r_wdvm
vamominud_v 11000 . . ..... ..... 111 ..... 0101111 @r_wdvm
vamomaxud_v 11100 . . ..... ..... 111 ..... 0101111 @r_wdvm
# *** RV32B Standard Extension ***
clz 011000 000000 ..... 001 ..... 0010011 @r2
ctz 011000 000001 ..... 001 ..... 0010011 @r2
cpop 011000 000010 ..... 001 ..... 0010011 @r2
sext_b 011000 000100 ..... 001 ..... 0010011 @r2
sext_h 011000 000101 ..... 001 ..... 0010011 @r2
andn 0100000 .......... 111 ..... 0110011 @r
orn 0100000 .......... 110 ..... 0110011 @r
xnor 0100000 .......... 100 ..... 0110011 @r
pack 0000100 .......... 100 ..... 0110011 @r
packu 0100100 .......... 100 ..... 0110011 @r
packh 0000100 .......... 111 ..... 0110011 @r
min 0000101 .......... 100 ..... 0110011 @r
minu 0000101 .......... 101 ..... 0110011 @r
max 0000101 .......... 110 ..... 0110011 @r
maxu 0000101 .......... 111 ..... 0110011 @r
bset 0010100 .......... 001 ..... 0110011 @r
bclr 0100100 .......... 001 ..... 0110011 @r
binv 0110100 .......... 001 ..... 0110011 @r
bext 0100100 .......... 101 ..... 0110011 @r
slo 0010000 .......... 001 ..... 0110011 @r
sro 0010000 .......... 101 ..... 0110011 @r
ror 0110000 .......... 101 ..... 0110011 @r
rol 0110000 .......... 001 ..... 0110011 @r
grev 0110100 .......... 101 ..... 0110011 @r
gorc 0010100 .......... 101 ..... 0110011 @r
# *** RV32 Zba Standard Extension ***
sh1add 0010000 .......... 010 ..... 0110011 @r
sh2add 0010000 .......... 100 ..... 0110011 @r
sh3add 0010000 .......... 110 ..... 0110011 @r
bseti 00101. ........... 001 ..... 0010011 @sh
bclri 01001. ........... 001 ..... 0010011 @sh
binvi 01101. ........... 001 ..... 0010011 @sh
bexti 01001. ........... 101 ..... 0010011 @sh
sloi 00100. ........... 001 ..... 0010011 @sh
sroi 00100. ........... 101 ..... 0010011 @sh
rori 01100. ........... 101 ..... 0010011 @sh
grevi 01101. ........... 101 ..... 0010011 @sh
gorci 00101. ........... 101 ..... 0010011 @sh
# *** RV64B Standard Extension (in addition to RV32B) ***
clzw 0110000 00000 ..... 001 ..... 0011011 @r2
ctzw 0110000 00001 ..... 001 ..... 0011011 @r2
cpopw 0110000 00010 ..... 001 ..... 0011011 @r2
packw 0000100 .......... 100 ..... 0111011 @r
packuw 0100100 .......... 100 ..... 0111011 @r
bsetw 0010100 .......... 001 ..... 0111011 @r
bclrw 0100100 .......... 001 ..... 0111011 @r
binvw 0110100 .......... 001 ..... 0111011 @r
bextw 0100100 .......... 101 ..... 0111011 @r
slow 0010000 .......... 001 ..... 0111011 @r
srow 0010000 .......... 101 ..... 0111011 @r
rorw 0110000 .......... 101 ..... 0111011 @r
rolw 0110000 .......... 001 ..... 0111011 @r
grevw 0110100 .......... 101 ..... 0111011 @r
gorcw 0010100 .......... 101 ..... 0111011 @r
# *** RV64 Zba Standard Extension (in addition to RV32 Zba) ***
add_uw 0000100 .......... 000 ..... 0111011 @r
sh1add_uw 0010000 .......... 010 ..... 0111011 @r
sh2add_uw 0010000 .......... 100 ..... 0111011 @r
sh3add_uw 0010000 .......... 110 ..... 0111011 @r
add_uw 0000100 .......... 000 ..... 0111011 @r
slli_uw 00001 ............ 001 ..... 0011011 @sh
bsetiw 0010100 .......... 001 ..... 0011011 @sh5
bclriw 0100100 .......... 001 ..... 0011011 @sh5
binviw 0110100 .......... 001 ..... 0011011 @sh5
sloiw 0010000 .......... 001 ..... 0011011 @sh5
sroiw 0010000 .......... 101 ..... 0011011 @sh5
# *** RV32 Zbb Standard Extension ***
andn 0100000 .......... 111 ..... 0110011 @r
clz 011000 000000 ..... 001 ..... 0010011 @r2
cpop 011000 000010 ..... 001 ..... 0010011 @r2
ctz 011000 000001 ..... 001 ..... 0010011 @r2
max 0000101 .......... 110 ..... 0110011 @r
maxu 0000101 .......... 111 ..... 0110011 @r
min 0000101 .......... 100 ..... 0110011 @r
minu 0000101 .......... 101 ..... 0110011 @r
orc_b 001010 000111 ..... 101 ..... 0010011 @r2
orn 0100000 .......... 110 ..... 0110011 @r
# The encoding for rev8 differs between RV32 and RV64.
# rev8_32 denotes the RV32 variant.
rev8_32 011010 011000 ..... 101 ..... 0010011 @r2
rol 0110000 .......... 001 ..... 0110011 @r
ror 0110000 .......... 101 ..... 0110011 @r
rori 01100 ............ 101 ..... 0010011 @sh
sext_b 011000 000100 ..... 001 ..... 0010011 @r2
sext_h 011000 000101 ..... 001 ..... 0010011 @r2
xnor 0100000 .......... 100 ..... 0110011 @r
# The encoding for zext.h differs between RV32 and RV64.
# zext_h_32 denotes the RV32 variant.
zext_h_32 0000100 00000 ..... 100 ..... 0110011 @r2
# *** RV64 Zbb Standard Extension (in addition to RV32 Zbb) ***
clzw 0110000 00000 ..... 001 ..... 0011011 @r2
ctzw 0110000 00001 ..... 001 ..... 0011011 @r2
cpopw 0110000 00010 ..... 001 ..... 0011011 @r2
# The encoding for rev8 differs between RV32 and RV64.
# When executing on RV64, the encoding used in RV32 is an illegal
# instruction, so we use different handler functions to differentiate.
rev8_64 011010 111000 ..... 101 ..... 0010011 @r2
rolw 0110000 .......... 001 ..... 0111011 @r
roriw 0110000 .......... 101 ..... 0011011 @sh5
greviw 0110100 .......... 101 ..... 0011011 @sh5
gorciw 0010100 .......... 101 ..... 0011011 @sh5
rorw 0110000 .......... 101 ..... 0111011 @r
# The encoding for zext.h differs between RV32 and RV64.
# When executing on RV64, the encoding used in RV32 is an illegal
# instruction, so we use different handler functions to differentiate.
zext_h_64 0000100 00000 ..... 100 ..... 0111011 @r2
slli_uw 00001. ........... 001 ..... 0011011 @sh
# *** RV32 Zbc Standard Extension ***
clmul 0000101 .......... 001 ..... 0110011 @r
clmulh 0000101 .......... 011 ..... 0110011 @r
clmulr 0000101 .......... 010 ..... 0110011 @r
# *** RV32 Zbs Standard Extension ***
bclr 0100100 .......... 001 ..... 0110011 @r
bclri 01001. ........... 001 ..... 0010011 @sh
bext 0100100 .......... 101 ..... 0110011 @r
bexti 01001. ........... 101 ..... 0010011 @sh
binv 0110100 .......... 001 ..... 0110011 @r
binvi 01101. ........... 001 ..... 0010011 @sh
bset 0010100 .......... 001 ..... 0110011 @r
bseti 00101. ........... 001 ..... 0010011 @sh

View file

@ -1,8 +1,9 @@
/*
* RISC-V translation routines for the RVB Standard Extension.
* RISC-V translation routines for the Zb[abcs] Standard Extension.
*
* Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com
* Copyright (c) 2020 Frank Chang, frank.chang@sifive.com
* Copyright (c) 2021 Philipp Tomsich, philipp.tomsich@vrull.eu
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -17,6 +18,29 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define REQUIRE_ZBA(ctx) do { \
if (!RISCV_CPU(ctx->cs)->cfg.ext_zba) { \
return false; \
} \
} while (0)
#define REQUIRE_ZBB(ctx) do { \
if (!RISCV_CPU(ctx->cs)->cfg.ext_zbb) { \
return false; \
} \
} while (0)
#define REQUIRE_ZBC(ctx) do { \
if (!RISCV_CPU(ctx->cs)->cfg.ext_zbc) { \
return false; \
} \
} while (0)
#define REQUIRE_ZBS(ctx) do { \
if (!RISCV_CPU(ctx->cs)->cfg.ext_zbs) { \
return false; \
} \
} while (0)
static void gen_clz(TCGv ret, TCGv arg1)
{
@ -25,7 +49,7 @@ static void gen_clz(TCGv ret, TCGv arg1)
static bool trans_clz(DisasContext *ctx, arg_clz *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_ZERO, gen_clz);
}
@ -36,108 +60,67 @@ static void gen_ctz(TCGv ret, TCGv arg1)
static bool trans_ctz(DisasContext *ctx, arg_ctz *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_ZERO, gen_ctz);
}
static bool trans_cpop(DisasContext *ctx, arg_cpop *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl);
}
static bool trans_andn(DisasContext *ctx, arg_andn *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl);
}
static bool trans_orn(DisasContext *ctx, arg_orn *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl);
}
static bool trans_xnor(DisasContext *ctx, arg_xnor *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl);
}
static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2)
{
tcg_gen_deposit_tl(ret, arg1, arg2,
TARGET_LONG_BITS / 2,
TARGET_LONG_BITS / 2);
}
static bool trans_pack(DisasContext *ctx, arg_pack *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_arith(ctx, a, EXT_NONE, gen_pack);
}
static void gen_packu(TCGv ret, TCGv arg1, TCGv arg2)
{
TCGv t = tcg_temp_new();
tcg_gen_shri_tl(t, arg1, TARGET_LONG_BITS / 2);
tcg_gen_deposit_tl(ret, arg2, t, 0, TARGET_LONG_BITS / 2);
tcg_temp_free(t);
}
static bool trans_packu(DisasContext *ctx, arg_packu *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_arith(ctx, a, EXT_NONE, gen_packu);
}
static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2)
{
TCGv t = tcg_temp_new();
tcg_gen_ext8u_tl(t, arg2);
tcg_gen_deposit_tl(ret, arg1, t, 8, TARGET_LONG_BITS - 8);
tcg_temp_free(t);
}
static bool trans_packh(DisasContext *ctx, arg_packh *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_arith(ctx, a, EXT_NONE, gen_packh);
}
static bool trans_min(DisasContext *ctx, arg_min *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smin_tl);
}
static bool trans_max(DisasContext *ctx, arg_max *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smax_tl);
}
static bool trans_minu(DisasContext *ctx, arg_minu *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umin_tl);
}
static bool trans_maxu(DisasContext *ctx, arg_maxu *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umax_tl);
}
static bool trans_sext_b(DisasContext *ctx, arg_sext_b *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext8s_tl);
}
static bool trans_sext_h(DisasContext *ctx, arg_sext_h *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16s_tl);
}
@ -159,13 +142,13 @@ static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt)
static bool trans_bset(DisasContext *ctx, arg_bset *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBS(ctx);
return gen_shift(ctx, a, EXT_NONE, gen_bset);
}
static bool trans_bseti(DisasContext *ctx, arg_bseti *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBS(ctx);
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bset);
}
@ -181,13 +164,13 @@ static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt)
static bool trans_bclr(DisasContext *ctx, arg_bclr *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBS(ctx);
return gen_shift(ctx, a, EXT_NONE, gen_bclr);
}
static bool trans_bclri(DisasContext *ctx, arg_bclri *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBS(ctx);
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bclr);
}
@ -203,13 +186,13 @@ static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt)
static bool trans_binv(DisasContext *ctx, arg_binv *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBS(ctx);
return gen_shift(ctx, a, EXT_NONE, gen_binv);
}
static bool trans_binvi(DisasContext *ctx, arg_binvi *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBS(ctx);
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_binv);
}
@ -221,104 +204,69 @@ static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt)
static bool trans_bext(DisasContext *ctx, arg_bext *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBS(ctx);
return gen_shift(ctx, a, EXT_NONE, gen_bext);
}
static bool trans_bexti(DisasContext *ctx, arg_bexti *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBS(ctx);
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bext);
}
static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2)
{
tcg_gen_not_tl(ret, arg1);
tcg_gen_shl_tl(ret, ret, arg2);
tcg_gen_not_tl(ret, ret);
}
static bool trans_slo(DisasContext *ctx, arg_slo *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift(ctx, a, EXT_NONE, gen_slo);
}
static bool trans_sloi(DisasContext *ctx, arg_sloi *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_slo);
}
static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2)
{
tcg_gen_not_tl(ret, arg1);
tcg_gen_shr_tl(ret, ret, arg2);
tcg_gen_not_tl(ret, ret);
}
static bool trans_sro(DisasContext *ctx, arg_sro *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift(ctx, a, EXT_ZERO, gen_sro);
}
static bool trans_sroi(DisasContext *ctx, arg_sroi *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_sro);
}
static bool trans_ror(DisasContext *ctx, arg_ror *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotr_tl);
}
static bool trans_rori(DisasContext *ctx, arg_rori *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_rotri_tl);
}
static bool trans_rol(DisasContext *ctx, arg_rol *a)
{
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotl_tl);
}
static bool trans_grev(DisasContext *ctx, arg_grev *a)
static bool trans_rev8_32(DisasContext *ctx, arg_rev8_32 *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift(ctx, a, EXT_NONE, gen_helper_grev);
REQUIRE_32BIT(ctx);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_NONE, tcg_gen_bswap_tl);
}
static void gen_grevi(TCGv dest, TCGv src, target_long shamt)
static bool trans_rev8_64(DisasContext *ctx, arg_rev8_64 *a)
{
if (shamt == TARGET_LONG_BITS - 8) {
/* rev8, byte swaps */
tcg_gen_bswap_tl(dest, src);
} else {
gen_helper_grev(dest, src, tcg_constant_tl(shamt));
}
REQUIRE_64BIT(ctx);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_NONE, tcg_gen_bswap_tl);
}
static bool trans_grevi(DisasContext *ctx, arg_grevi *a)
static void gen_orc_b(TCGv ret, TCGv source1)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_grevi);
TCGv tmp = tcg_temp_new();
TCGv ones = tcg_constant_tl(dup_const_tl(MO_8, 0x01));
/* Set lsb in each byte if the byte was zero. */
tcg_gen_sub_tl(tmp, source1, ones);
tcg_gen_andc_tl(tmp, tmp, source1);
tcg_gen_shri_tl(tmp, tmp, 7);
tcg_gen_andc_tl(tmp, ones, tmp);
/* Replicate the lsb of each byte across the byte. */
tcg_gen_muli_tl(ret, tmp, 0xff);
tcg_temp_free(tmp);
}
static bool trans_gorc(DisasContext *ctx, arg_gorc *a)
static bool trans_orc_b(DisasContext *ctx, arg_orc_b *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift(ctx, a, EXT_ZERO, gen_helper_gorc);
}
static bool trans_gorci(DisasContext *ctx, arg_gorci *a)
{
REQUIRE_EXT(ctx, RVB);
return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_gorc);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_ZERO, gen_orc_b);
}
#define GEN_SHADD(SHAMT) \
@ -339,7 +287,7 @@ GEN_SHADD(3)
#define GEN_TRANS_SHADD(SHAMT) \
static bool trans_sh##SHAMT##add(DisasContext *ctx, arg_sh##SHAMT##add *a) \
{ \
REQUIRE_EXT(ctx, RVB); \
REQUIRE_ZBA(ctx); \
return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add); \
}
@ -347,17 +295,33 @@ GEN_TRANS_SHADD(1)
GEN_TRANS_SHADD(2)
GEN_TRANS_SHADD(3)
static bool trans_zext_h_32(DisasContext *ctx, arg_zext_h_32 *a)
{
REQUIRE_32BIT(ctx);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16u_tl);
}
static bool trans_zext_h_64(DisasContext *ctx, arg_zext_h_64 *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16u_tl);
}
static void gen_clzw(TCGv ret, TCGv arg1)
{
tcg_gen_clzi_tl(ret, ret, 64);
tcg_gen_subi_tl(ret, ret, 32);
TCGv t = tcg_temp_new();
tcg_gen_shli_tl(t, arg1, 32);
tcg_gen_clzi_tl(ret, t, 32);
tcg_temp_free(t);
}
static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
return gen_unary(ctx, a, EXT_ZERO, gen_clzw);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_NONE, gen_clzw);
}
static void gen_ctzw(TCGv ret, TCGv arg1)
@ -369,137 +333,18 @@ static void gen_ctzw(TCGv ret, TCGv arg1)
static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
return gen_unary(ctx, a, EXT_NONE, gen_ctzw);
}
static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
ctx->w = true;
return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl);
}
static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2)
{
TCGv t = tcg_temp_new();
tcg_gen_ext16s_tl(t, arg2);
tcg_gen_deposit_tl(ret, arg1, t, 16, 48);
tcg_temp_free(t);
}
static bool trans_packw(DisasContext *ctx, arg_packw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
return gen_arith(ctx, a, EXT_NONE, gen_packw);
}
static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2)
{
TCGv t = tcg_temp_new();
tcg_gen_shri_tl(t, arg1, 16);
tcg_gen_deposit_tl(ret, arg2, t, 0, 16);
tcg_gen_ext32s_tl(ret, ret);
tcg_temp_free(t);
}
static bool trans_packuw(DisasContext *ctx, arg_packuw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
return gen_arith(ctx, a, EXT_NONE, gen_packuw);
}
static bool trans_bsetw(DisasContext *ctx, arg_bsetw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift(ctx, a, EXT_NONE, gen_bset);
}
static bool trans_bsetiw(DisasContext *ctx, arg_bsetiw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bset);
}
static bool trans_bclrw(DisasContext *ctx, arg_bclrw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift(ctx, a, EXT_NONE, gen_bclr);
}
static bool trans_bclriw(DisasContext *ctx, arg_bclriw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bclr);
}
static bool trans_binvw(DisasContext *ctx, arg_binvw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift(ctx, a, EXT_NONE, gen_binv);
}
static bool trans_binviw(DisasContext *ctx, arg_binviw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_binv);
}
static bool trans_bextw(DisasContext *ctx, arg_bextw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift(ctx, a, EXT_NONE, gen_bext);
}
static bool trans_slow(DisasContext *ctx, arg_slow *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift(ctx, a, EXT_NONE, gen_slo);
}
static bool trans_sloiw(DisasContext *ctx, arg_sloiw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_slo);
}
static bool trans_srow(DisasContext *ctx, arg_srow *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift(ctx, a, EXT_ZERO, gen_sro);
}
static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_sro);
}
static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
{
TCGv_i32 t1 = tcg_temp_new_i32();
@ -521,7 +366,7 @@ static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
static bool trans_rorw(DisasContext *ctx, arg_rorw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
ctx->w = true;
return gen_shift(ctx, a, EXT_NONE, gen_rorw);
}
@ -529,7 +374,7 @@ static bool trans_rorw(DisasContext *ctx, arg_rorw *a)
static bool trans_roriw(DisasContext *ctx, arg_roriw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
ctx->w = true;
return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_rorw);
}
@ -555,43 +400,11 @@ static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2)
static bool trans_rolw(DisasContext *ctx, arg_rolw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBB(ctx);
ctx->w = true;
return gen_shift(ctx, a, EXT_NONE, gen_rolw);
}
static bool trans_grevw(DisasContext *ctx, arg_grevw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift(ctx, a, EXT_ZERO, gen_helper_grev);
}
static bool trans_greviw(DisasContext *ctx, arg_greviw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_grev);
}
static bool trans_gorcw(DisasContext *ctx, arg_gorcw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift(ctx, a, EXT_ZERO, gen_helper_gorc);
}
static bool trans_gorciw(DisasContext *ctx, arg_gorciw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
ctx->w = true;
return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_helper_gorc);
}
#define GEN_SHADD_UW(SHAMT) \
static void gen_sh##SHAMT##add_uw(TCGv ret, TCGv arg1, TCGv arg2) \
{ \
@ -614,7 +427,7 @@ static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, \
arg_sh##SHAMT##add_uw *a) \
{ \
REQUIRE_64BIT(ctx); \
REQUIRE_EXT(ctx, RVB); \
REQUIRE_ZBA(ctx); \
return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add_uw); \
}
@ -624,14 +437,16 @@ GEN_TRANS_SHADD_UW(3)
static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2)
{
tcg_gen_ext32u_tl(arg1, arg1);
tcg_gen_add_tl(ret, arg1, arg2);
TCGv t = tcg_temp_new();
tcg_gen_ext32u_tl(t, arg1);
tcg_gen_add_tl(ret, t, arg2);
tcg_temp_free(t);
}
static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBA(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_add_uw);
}
@ -643,6 +458,30 @@ static void gen_slli_uw(TCGv dest, TCGv src, target_long shamt)
static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a)
{
REQUIRE_64BIT(ctx);
REQUIRE_EXT(ctx, RVB);
REQUIRE_ZBA(ctx);
return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_slli_uw);
}
static bool trans_clmul(DisasContext *ctx, arg_clmul *a)
{
REQUIRE_ZBC(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_helper_clmul);
}
static void gen_clmulh(TCGv dst, TCGv src1, TCGv src2)
{
gen_helper_clmulr(dst, src1, src2);
tcg_gen_shri_tl(dst, dst, 1);
}
static bool trans_clmulh(DisasContext *ctx, arg_clmulr *a)
{
REQUIRE_ZBC(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_clmulh);
}
static bool trans_clmulr(DisasContext *ctx, arg_clmulh *a)
{
REQUIRE_ZBC(ctx);
return gen_arith(ctx, a, EXT_NONE, gen_helper_clmulr);
}

View file

@ -58,6 +58,7 @@ typedef struct DisasContext {
target_ulong misa;
uint32_t opcode;
uint32_t mstatus_fs;
uint32_t mstatus_hs_fs;
uint32_t mem_idx;
/* Remember the rounding mode encoded in the previous fp instruction,
which we have already installed into env->fp_status. Or -1 for
@ -280,27 +281,29 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
static void mark_fs_dirty(DisasContext *ctx)
{
TCGv tmp;
target_ulong sd;
target_ulong sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
if (ctx->mstatus_fs == MSTATUS_FS) {
return;
if (ctx->mstatus_fs != MSTATUS_FS) {
/* Remember the state change for the rest of the TB. */
ctx->mstatus_fs = MSTATUS_FS;
tmp = tcg_temp_new();
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
tcg_temp_free(tmp);
}
/* Remember the state change for the rest of the TB. */
ctx->mstatus_fs = MSTATUS_FS;
tmp = tcg_temp_new();
sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
/* Remember the stage change for the rest of the TB. */
ctx->mstatus_hs_fs = MSTATUS_FS;
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
if (ctx->virt_enabled) {
tmp = tcg_temp_new();
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
tcg_temp_free(tmp);
}
tcg_temp_free(tmp);
}
#else
static inline void mark_fs_dirty(DisasContext *ctx) { }
@ -337,6 +340,12 @@ EX_SH(12)
} \
} while (0)
#define REQUIRE_32BIT(ctx) do { \
if (!is_32bit(ctx)) { \
return false; \
} \
} while (0)
#define REQUIRE_64BIT(ctx) do { \
if (is_32bit(ctx)) { \
return false; \
@ -533,6 +542,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->frm = -1; /* unknown rounding mode */
ctx->ext_ifencei = cpu->cfg.ext_ifencei;
ctx->vlen = cpu->cfg.vlen;
ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);