diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2021-10-07 07:18:39 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-10-07 07:18:39 -0700 |
commit | 3c019339830affe7974b738e0c2b71bd28778ef0 (patch) | |
tree | 66718f21492d05ef2bc63d0a9bcb3ddc9c1a0d82 | |
parent | ca61fa4b803e5d0abaf6f1ceb690f23bb78a4def (diff) | |
parent | 9ae6ecd848dcd1b32003526ab65a0d4c644dfb07 (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.c | 157 | ||||
-rw-r--r-- | hw/char/ibex_uart.c | 1 | ||||
-rw-r--r-- | hw/char/mchp_pfsoc_mmuart.c | 116 | ||||
-rw-r--r-- | hw/char/shakti_uart.c | 1 | ||||
-rw-r--r-- | hw/char/sifive_uart.c | 1 | ||||
-rw-r--r-- | hw/dma/sifive_pdma.c | 13 | ||||
-rw-r--r-- | hw/riscv/shakti_c.c | 7 | ||||
-rw-r--r-- | include/hw/char/mchp_pfsoc_mmuart.h | 17 | ||||
-rw-r--r-- | target/riscv/bitmanip_helper.c | 65 | ||||
-rw-r--r-- | target/riscv/cpu.c | 30 | ||||
-rw-r--r-- | target/riscv/cpu.h | 11 | ||||
-rw-r--r-- | target/riscv/helper.h | 6 | ||||
-rw-r--r-- | target/riscv/insn32.decode | 115 | ||||
-rw-r--r-- | target/riscv/insn_trans/trans_rvb.c.inc | 419 | ||||
-rw-r--r-- | target/riscv/translate.c | 36 |
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); |