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:
commit
3c01933983
157
disas/riscv.c
157
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:
|
||||
|
@ -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 = {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user