aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-10-07 07:18:39 -0700
committerRichard Henderson <richard.henderson@linaro.org>2021-10-07 07:18:39 -0700
commit3c019339830affe7974b738e0c2b71bd28778ef0 (patch)
tree66718f21492d05ef2bc63d0a9bcb3ddc9c1a0d82
parentca61fa4b803e5d0abaf6f1ceb690f23bb78a4def (diff)
parent9ae6ecd848dcd1b32003526ab65a0d4c644dfb07 (diff)
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>
-rw-r--r--disas/riscv.c157
-rw-r--r--hw/char/ibex_uart.c1
-rw-r--r--hw/char/mchp_pfsoc_mmuart.c116
-rw-r--r--hw/char/shakti_uart.c1
-rw-r--r--hw/char/sifive_uart.c1
-rw-r--r--hw/dma/sifive_pdma.c13
-rw-r--r--hw/riscv/shakti_c.c7
-rw-r--r--include/hw/char/mchp_pfsoc_mmuart.h17
-rw-r--r--target/riscv/bitmanip_helper.c65
-rw-r--r--target/riscv/cpu.c30
-rw-r--r--target/riscv/cpu.h11
-rw-r--r--target/riscv/helper.h6
-rw-r--r--target/riscv/insn32.decode115
-rw-r--r--target/riscv/insn_trans/trans_rvb.c.inc419
-rw-r--r--target/riscv/translate.c36
15 files changed, 516 insertions, 479 deletions
diff --git a/disas/riscv.c b/disas/riscv.c
index 278d9be924..793ad14c27 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -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:
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
index 9b0a817713..e58181fcf4 100644
--- a/hw/char/ibex_uart.c
+++ b/hw/char/ibex_uart.c
@@ -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 = {
diff --git a/hw/char/mchp_pfsoc_mmuart.c b/hw/char/mchp_pfsoc_mmuart.c
index 2facf85c2d..22f3e78eb9 100644
--- a/hw/char/mchp_pfsoc_mmuart.c
+++ b/hw/char/mchp_pfsoc_mmuart.c
@@ -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 = MCHP_PFSOC_UART(dev);
+
+ 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;
+ 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));
- s = g_new0(MchpPfSoCMMUartState, 1);
+ memory_region_init(&s->container, OBJECT(s), "mchp.pfsoc.mmuart", 0x1000);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
- memory_region_init_io(&s->iomem, NULL, &mchp_pfsoc_mmuart_ops, s,
- "mchp.pfsoc.mmuart", 0x1000);
+ 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);
+}
- s->base = base;
- s->irq = irq;
+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);
- s->serial = serial_mm_init(sysmem, base, 2, irq, 399193, chr,
- DEVICE_LITTLE_ENDIAN);
+ qdev_prop_set_chr(dev, "chardev", chr);
+ sysbus_realize(sbd, &error_fatal);
- memory_region_add_subregion(sysmem, base + 0x20, &s->iomem);
+ memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(sbd, 0));
+ sysbus_connect_irq(sbd, 0, irq);
- return s;
+ return MCHP_PFSOC_UART(dev);
}
diff --git a/hw/char/shakti_uart.c b/hw/char/shakti_uart.c
index 6870821325..98b142c7df 100644
--- a/hw/char/shakti_uart.c
+++ b/hw/char/shakti_uart.c
@@ -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 = {
diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c
index 278e21c434..1c75f792b3 100644
--- a/hw/char/sifive_uart.c
+++ b/hw/char/sifive_uart.c
@@ -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 = {
diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
index b4fd40573a..85fe34f5f3 100644
--- a/hw/dma/sifive_pdma.c
+++ b/hw/dma/sifive_pdma.c
@@ -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;
}
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
index 2f084d3c8d..d7d1f91fa5 100644
--- a/hw/riscv/shakti_c.c
+++ b/hw/riscv/shakti_c.c
@@ -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)
diff --git a/include/hw/char/mchp_pfsoc_mmuart.h b/include/hw/char/mchp_pfsoc_mmuart.h
index f61990215f..b0e14ca355 100644
--- a/include/hw/char/mchp_pfsoc_mmuart.h
+++ b/include/hw/char/mchp_pfsoc_mmuart.h
@@ -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;
/**
diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/bitmanip_helper.c
index 5b2f795d03..f1b5e5549f 100644
--- a/target/riscv/bitmanip_helper.c
+++ b/target/riscv/bitmanip_helper.c
@@ -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)
-{
- return ((x & mask) << shift) | ((x & ~mask) >> shift);
-}
-
-static target_ulong do_grev(target_ulong rs1,
- target_ulong rs2,
- int bits)
+target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2)
{
- target_ulong x = rs1;
- int i, shift;
+ target_ulong result = 0;
- 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;
-}
-
-target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2)
-{
- return do_grev(rs1, rs2, TARGET_LONG_BITS);
-}
-
-target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2)
-{
- return do_grev(rs1, rs2, 32);
+ return result;
}
-static target_ulong do_gorc(target_ulong rs1,
- target_ulong rs2,
- int bits)
+target_ulong HELPER(clmulr)(target_ulong rs1, target_ulong rs2)
{
- target_ulong x = rs1;
- int i, shift;
+ target_ulong result = 0;
- 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;
}
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7c626d89cd..1d69d1887e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -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),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5896aca346..9e55b2f5b1 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -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
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 460eee9988..c7a5376227 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -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)
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 2cd921d51c..2f251dac1b 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -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
+# *** RV32 Zba Standard Extension ***
+sh1add 0010000 .......... 010 ..... 0110011 @r
+sh2add 0010000 .......... 100 ..... 0110011 @r
+sh3add 0010000 .......... 110 ..... 0110011 @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
+slli_uw 00001 ............ 001 ..... 0011011 @sh
+
+# *** RV32 Zbb Standard Extension ***
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
+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
-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
+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
-grev 0110100 .......... 101 ..... 0110011 @r
-gorc 0010100 .......... 101 ..... 0110011 @r
-sh1add 0010000 .......... 010 ..... 0110011 @r
-sh2add 0010000 .......... 100 ..... 0110011 @r
-sh3add 0010000 .......... 110 ..... 0110011 @r
-
-bseti 00101. ........... 001 ..... 0010011 @sh
-bclri 01001. ........... 001 ..... 0010011 @sh
-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
+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
-# *** RV64B Standard Extension (in addition to RV32B) ***
+# *** 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
-
-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
+# 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
-grevw 0110100 .......... 101 ..... 0111011 @r
-gorcw 0010100 .......... 101 ..... 0111011 @r
-sh1add_uw 0010000 .......... 010 ..... 0111011 @r
-sh2add_uw 0010000 .......... 100 ..... 0111011 @r
-sh3add_uw 0010000 .......... 110 ..... 0111011 @r
-add_uw 0000100 .......... 000 ..... 0111011 @r
-
-bsetiw 0010100 .......... 001 ..... 0011011 @sh5
-bclriw 0100100 .......... 001 ..... 0011011 @sh5
-binviw 0110100 .......... 001 ..... 0011011 @sh5
-sloiw 0010000 .......... 001 ..... 0011011 @sh5
-sroiw 0010000 .......... 101 ..... 0011011 @sh5
roriw 0110000 .......... 101 ..... 0011011 @sh5
-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
+
+# *** RV32 Zbc Standard Extension ***
+clmul 0000101 .......... 001 ..... 0110011 @r
+clmulh 0000101 .......... 011 ..... 0110011 @r
+clmulr 0000101 .......... 010 ..... 0110011 @r
-slli_uw 00001. ........... 001 ..... 0011011 @sh
+# *** 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
diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc
index b72e76255c..185c3e9a60 100644
--- a/target/riscv/insn_trans/trans_rvb.c.inc
+++ b/target/riscv/insn_trans/trans_rvb.c.inc
@@ -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));
-static bool trans_gorc(DisasContext *ctx, arg_gorc *a)
-{
- REQUIRE_EXT(ctx, RVB);
- return gen_shift(ctx, a, EXT_ZERO, gen_helper_gorc);
+ /* 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_gorci(DisasContext *ctx, arg_gorci *a)
+static bool trans_orc_b(DisasContext *ctx, arg_orc_b *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,157 +295,54 @@ GEN_TRANS_SHADD(1)
GEN_TRANS_SHADD(2)
GEN_TRANS_SHADD(3)
-static void gen_clzw(TCGv ret, TCGv arg1)
-{
- tcg_gen_clzi_tl(ret, ret, 64);
- tcg_gen_subi_tl(ret, ret, 32);
-}
-
-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);
-}
-
-static void gen_ctzw(TCGv ret, TCGv arg1)
-{
- tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
- tcg_gen_ctzi_tl(ret, ret, 64);
-}
-
-static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a)
-{
- REQUIRE_64BIT(ctx);
- REQUIRE_EXT(ctx, RVB);
- return gen_unary(ctx, a, EXT_NONE, gen_ctzw);
-}
-
-static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a)
+static bool trans_zext_h_32(DisasContext *ctx, arg_zext_h_32 *a)
{
- REQUIRE_64BIT(ctx);
- REQUIRE_EXT(ctx, RVB);
- ctx->w = true;
- return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl);
+ REQUIRE_32BIT(ctx);
+ REQUIRE_ZBB(ctx);
+ return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16u_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)
+static bool trans_zext_h_64(DisasContext *ctx, arg_zext_h_64 *a)
{
REQUIRE_64BIT(ctx);
- REQUIRE_EXT(ctx, RVB);
- return gen_arith(ctx, a, EXT_NONE, gen_packw);
+ REQUIRE_ZBB(ctx);
+ return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16u_tl);
}
-static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2)
+static void gen_clzw(TCGv ret, TCGv arg1)
{
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_gen_shli_tl(t, arg1, 32);
+ tcg_gen_clzi_tl(ret, t, 32);
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)
+static bool trans_clzw(DisasContext *ctx, arg_clzw *a)
{
REQUIRE_64BIT(ctx);
- REQUIRE_EXT(ctx, RVB);
- ctx->w = true;
- return gen_shift(ctx, a, EXT_NONE, gen_slo);
+ REQUIRE_ZBB(ctx);
+ return gen_unary(ctx, a, EXT_NONE, gen_clzw);
}
-static bool trans_sloiw(DisasContext *ctx, arg_sloiw *a)
+static void gen_ctzw(TCGv ret, TCGv arg1)
{
- REQUIRE_64BIT(ctx);
- REQUIRE_EXT(ctx, RVB);
- ctx->w = true;
- return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_slo);
+ tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
+ tcg_gen_ctzi_tl(ret, ret, 64);
}
-static bool trans_srow(DisasContext *ctx, arg_srow *a)
+static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a)
{
REQUIRE_64BIT(ctx);
- REQUIRE_EXT(ctx, RVB);
- ctx->w = true;
- return gen_shift(ctx, a, EXT_ZERO, gen_sro);
+ REQUIRE_ZBB(ctx);
+ return gen_unary(ctx, a, EXT_NONE, gen_ctzw);
}
-static bool trans_sroiw(DisasContext *ctx, arg_sroiw *a)
+static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a)
{
REQUIRE_64BIT(ctx);
- REQUIRE_EXT(ctx, RVB);
+ REQUIRE_ZBB(ctx);
ctx->w = true;
- return gen_shift_imm_tl(ctx, a, EXT_ZERO, gen_sro);
+ return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl);
}
static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
@@ -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);
+}
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 74b33fa3c9..d2442f0cf5 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -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;
- }
- /* Remember the state change for the rest of the TB. */
- ctx->mstatus_fs = MSTATUS_FS;
+ 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();
- sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
+ 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);
+ }
- 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 && ctx->mstatus_hs_fs != MSTATUS_FS) {
+ /* Remember the stage change for the rest of the TB. */
+ ctx->mstatus_hs_fs = MSTATUS_FS;
- 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);