diff options
161 files changed, 4300 insertions, 2924 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 846b81e3ec..bb96a00db0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -489,7 +489,7 @@ S: Supported F: include/system/kvm_xen.h F: target/i386/kvm/xen* F: hw/i386/kvm/xen* -F: tests/avocado/kvm_xen_guest.py +F: tests/functional/test_x86_64_kvm_xen.py Guest CPU Cores (other accelerators) ------------------------------------ @@ -1157,6 +1157,7 @@ F: hw/*/microbit*.c F: include/hw/*/nrf51*.h F: include/hw/*/microbit*.h F: tests/qtest/microbit-test.c +F: tests/functional/test_arm_microbit.py F: docs/system/arm/nrf.rst ARM PL011 Rust device @@ -4207,7 +4208,6 @@ F: tests/tcg/Makefile.target Integration Testing with the Avocado framework W: https://trello.com/b/6Qi1pxVn/avocado-qemu R: Cleber Rosa <crosa@redhat.com> -R: Philippe Mathieu-Daudé <philmd@linaro.org> S: Odd Fixes F: tests/avocado/ diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index d48b82a932..8b773d8847 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -249,7 +249,20 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, vaddr pc, return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); } -/* Might cause an exception, so have a longjmp destination ready */ +/** + * tb_lookup: + * @cpu: CPU that will execute the returned translation block + * @pc: guest PC + * @cs_base: arch-specific value associated with translation block + * @flags: arch-specific translation block flags + * @cflags: CF_* flags + * + * Look up a translation block inside the QHT using @pc, @cs_base, @flags and + * @cflags. Uses @cpu's tb_jmp_cache. Might cause an exception, so have a + * longjmp destination ready. + * + * Returns: an existing translation block or NULL. + */ static inline TranslationBlock *tb_lookup(CPUState *cpu, vaddr pc, uint64_t cs_base, uint32_t flags, uint32_t cflags) diff --git a/accel/tcg/internal-target.h b/accel/tcg/internal-target.h index a664be02cc..2cdf11c905 100644 --- a/accel/tcg/internal-target.h +++ b/accel/tcg/internal-target.h @@ -12,6 +12,7 @@ #include "exec/exec-all.h" #include "exec/translation-block.h" #include "tb-internal.h" +#include "tcg-target-mo.h" /* * Access to the various translations structures need to be serialised diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index d56ca13cdd..d4189c7386 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -532,9 +532,25 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } /* + * Insert TB into the corresponding region tree before publishing it + * through QHT. Otherwise rewinding happened in the TB might fail to + * lookup itself using host PC. + */ + tcg_tb_insert(tb); + + /* * If the TB is not associated with a physical RAM page then it must be - * a temporary one-insn TB, and we have nothing left to do. Return early - * before attempting to link to other TBs or add to the lookup table. + * a temporary one-insn TB. + * + * Such TBs must be added to region trees in order to make sure that + * restore_state_to_opc() - which on some architectures is not limited to + * rewinding, but also affects exception handling! - is called when such a + * TB causes an exception. + * + * At the same time, temporary one-insn TBs must be executed at most once, + * because subsequent reads from, e.g., I/O memory may return different + * values. So return early before attempting to link to other TBs or add + * to the QHT. */ if (tb_page_addr0(tb) == -1) { assert_no_pages_locked(); @@ -542,13 +558,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } /* - * Insert TB into the corresponding region tree before publishing it - * through QHT. Otherwise rewinding happened in the TB might fail to - * lookup itself using host PC. - */ - tcg_tb_insert(tb); - - /* * No explicit memory barrier is required -- tb_link_page() makes the * TB visible in a consistent state. */ diff --git a/crypto/pbkdf.c b/crypto/pbkdf.c index 0dd7c3aeaa..2989fc0a40 100644 --- a/crypto/pbkdf.c +++ b/crypto/pbkdf.c @@ -107,7 +107,7 @@ static void *threaded_qcrypto_pbkdf2_count_iters(void *data) size_t nsalt = iters_data->nsalt; size_t nout = iters_data->nout; Error **errp = iters_data->errp; - + size_t scaled = 0; uint64_t ret = -1; g_autofree uint8_t *out = g_new(uint8_t, nout); uint64_t iterations = (1 << 15); @@ -131,7 +131,17 @@ static void *threaded_qcrypto_pbkdf2_count_iters(void *data) delta_ms = end_ms - start_ms; - if (delta_ms == 0) { /* sanity check */ + /* + * For very small 'iterations' values, CPU (or crypto + * accelerator) might be fast enough that the scheduler + * hasn't incremented getrusage() data, or incremented + * it by a very small amount, resulting in delta_ms == 0. + * Once we've scaled 'iterations' x10, 5 times, we really + * should be seeing delta_ms != 0, so sanity check at + * that point. + */ + if (scaled > 5 && + delta_ms == 0) { /* sanity check */ error_setg(errp, "Unable to get accurate CPU usage"); goto cleanup; } else if (delta_ms > 500) { @@ -141,6 +151,7 @@ static void *threaded_qcrypto_pbkdf2_count_iters(void *data) } else { iterations = (iterations * 1000 / delta_ms); } + scaled++; } iterations = iterations * 1000 / delta_ms; diff --git a/disas/riscv.c b/disas/riscv.c index 9c1e332dde..4075ed6bfe 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -2611,7 +2611,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) break; case 2: op = rv_op_c_li; break; case 3: - if (dec->cfg->ext_zcmop) { + if (dec->cfg && dec->cfg->ext_zcmop) { if ((((inst >> 2) & 0b111111) == 0b100000) && (((inst >> 11) & 0b11) == 0b0)) { unsigned int cmop_code = 0; @@ -2712,7 +2712,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) op = rv_op_c_sqsp; } else { op = rv_op_c_fsdsp; - if (dec->cfg->ext_zcmp && ((inst >> 12) & 0b01)) { + if (dec->cfg && dec->cfg->ext_zcmp && ((inst >> 12) & 0b01)) { switch ((inst >> 8) & 0b01111) { case 8: if (((inst >> 4) & 0b01111) >= 4) { @@ -2738,7 +2738,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) } else { switch ((inst >> 10) & 0b011) { case 0: - if (!dec->cfg->ext_zcmt) { + if (dec->cfg && !dec->cfg->ext_zcmt) { break; } if (((inst >> 2) & 0xFF) >= 32) { @@ -2748,7 +2748,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) } break; case 3: - if (!dec->cfg->ext_zcmp) { + if (dec->cfg && !dec->cfg->ext_zcmp) { break; } switch ((inst >> 5) & 0b011) { @@ -2956,7 +2956,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) break; case 5: op = rv_op_auipc; - if (dec->cfg->ext_zicfilp && + if (dec->cfg && dec->cfg->ext_zicfilp && (((inst >> 7) & 0b11111) == 0b00000)) { op = rv_op_lpad; } @@ -4058,7 +4058,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 2: op = rv_op_csrrs; break; case 3: op = rv_op_csrrc; break; case 4: - if (dec->cfg->ext_zimop) { + if (dec->cfg && dec->cfg->ext_zimop) { int imm_mop5, imm_mop3, reg_num; if ((extract32(inst, 22, 10) & 0b1011001111) == 0b1000000111) { @@ -5112,28 +5112,28 @@ static GString *format_inst(size_t tab, rv_decode *dec) g_string_append(buf, rv_ireg_name_sym[dec->rs2]); break; case '3': - if (dec->cfg->ext_zfinx) { + if (dec->cfg && dec->cfg->ext_zfinx) { g_string_append(buf, rv_ireg_name_sym[dec->rd]); } else { g_string_append(buf, rv_freg_name_sym[dec->rd]); } break; case '4': - if (dec->cfg->ext_zfinx) { + if (dec->cfg && dec->cfg->ext_zfinx) { g_string_append(buf, rv_ireg_name_sym[dec->rs1]); } else { g_string_append(buf, rv_freg_name_sym[dec->rs1]); } break; case '5': - if (dec->cfg->ext_zfinx) { + if (dec->cfg && dec->cfg->ext_zfinx) { g_string_append(buf, rv_ireg_name_sym[dec->rs2]); } else { g_string_append(buf, rv_freg_name_sym[dec->rs2]); } break; case '6': - if (dec->cfg->ext_zfinx) { + if (dec->cfg && dec->cfg->ext_zfinx) { g_string_append(buf, rv_ireg_name_sym[dec->rs3]); } else { g_string_append(buf, rv_freg_name_sym[dec->rs3]); @@ -5439,7 +5439,8 @@ static GString *disasm_inst(rv_isa isa, uint64_t pc, rv_inst inst, const rv_opcode_data *opcode_data = decoders[i].opcode_data; void (*decode_func)(rv_decode *, rv_isa) = decoders[i].decode_func; - if (guard_func(cfg)) { + /* always_true_p don't dereference cfg */ + if (((i == 0) || cfg) && guard_func(cfg)) { dec.opcode_data = opcode_data; decode_func(&dec, isa); if (dec.op != rv_op_illegal) diff --git a/docs/devel/tcg-ops.rst b/docs/devel/tcg-ops.rst index d46b625e0e..6608a29376 100644 --- a/docs/devel/tcg-ops.rst +++ b/docs/devel/tcg-ops.rst @@ -712,10 +712,9 @@ QEMU specific operations Host vector operations ---------------------- -All of the vector ops have two parameters, ``TCGOP_VECL`` & ``TCGOP_VECE``. -The former specifies the length of the vector in log2 64-bit units; the -latter specifies the length of the element (if applicable) in log2 8-bit units. -E.g. VECL = 1 -> 64 << 1 -> v128, and VECE = 2 -> 1 << 2 -> i32. +All of the vector ops have two parameters, ``TCGOP_TYPE`` & ``TCGOP_VECE``. +The former specifies the length of the vector as a TCGType; the latter +specifies the length of the element (if applicable) in log2 8-bit units. .. list-table:: @@ -729,7 +728,7 @@ E.g. VECL = 1 -> 64 << 1 -> v128, and VECE = 2 -> 1 << 2 -> i32. * - dup_vec *v0*, *r1* - - | Duplicate the low N bits of *r1* into VECL/VECE copies across *v0*. + - | Duplicate the low N bits of *r1* into TYPE/VECE copies across *v0*. * - dupi_vec *v0*, *c* @@ -738,7 +737,7 @@ E.g. VECL = 1 -> 64 << 1 -> v128, and VECE = 2 -> 1 << 2 -> i32. * - dup2_vec *v0*, *r1*, *r2* - - | Duplicate *r2*:*r1* into VECL/64 copies across *v0*. This opcode is + - | Duplicate *r2*:*r1* into TYPE/64 copies across *v0*. This opcode is only present for 32-bit hosts. * - add_vec *v0*, *v1*, *v2* @@ -810,7 +809,7 @@ E.g. VECL = 1 -> 64 << 1 -> v128, and VECE = 2 -> 1 << 2 -> i32. .. code-block:: c - for (i = 0; i < VECL/VECE; ++i) { + for (i = 0; i < TYPE/VECE; ++i) { v0[i] = v1[i] << s2; } @@ -832,7 +831,7 @@ E.g. VECL = 1 -> 64 << 1 -> v128, and VECE = 2 -> 1 << 2 -> i32. .. code-block:: c - for (i = 0; i < VECL/VECE; ++i) { + for (i = 0; i < TYPE/VECE; ++i) { v0[i] = v1[i] << v2[i]; } diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst index fa4aa28eef..97fd6a0e7f 100644 --- a/docs/system/arm/aspeed.rst +++ b/docs/system/arm/aspeed.rst @@ -1,5 +1,5 @@ -Aspeed family boards (``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``, ``bletchley-bmc``, ``fuji-bmc``, ``fby35-bmc``, ``fp5280g2-bmc``, ``g220a-bmc``, ``palmetto-bmc``, ``qcom-dc-scm-v1-bmc``, ``qcom-firework-bmc``, ``quanta-q71l-bmc``, ``rainier-bmc``, ``romulus-bmc``, ``sonorapass-bmc``, ``supermicrox11-bmc``, ``supermicrox11spi-bmc``, ``tiogapass-bmc``, ``tacoma-bmc``, ``witherspoon-bmc``, ``yosemitev2-bmc``) -================================================================================================================================================================================================================================================================================================================================================================================================================================== +Aspeed family boards (``ast2500-evb``, ``ast2600-evb``, ``ast2700-evb``, ``bletchley-bmc``, ``fuji-bmc``, ``fby35-bmc``, ``fp5280g2-bmc``, ``g220a-bmc``, ``palmetto-bmc``, ``qcom-dc-scm-v1-bmc``, ``qcom-firework-bmc``, ``quanta-q71l-bmc``, ``rainier-bmc``, ``romulus-bmc``, ``sonorapass-bmc``, ``supermicrox11-bmc``, ``supermicrox11spi-bmc``, ``tiogapass-bmc``, ``witherspoon-bmc``, ``yosemitev2-bmc``) +================================================================================================================================================================================================================================================================================================================================================================================================================== The QEMU Aspeed machines model BMCs of various OpenPOWER systems and Aspeed evaluation boards. They are based on different releases of the diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc index ebde42992f..fee05d0a86 100644 --- a/fpu/softfloat-parts.c.inc +++ b/fpu/softfloat-parts.c.inc @@ -198,7 +198,7 @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status, if (likely(frac_eqz(p))) { p->cls = float_class_zero; } else if (status->flush_inputs_to_zero) { - float_raise(float_flag_input_denormal, status); + float_raise(float_flag_input_denormal_flushed, status); p->cls = float_class_zero; frac_clear(p); } else { @@ -334,7 +334,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s, } frac_shr(p, frac_shift); } else if (s->flush_to_zero) { - flags |= float_flag_output_denormal; + flags |= float_flag_output_denormal_flushed; p->cls = float_class_zero; exp = 0; frac_clear(p); diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 8d75d66817..26f3a8dc87 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -132,7 +132,7 @@ this code that are retained. if (unlikely(soft_t ## _is_denormal(*a))) { \ *a = soft_t ## _set_sign(soft_t ## _zero, \ soft_t ## _is_neg(*a)); \ - float_raise(float_flag_input_denormal, s); \ + float_raise(float_flag_input_denormal_flushed, s); \ } \ } @@ -4848,7 +4848,7 @@ float128 float128_silence_nan(float128 a, float_status *status) static bool parts_squash_denormal(FloatParts64 p, float_status *status) { if (p.exp == 0 && p.frac != 0) { - float_raise(float_flag_input_denormal, status); + float_raise(float_flag_input_denormal_flushed, status); return true; } @@ -5017,7 +5017,7 @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign, } if ( zExp <= 0 ) { if (status->flush_to_zero) { - float_raise(float_flag_output_denormal, status); + float_raise(float_flag_output_denormal_flushed, status); return packFloatx80(zSign, 0, 0); } isTiny = status->tininess_before_rounding diff --git a/host/include/riscv/host/cpuinfo.h b/host/include/riscv/host/cpuinfo.h index cdc784e7b6..b2b53dbf62 100644 --- a/host/include/riscv/host/cpuinfo.h +++ b/host/include/riscv/host/cpuinfo.h @@ -9,8 +9,9 @@ #define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */ #define CPUINFO_ZBA (1u << 1) #define CPUINFO_ZBB (1u << 2) -#define CPUINFO_ZICOND (1u << 3) -#define CPUINFO_ZVE64X (1u << 4) +#define CPUINFO_ZBS (1u << 3) +#define CPUINFO_ZICOND (1u << 4) +#define CPUINFO_ZVE64X (1u << 5) /* Initialized with a constructor. */ extern unsigned cpuinfo; diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index e779b5af95..256013ca80 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -516,6 +516,7 @@ config FSL_IMX6 select PL310 # cache controller select PCI_EXPRESS_DESIGNWARE select SDHCI + select OR_IRQ config ASPEED_SOC bool @@ -573,6 +574,7 @@ config FSL_IMX7 select WDT_IMX2 select PCI_EXPRESS_DESIGNWARE select SDHCI + select OR_IRQ select UNIMP config ARM_SMMUV3 diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index a18d4ed1fb..d9418e2b9f 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -364,11 +364,11 @@ static void connect_serial_hds_to_uarts(AspeedMachineState *bmc) int uart_chosen = bmc->uart_chosen ? bmc->uart_chosen : amc->uart_default; aspeed_soc_uart_set_chr(s, uart_chosen, serial_hd(0)); - for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; i++, uart++) { + for (int i = 1, uart = sc->uarts_base; i < sc->uarts_num; uart++) { if (uart == uart_chosen) { continue; } - aspeed_soc_uart_set_chr(s, uart, serial_hd(i)); + aspeed_soc_uart_set_chr(s, uart, serial_hd(i++)); } } @@ -409,6 +409,12 @@ static void aspeed_machine_init(MachineState *machine) OBJECT(get_system_memory()), &error_abort); object_property_set_link(OBJECT(bmc->soc), "dram", OBJECT(machine->ram), &error_abort); + if (amc->sdhci_wp_inverted) { + for (i = 0; i < bmc->soc->sdhci.num_slots; i++) { + object_property_set_bool(OBJECT(&bmc->soc->sdhci.slots[i]), + "wp-inverted", true, &error_abort); + } + } if (machine->kernel_filename) { /* * When booting with a -kernel command line there is no u-boot @@ -450,14 +456,14 @@ static void aspeed_machine_init(MachineState *machine) amc->i2c_init(bmc); } - for (i = 0; i < bmc->soc->sdhci.num_slots; i++) { + for (i = 0; i < bmc->soc->sdhci.num_slots && defaults_enabled(); i++) { sdhci_attach_drive(&bmc->soc->sdhci.slots[i], drive_get(IF_SD, 0, i), false, false); } boot_emmc = sc->boot_from_emmc(bmc->soc); - if (bmc->soc->emmc.num_slots) { + if (bmc->soc->emmc.num_slots && defaults_enabled()) { emmc0 = drive_get(IF_SD, 0, bmc->soc->sdhci.num_slots); sdhci_attach_drive(&bmc->soc->emmc.slots[0], emmc0, true, boot_emmc); } @@ -1415,6 +1421,7 @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data) amc->num_cs = 1; amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON | ASPEED_MAC2_ON | ASPEED_MAC3_ON; + amc->sdhci_wp_inverted = true; amc->i2c_init = ast2600_evb_i2c_init; mc->default_ram_size = 1 * GiB; aspeed_machine_class_init_cpus_defaults(mc); diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index fee3755837..4114e15ddd 100644 --- a/hw/arm/aspeed_ast27x0.c +++ b/hw/arm/aspeed_ast27x0.c @@ -66,6 +66,7 @@ static const hwaddr aspeed_soc_ast2700_memmap[] = { [ASPEED_DEV_GPIO] = 0x14C0B000, [ASPEED_DEV_RTC] = 0x12C0F000, [ASPEED_DEV_SDHCI] = 0x14080000, + [ASPEED_DEV_TIMER1] = 0x12C10000, }; #define AST2700_MAX_IRQ 256 @@ -397,6 +398,9 @@ static void aspeed_soc_ast2700_init(Object *obj) object_initialize_child(obj, "emmc-controller.sdhci", &s->emmc.slots[0], TYPE_SYSBUS_SDHCI); + + snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname); + object_initialize_child(obj, "timerctrl", &s->timerctrl, typename); } /* @@ -716,6 +720,19 @@ static void aspeed_soc_ast2700_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->emmc), 0, aspeed_soc_get_irq(s, ASPEED_DEV_EMMC)); + /* Timer */ + object_property_set_link(OBJECT(&s->timerctrl), "scu", OBJECT(&s->scu), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->timerctrl), errp)) { + return; + } + aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->timerctrl), 0, + sc->memmap[ASPEED_DEV_TIMER1]); + for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) { + irq = aspeed_soc_get_irq(s, ASPEED_DEV_TIMER1 + i); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq); + } + create_unimplemented_device("ast2700.dpmcu", 0x11000000, 0x40000); create_unimplemented_device("ast2700.iomem0", 0x12000000, 0x01000000); create_unimplemented_device("ast2700.iomem1", 0x14000000, 0x01000000); diff --git a/hw/arm/b-l475e-iot01a.c b/hw/arm/b-l475e-iot01a.c index 5002a40f06..c9a5209216 100644 --- a/hw/arm/b-l475e-iot01a.c +++ b/hw/arm/b-l475e-iot01a.c @@ -82,7 +82,7 @@ static void bl475e_init(MachineState *machine) sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal); sc = STM32L4X5_SOC_GET_CLASS(&s->soc); - armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0, + armv7m_load_kernel(s->soc.armv7m.cpu, machine->kernel_filename, 0, sc->flash_size); if (object_class_by_name(TYPE_DM163)) { diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index ac8c66e242..88b9ccff49 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -106,6 +106,8 @@ static void fsl_imx6_init(Object *obj) object_initialize_child(obj, "eth", &s->eth, TYPE_IMX_ENET); object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST); + object_initialize_child(obj, "pcie4-msi-irq", &s->pcie4_msi_irq, + TYPE_OR_IRQ); } static void fsl_imx6_realize(DeviceState *dev, Error **errp) @@ -435,14 +437,23 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX6_PCIe_REG_ADDR); + object_property_set_int(OBJECT(&s->pcie4_msi_irq), "num-lines", 2, + &error_abort); + qdev_realize(DEVICE(&s->pcie4_msi_irq), NULL, &error_abort); + + irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE4_MSI_IRQ); + qdev_connect_gpio_out(DEVICE(&s->pcie4_msi_irq), 0, irq); + irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE1_IRQ); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq); irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE2_IRQ); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq); irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE3_IRQ); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq); - irq = qdev_get_gpio_in(DEVICE(&s->a9mpcore), FSL_IMX6_PCIE4_IRQ); + irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 0); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq); + irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 1); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4, irq); /* * PCIe PHY diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c index 05e3389fbe..004bf49937 100644 --- a/hw/arm/fsl-imx7.c +++ b/hw/arm/fsl-imx7.c @@ -150,6 +150,8 @@ static void fsl_imx7_init(Object *obj) * PCIE */ object_initialize_child(obj, "pcie", &s->pcie, TYPE_DESIGNWARE_PCIE_HOST); + object_initialize_child(obj, "pcie4-msi-irq", &s->pcie4_msi_irq, + TYPE_OR_IRQ); /* * USBs @@ -597,14 +599,23 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp) sysbus_realize(SYS_BUS_DEVICE(&s->pcie), &error_abort); sysbus_mmio_map(SYS_BUS_DEVICE(&s->pcie), 0, FSL_IMX7_PCIE_REG_ADDR); + object_property_set_int(OBJECT(&s->pcie4_msi_irq), "num-lines", 2, + &error_abort); + qdev_realize(DEVICE(&s->pcie4_msi_irq), NULL, &error_abort); + + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_MSI_IRQ); + qdev_connect_gpio_out(DEVICE(&s->pcie4_msi_irq), 0, irq); + irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTA_IRQ); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 0, irq); irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTB_IRQ); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 1, irq); irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTC_IRQ); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 2, irq); - irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), FSL_IMX7_PCI_INTD_IRQ); + irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 0); sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 3, irq); + irq = qdev_get_gpio_in(DEVICE(&s->pcie4_msi_irq), 1); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->pcie), 4, irq); /* * USBs diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c index 374fbcb361..3f56fb45ce 100644 --- a/hw/arm/microbit.c +++ b/hw/arm/microbit.c @@ -56,7 +56,7 @@ static void microbit_init(MachineState *machine) memory_region_add_subregion_overlap(&s->nrf51.container, NRF51_TWI_BASE, mr, -1); - armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + armv7m_load_kernel(s->nrf51.armv7m.cpu, machine->kernel_filename, 0, s->nrf51.flash_size); } diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c index 0136e419bf..d3a9f1b03a 100644 --- a/hw/arm/mps2-tz.c +++ b/hw/arm/mps2-tz.c @@ -1211,7 +1211,7 @@ static void mps2tz_common_init(MachineState *machine) mms->remap_irq); } - armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + armv7m_load_kernel(mms->iotkit.armv7m[0].cpu, machine->kernel_filename, 0, boot_ram_size(mms)); } diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index efb3500742..56b2af40f1 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -460,7 +460,7 @@ static void mps2_common_init(MachineState *machine) qdev_get_gpio_in(armv7m, mmc->fpga_type == FPGA_AN511 ? 47 : 13)); - armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + armv7m_load_kernel(mms->armv7m.cpu, machine->kernel_filename, 0, 0x400000); } diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c index 5c415abe85..9b20f1e2c9 100644 --- a/hw/arm/msf2-som.c +++ b/hw/arm/msf2-som.c @@ -92,7 +92,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine) cs_line = qdev_get_gpio_in_named(spi_flash, SSI_GPIO_CS, 0); sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line); - armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + armv7m_load_kernel(soc->armv7m.cpu, machine->kernel_filename, 0, soc->envm_size); } diff --git a/hw/arm/musca.c b/hw/arm/musca.c index 3c3b534cb7..e9c092abc3 100644 --- a/hw/arm/musca.c +++ b/hw/arm/musca.c @@ -590,7 +590,7 @@ static void musca_init(MachineState *machine) "cfg_sec_resp", 0)); } - armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + armv7m_load_kernel(mms->sse.armv7m[0].cpu, machine->kernel_filename, 0, 0x2000000); } diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c index 8b1a9a2437..df793c77fe 100644 --- a/hw/arm/netduino2.c +++ b/hw/arm/netduino2.c @@ -48,7 +48,7 @@ static void netduino2_init(MachineState *machine) qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + armv7m_load_kernel(STM32F205_SOC(dev)->armv7m.cpu, machine->kernel_filename, 0, FLASH_SIZE); } diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c index bccd100354..81b6334cf7 100644 --- a/hw/arm/netduinoplus2.c +++ b/hw/arm/netduinoplus2.c @@ -48,7 +48,7 @@ static void netduinoplus2_init(MachineState *machine) qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - armv7m_load_kernel(ARM_CPU(first_cpu), + armv7m_load_kernel(STM32F405_SOC(dev)->armv7m.cpu, machine->kernel_filename, 0, FLASH_SIZE); } diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c index 37dd4cf5f4..dee06ab565 100644 --- a/hw/arm/nrf51_soc.c +++ b/hw/arm/nrf51_soc.c @@ -76,16 +76,16 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) } /* This clock doesn't need migration because it is fixed-frequency */ clock_set_hz(s->sysclk, HCLK_FRQ); - qdev_connect_clock_in(DEVICE(&s->cpu), "cpuclk", s->sysclk); + qdev_connect_clock_in(DEVICE(&s->armv7m), "cpuclk", s->sysclk); /* * This SoC has no systick device, so don't connect refclk. * TODO: model the lack of systick (currently the armv7m object * will always provide one). */ - object_property_set_link(OBJECT(&s->cpu), "memory", OBJECT(&s->container), + object_property_set_link(OBJECT(&s->armv7m), "memory", OBJECT(&s->container), &error_abort); - if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu), errp)) { + if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) { return; } @@ -104,7 +104,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0); memory_region_add_subregion_overlap(&s->container, NRF51_UART_BASE, mr, 0); sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart), 0, - qdev_get_gpio_in(DEVICE(&s->cpu), + qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(NRF51_UART_BASE))); /* RNG */ @@ -115,7 +115,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0); memory_region_add_subregion_overlap(&s->container, NRF51_RNG_BASE, mr, 0); sysbus_connect_irq(SYS_BUS_DEVICE(&s->rng), 0, - qdev_get_gpio_in(DEVICE(&s->cpu), + qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(NRF51_RNG_BASE))); /* UICR, FICR, NVMC, FLASH */ @@ -161,7 +161,7 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->timer[i]), 0, base_addr); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer[i]), 0, - qdev_get_gpio_in(DEVICE(&s->cpu), + qdev_get_gpio_in(DEVICE(&s->armv7m), BASE_TO_IRQ(base_addr))); } @@ -185,10 +185,10 @@ static void nrf51_soc_init(Object *obj) memory_region_init(&s->container, obj, "nrf51-container", UINT64_MAX); - object_initialize_child(OBJECT(s), "armv6m", &s->cpu, TYPE_ARMV7M); - qdev_prop_set_string(DEVICE(&s->cpu), "cpu-type", + object_initialize_child(OBJECT(s), "armv6m", &s->armv7m, TYPE_ARMV7M); + qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type", ARM_CPU_TYPE_NAME("cortex-m0")); - qdev_prop_set_uint32(DEVICE(&s->cpu), "num-irq", 32); + qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", 32); object_initialize_child(obj, "uart", &s->uart, TYPE_NRF51_UART); object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev"); diff --git a/hw/arm/olimex-stm32-h405.c b/hw/arm/olimex-stm32-h405.c index 4ad7b043be..1f15620f9f 100644 --- a/hw/arm/olimex-stm32-h405.c +++ b/hw/arm/olimex-stm32-h405.c @@ -51,7 +51,7 @@ static void olimex_stm32_h405_init(MachineState *machine) qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - armv7m_load_kernel(ARM_CPU(first_cpu), + armv7m_load_kernel(STM32F405_SOC(dev)->armv7m.cpu, machine->kernel_filename, 0, FLASH_SIZE); } diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 1bba96df14..c3c3fd0410 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -8,6 +8,7 @@ */ #include "qemu/osdep.h" +#include "qemu/bitops.h" #include "qapi/error.h" #include "hw/core/split-irq.h" #include "hw/sysbus.h" @@ -49,6 +50,31 @@ #define NUM_IRQ_LINES 64 #define NUM_PRIO_BITS 3 +#define NUM_GPIO 7 +#define NUM_UART 4 +#define NUM_GPTM 4 +#define NUM_I2C 2 + +/* + * See Stellaris Data Sheet chapter 5.2.5 "System Control", + * Register 13 .. 17: Device Capabilities 0 .. 4 (DC0 .. DC4). + */ +#define DC1_WDT 3 +#define DC1_HIB 6 +#define DC1_MPU 7 +#define DC1_ADC 16 +#define DC1_PWM 20 +#define DC2_UART(n) (n) +#define DC2_SSI 4 +#define DC2_QEI(n) (8 + n) +#define DC2_I2C(n) (12 + 2 * n) +#define DC2_GPTM(n) (16 + n) +#define DC2_COMP(n) (24 + n) +#define DC4_GPIO(n) (n) +#define DC4_EMAC 28 + +#define DEV_CAP(_dc, _cap) extract32(board->dc##_dc, DC##_dc##_##_cap, 1) + typedef const struct { const char *name; uint32_t did0; @@ -101,7 +127,7 @@ static void ssys_update(ssys_state *s) qemu_set_irq(s->irq, (s->int_status & s->int_mask) != 0); } -static uint32_t pllcfg_sandstorm[16] = { +static const uint32_t pllcfg_sandstorm[16] = { 0x31c0, /* 1 Mhz */ 0x1ae0, /* 1.8432 Mhz */ 0x18c0, /* 2 Mhz */ @@ -120,7 +146,7 @@ static uint32_t pllcfg_sandstorm[16] = { 0x585b /* 8.192 Mhz */ }; -static uint32_t pllcfg_fury[16] = { +static const uint32_t pllcfg_fury[16] = { 0x3200, /* 1 Mhz */ 0x1b20, /* 1.8432 Mhz */ 0x1900, /* 2 Mhz */ @@ -964,7 +990,7 @@ static void stellaris_adc_init(Object *obj) } /* Board init. */ -static stellaris_board_info stellaris_boards[] = { +static const stellaris_board_info stellaris_boards[] = { { "LM3S811EVB", 0, 0x0032000e, @@ -989,19 +1015,20 @@ static stellaris_board_info stellaris_boards[] = { static void stellaris_init(MachineState *ms, stellaris_board_info *board) { - static const int uart_irq[] = {5, 6, 33, 34}; - static const int timer_irq[] = {19, 21, 23, 35}; - static const uint32_t gpio_addr[7] = + static const int uart_irq[NUM_UART] = {5, 6, 33, 34}; + static const int timer_irq[NUM_GPTM] = {19, 21, 23, 35}; + static const uint32_t gpio_addr[NUM_GPIO] = { 0x40004000, 0x40005000, 0x40006000, 0x40007000, 0x40024000, 0x40025000, 0x40026000}; - static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31}; + static const int gpio_irq[NUM_GPIO] = {0, 1, 2, 3, 4, 30, 31}; + static const uint32_t i2c_addr[NUM_I2C] = {0x40020000, 0x40021000}; + static const int i2c_irq[NUM_I2C] = {8, 37}; /* Memory map of SoC devices, from * Stellaris LM3S6965 Microcontroller Data Sheet (rev I) * http://www.ti.com/lit/ds/symlink/lm3s6965.pdf * * 40000000 wdtimer - * 40002000 i2c (unimplemented) * 40004000 GPIO * 40005000 GPIO * 40006000 GPIO @@ -1031,13 +1058,13 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) */ Object *soc_container; - DeviceState *gpio_dev[7], *nvic; - qemu_irq gpio_in[7][8]; - qemu_irq gpio_out[7][8]; + DeviceState *gpio_dev[NUM_GPIO], *armv7m, *nvic; + qemu_irq gpio_in[NUM_GPIO][8]; + qemu_irq gpio_out[NUM_GPIO][8]; qemu_irq adc; int sram_size; int flash_size; - I2CBus *i2c; + DeviceState *i2c_dev[NUM_I2C] = { }; DeviceState *dev; DeviceState *ssys_dev; int i; @@ -1095,25 +1122,26 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) qdev_prop_set_uint32(ssys_dev, "dc4", board->dc4); sysbus_realize_and_unref(SYS_BUS_DEVICE(ssys_dev), &error_fatal); - nvic = qdev_new(TYPE_ARMV7M); - object_property_add_child(soc_container, "v7m", OBJECT(nvic)); - qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES); - qdev_prop_set_uint8(nvic, "num-prio-bits", NUM_PRIO_BITS); - qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type); - qdev_prop_set_bit(nvic, "enable-bitband", true); - qdev_connect_clock_in(nvic, "cpuclk", + armv7m = qdev_new(TYPE_ARMV7M); + object_property_add_child(soc_container, "v7m", OBJECT(armv7m)); + qdev_prop_set_uint32(armv7m, "num-irq", NUM_IRQ_LINES); + qdev_prop_set_uint8(armv7m, "num-prio-bits", NUM_PRIO_BITS); + qdev_prop_set_string(armv7m, "cpu-type", ms->cpu_type); + qdev_prop_set_bit(armv7m, "enable-bitband", true); + qdev_connect_clock_in(armv7m, "cpuclk", qdev_get_clock_out(ssys_dev, "SYSCLK")); /* This SoC does not connect the systick reference clock */ - object_property_set_link(OBJECT(nvic), "memory", + object_property_set_link(OBJECT(armv7m), "memory", OBJECT(get_system_memory()), &error_abort); /* This will exit with an error if the user passed us a bad cpu_type */ - sysbus_realize_and_unref(SYS_BUS_DEVICE(nvic), &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(armv7m), &error_fatal); + nvic = armv7m; /* Now we can wire up the IRQ and MMIO of the system registers */ sysbus_mmio_map(SYS_BUS_DEVICE(ssys_dev), 0, 0x400fe000); sysbus_connect_irq(SYS_BUS_DEVICE(ssys_dev), 0, qdev_get_gpio_in(nvic, 28)); - if (board->dc1 & (1 << 16)) { + if (DEV_CAP(1, ADC)) { dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000, qdev_get_gpio_in(nvic, 14), qdev_get_gpio_in(nvic, 15), @@ -1124,8 +1152,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) } else { adc = NULL; } - for (i = 0; i < 4; i++) { - if (board->dc2 & (0x10000 << i)) { + for (i = 0; i < NUM_GPTM; i++) { + if (DEV_CAP(2, GPTM(i))) { SysBusDevice *sbd; dev = qdev_new(TYPE_STELLARIS_GPTM); @@ -1142,7 +1170,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) } } - if (board->dc1 & (1 << 3)) { /* watchdog present */ + if (DEV_CAP(1, WDT)) { dev = qdev_new(TYPE_LUMINARY_WATCHDOG); object_property_add_child(soc_container, "wdg", OBJECT(dev)); qdev_connect_clock_in(dev, "WDOGCLK", @@ -1158,8 +1186,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) } - for (i = 0; i < 7; i++) { - if (board->dc4 & (1 << i)) { + for (i = 0; i < NUM_GPIO; i++) { + if (DEV_CAP(4, GPIO(i))) { gpio_dev[i] = sysbus_create_simple("pl061_luminary", gpio_addr[i], qdev_get_gpio_in(nvic, gpio_irq[i])); @@ -1170,17 +1198,21 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) } } - if (board->dc2 & (1 << 12)) { - dev = sysbus_create_simple(TYPE_STELLARIS_I2C, 0x40020000, - qdev_get_gpio_in(nvic, 8)); - i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); - if (board->peripherals & BP_OLED_I2C) { - i2c_slave_create_simple(i2c, "ssd0303", 0x3d); + for (i = 0; i < NUM_I2C; i++) { + if (DEV_CAP(2, I2C(i))) { + i2c_dev[i] = sysbus_create_simple(TYPE_STELLARIS_I2C, i2c_addr[i], + qdev_get_gpio_in(nvic, + i2c_irq[i])); } } + if (board->peripherals & BP_OLED_I2C) { + I2CBus *bus = (I2CBus *)qdev_get_child_bus(i2c_dev[0], "i2c"); - for (i = 0; i < 4; i++) { - if (board->dc2 & (1 << i)) { + i2c_slave_create_simple(bus, "ssd0303", 0x3d); + } + + for (i = 0; i < NUM_UART; i++) { + if (DEV_CAP(2, UART(i))) { SysBusDevice *sbd; dev = qdev_new("pl011_luminary"); @@ -1192,7 +1224,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(nvic, uart_irq[i])); } } - if (board->dc2 & (1 << 4)) { + if (DEV_CAP(2, SSI)) { dev = sysbus_create_simple("pl022", 0x40008000, qdev_get_gpio_in(nvic, 7)); if (board->peripherals & BP_OLED_SSI) { @@ -1301,7 +1333,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) qemu_irq_raise(gpio_out[GPIO_D][0]); } } - if (board->dc4 & (1 << 28)) { + if (DEV_CAP(4, EMAC)) { DeviceState *enet; enet = qdev_new("stellaris_enet"); @@ -1356,8 +1388,6 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) /* Add dummy regions for the devices we don't implement yet, * so guest accesses don't cause unlogged crashes. */ - create_unimplemented_device("i2c-0", 0x40002000, 0x1000); - create_unimplemented_device("i2c-2", 0x40021000, 0x1000); create_unimplemented_device("PWM", 0x40028000, 0x1000); create_unimplemented_device("QEI-0", 0x4002c000, 0x1000); create_unimplemented_device("QEI-1", 0x4002d000, 0x1000); @@ -1365,7 +1395,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) create_unimplemented_device("hibernation", 0x400fc000, 0x1000); create_unimplemented_device("flash-control", 0x400fd000, 0x1000); - armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, 0, flash_size); + armv7m_load_kernel(ARMV7M(armv7m)->cpu, ms->kernel_filename, 0, flash_size); } /* FIXME: Figure out how to generate these from stellaris_boards. */ @@ -1379,6 +1409,10 @@ static void lm3s6965evb_init(MachineState *machine) stellaris_init(machine, &stellaris_boards[1]); } +/* + * Stellaris LM3S811 Evaluation Board Schematics: + * https://www.ti.com/lit/ug/symlink/spmu030.pdf + */ static void lm3s811evb_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -1395,6 +1429,10 @@ static const TypeInfo lm3s811evb_type = { .class_init = lm3s811evb_class_init, }; +/* + * Stellaris: LM3S6965 Evaluation Board Schematics: + * https://www.ti.com/lit/ug/symlink/spmu029.pdf + */ static void lm3s6965evb_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c index cc41935160..e6c1f5b8d7 100644 --- a/hw/arm/stm32vldiscovery.c +++ b/hw/arm/stm32vldiscovery.c @@ -51,7 +51,7 @@ static void stm32vldiscovery_init(MachineState *machine) qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - armv7m_load_kernel(ARM_CPU(first_cpu), + armv7m_load_kernel(STM32F100_SOC(dev)->armv7m.cpu, machine->kernel_filename, 0, FLASH_SIZE); } diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 7c353fde50..38b4865157 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -160,6 +160,7 @@ static void imx_serial_reset(IMXSerialState *s) s->ucr3 = 0x700; s->ubmr = 0; s->ubrc = 4; + s->ufcr = BIT(11) | BIT(0); fifo32_reset(&s->rx_fifo); timer_del(&s->ageing_timer); @@ -400,14 +401,14 @@ static void imx_put_data(void *opaque, uint32_t value) if (fifo32_num_used(&s->rx_fifo) >= rxtl) { s->usr1 |= USR1_RRDY; } - - imx_serial_rx_fifo_ageing_timer_restart(s); - s->usr2 |= USR2_RDR; s->uts1 &= ~UTS1_RXEMPTY; if (value & URXD_BRK) { s->usr2 |= USR2_BRCD; } + + imx_serial_rx_fifo_ageing_timer_restart(s); + imx_update(s); } diff --git a/hw/hppa/hppa_hardware.h b/hw/hppa/hppa_hardware.h index a9be7bb851..a276240967 100644 --- a/hw/hppa/hppa_hardware.h +++ b/hw/hppa/hppa_hardware.h @@ -49,4 +49,6 @@ #define CPU_HPA_CR_REG 7 /* store CPU HPA in cr7 (SeaBIOS internal) */ #define PIM_STORAGE_SIZE 600 /* storage size of pdc_pim_toc_struct (64bit) */ +#define RAM_MAP_HIGH 0x0100000000 /* memory above 3.75 GB is mapped here */ + #endif diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 8230f43e41..0dd1908214 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -283,16 +283,13 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine) cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type)); } - /* - * For now, treat address layout as if PSW_W is clear. - * TODO: create a proper hppa64 board model and load elf64 firmware. - */ + /* Initialize memory */ if (hppa_is_pa20(&cpu[0]->env)) { translate = translate_pa20; - ram_max = 0xf0000000; /* 3.75 GB (limited by 32-bit firmware) */ + ram_max = 256 * GiB; /* like HP rp8440 */ } else { translate = translate_pa10; - ram_max = 0xf0000000; /* 3.75 GB (32-bit CPU) */ + ram_max = FIRMWARE_START; /* 3.75 GB (32-bit CPU) */ } soft_power_reg = translate(NULL, HPA_POWER_BUTTON); @@ -320,7 +317,22 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine) info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB); machine->ram_size = ram_max; } - memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1); + if (machine->ram_size <= FIRMWARE_START) { + /* contiguous memory up to 3.75 GB RAM */ + memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1); + } else { + /* non-contiguous: Memory above 3.75 GB is mapped at RAM_MAP_HIGH */ + MemoryRegion *mem_region; + mem_region = g_new(MemoryRegion, 2); + memory_region_init_alias(&mem_region[0], &addr_space->parent_obj, + "LowMem", machine->ram, 0, FIRMWARE_START); + memory_region_init_alias(&mem_region[1], &addr_space->parent_obj, + "HighMem", machine->ram, FIRMWARE_START, + machine->ram_size - FIRMWARE_START); + memory_region_add_subregion_overlap(addr_space, 0, &mem_region[0], -1); + memory_region_add_subregion_overlap(addr_space, RAM_MAP_HIGH, + &mem_region[1], -1); + } return translate; } @@ -344,7 +356,6 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus, uint64_t kernel_entry = 0, kernel_low, kernel_high; MemoryRegion *addr_space = get_system_memory(); MemoryRegion *rom_region; - unsigned int smp_cpus = machine->smp.cpus; SysBusDevice *s; /* SCSI disk setup. */ @@ -470,8 +481,8 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus, kernel_low, kernel_high, kernel_entry, size / KiB); if (kernel_cmdline) { - cpu[0]->env.gr[24] = 0x4000; - pstrcpy_targphys("cmdline", cpu[0]->env.gr[24], + cpu[0]->env.cmdline_or_bootorder = 0x4000; + pstrcpy_targphys("cmdline", cpu[0]->env.cmdline_or_bootorder, TARGET_PAGE_SIZE, kernel_cmdline); } @@ -501,32 +512,22 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus, } load_image_targphys(initrd_filename, initrd_base, initrd_size); - cpu[0]->env.gr[23] = initrd_base; - cpu[0]->env.gr[22] = initrd_base + initrd_size; + cpu[0]->env.initrd_base = initrd_base; + cpu[0]->env.initrd_end = initrd_base + initrd_size; } } if (!kernel_entry) { /* When booting via firmware, tell firmware if we want interactive - * mode (kernel_entry=1), and to boot from CD (gr[24]='d') - * or hard disc * (gr[24]='c'). + * mode (kernel_entry=1), and to boot from CD (cmdline_or_bootorder='d') + * or hard disc (cmdline_or_bootorder='c'). */ kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0; - cpu[0]->env.gr[24] = machine->boot_config.order[0]; + cpu[0]->env.cmdline_or_bootorder = machine->boot_config.order[0]; } - /* We jump to the firmware entry routine and pass the - * various parameters in registers. After firmware initialization, - * firmware will start the Linux kernel with ramdisk and cmdline. - */ - cpu[0]->env.gr[26] = machine->ram_size; - cpu[0]->env.gr[25] = kernel_entry; - - /* tell firmware how many SMP CPUs to present in inventory table */ - cpu[0]->env.gr[21] = smp_cpus; - - /* tell firmware fw_cfg port */ - cpu[0]->env.gr[19] = FW_CFG_IO_BASE; + /* Keep initial kernel_entry for first boot */ + cpu[0]->env.kernel_entry = kernel_entry; } /* @@ -663,18 +664,19 @@ static void hppa_machine_reset(MachineState *ms, ResetType type) cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000; } - /* already initialized by machine_hppa_init()? */ - if (cpu[0]->env.gr[26] == ms->ram_size) { - return; - } - cpu[0]->env.gr[26] = ms->ram_size; - cpu[0]->env.gr[25] = 0; /* no firmware boot menu */ - cpu[0]->env.gr[24] = 'c'; - /* gr22/gr23 unused, no initrd while reboot. */ + cpu[0]->env.gr[25] = cpu[0]->env.kernel_entry; + cpu[0]->env.gr[24] = cpu[0]->env.cmdline_or_bootorder; + cpu[0]->env.gr[23] = cpu[0]->env.initrd_base; + cpu[0]->env.gr[22] = cpu[0]->env.initrd_end; cpu[0]->env.gr[21] = smp_cpus; - /* tell firmware fw_cfg port */ cpu[0]->env.gr[19] = FW_CFG_IO_BASE; + + /* reset static fields to avoid starting Linux kernel & initrd on reboot */ + cpu[0]->env.kernel_entry = 0; + cpu[0]->env.initrd_base = 0; + cpu[0]->env.initrd_end = 0; + cpu[0]->env.cmdline_or_bootorder = 'c'; } static void hppa_nmi(NMIState *n, int cpu_index, Error **errp) diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c index c3fc37b904..3e8c36e6a7 100644 --- a/hw/pci-host/designware.c +++ b/hw/pci-host/designware.c @@ -55,8 +55,6 @@ #define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff) #define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C -#define DESIGNWARE_PCIE_IRQ_MSI 3 - static DesignwarePCIEHost * designware_pcie_root_to_host(DesignwarePCIERoot *root) { @@ -90,7 +88,7 @@ static void designware_pcie_root_msi_write(void *opaque, hwaddr addr, root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable; if (root->msi.intr[0].status & ~root->msi.intr[0].mask) { - qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 1); + qemu_set_irq(host->pci.msi, 1); } } @@ -335,7 +333,7 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address, case DESIGNWARE_PCIE_MSI_INTR0_STATUS: root->msi.intr[0].status ^= val; if (!root->msi.intr[0].status) { - qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 0); + qemu_set_irq(host->pci.msi, 0); } break; @@ -680,6 +678,7 @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp) for (i = 0; i < ARRAY_SIZE(s->pci.irqs); i++) { sysbus_init_irq(sbd, &s->pci.irqs[i]); } + sysbus_init_irq(sbd, &s->pci.msi); memory_region_init_io(&s->mmio, OBJECT(s), diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 38aeba14ee..3af613d4e9 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -782,7 +782,6 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) s390mc->hpage_1m_allowed = true; s390mc->max_threads = 1; - mc->init = ccw_init; mc->reset = s390_machine_reset; mc->block_default_type = IF_VIRTIO; mc->no_cdrom = 1; @@ -852,6 +851,12 @@ static const TypeInfo ccw_machine_info = { }; #define DEFINE_CCW_MACHINE_IMPL(latest, ...) \ + static void MACHINE_VER_SYM(mach_init, ccw, __VA_ARGS__)(MachineState *mach) \ + { \ + current_mc = S390_CCW_MACHINE_CLASS(MACHINE_GET_CLASS(mach)); \ + MACHINE_VER_SYM(instance_options, ccw, __VA_ARGS__)(mach); \ + ccw_init(mach); \ + } \ static void MACHINE_VER_SYM(class_init, ccw, __VA_ARGS__)( \ ObjectClass *oc, \ void *data) \ @@ -859,24 +864,18 @@ static const TypeInfo ccw_machine_info = { MachineClass *mc = MACHINE_CLASS(oc); \ MACHINE_VER_SYM(class_options, ccw, __VA_ARGS__)(mc); \ mc->desc = "Virtual s390x machine (version " MACHINE_VER_STR(__VA_ARGS__) ")"; \ + mc->init = MACHINE_VER_SYM(mach_init, ccw, __VA_ARGS__); \ MACHINE_VER_DEPRECATION(__VA_ARGS__); \ if (latest) { \ mc->alias = "s390-ccw-virtio"; \ mc->is_default = true; \ } \ } \ - static void MACHINE_VER_SYM(instance_init, ccw, __VA_ARGS__)(Object *obj) \ - { \ - MachineState *machine = MACHINE(obj); \ - current_mc = S390_CCW_MACHINE_CLASS(MACHINE_GET_CLASS(machine)); \ - MACHINE_VER_SYM(instance_options, ccw, __VA_ARGS__)(machine); \ - } \ static const TypeInfo MACHINE_VER_SYM(info, ccw, __VA_ARGS__) = \ { \ .name = MACHINE_VER_TYPE_NAME("s390-ccw-virtio", __VA_ARGS__), \ .parent = TYPE_S390_CCW_MACHINE, \ .class_init = MACHINE_VER_SYM(class_init, ccw, __VA_ARGS__), \ - .instance_init = MACHINE_VER_SYM(instance_init, ccw, __VA_ARGS__), \ }; \ static void MACHINE_VER_SYM(register, ccw, __VA_ARGS__)(void) \ { \ diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 318587ff57..99dd4a4e95 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -274,6 +274,10 @@ static void sdhci_set_readonly(DeviceState *dev, bool level) { SDHCIState *s = (SDHCIState *)dev; + if (s->wp_inverted) { + level = !level; + } + if (level) { s->prnsts &= ~SDHC_WRITE_PROTECT; } else { @@ -1555,6 +1559,8 @@ static const Property sdhci_sysbus_properties[] = { false), DEFINE_PROP_LINK("dma", SDHCIState, dma_mr, TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_BOOL("wp-inverted", SDHCIState, + wp_inverted, false), }; static void sdhci_sysbus_init(Object *obj) diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c index 4868651ad4..ecda49574e 100644 --- a/hw/timer/aspeed_timer.c +++ b/hw/timer/aspeed_timer.c @@ -239,9 +239,8 @@ static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg) return value; } -static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size) +static uint64_t aspeed_timer_read_common(AspeedTimerCtrlState *s, hwaddr offset) { - AspeedTimerCtrlState *s = opaque; const int reg = (offset & 0xf) / 4; uint64_t value; @@ -256,10 +255,11 @@ static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size) value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg); break; default: - value = ASPEED_TIMER_GET_CLASS(s)->read(s, offset); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", + __func__, offset); + value = 0; break; } - trace_aspeed_timer_read(offset, size, value); return value; } @@ -431,12 +431,11 @@ static void aspeed_timer_set_ctrl2(AspeedTimerCtrlState *s, uint32_t value) trace_aspeed_timer_set_ctrl2(value); } -static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value, - unsigned size) +static void aspeed_timer_write_common(AspeedTimerCtrlState *s, hwaddr offset, + uint64_t value) { const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF); const int reg = (offset & 0xf) / 4; - AspeedTimerCtrlState *s = opaque; switch (offset) { /* Control Registers */ @@ -451,11 +450,25 @@ static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value, aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv); break; default: - ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", + __func__, offset); break; } } +static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size) +{ + AspeedTimerCtrlState *s = ASPEED_TIMER(opaque); + return ASPEED_TIMER_GET_CLASS(s)->read(s, offset); +} + +static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + AspeedTimerCtrlState *s = ASPEED_TIMER(opaque); + ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value); +} + static const MemoryRegionOps aspeed_timer_ops = { .read = aspeed_timer_read, .write = aspeed_timer_write, @@ -475,12 +488,15 @@ static uint64_t aspeed_2400_timer_read(AspeedTimerCtrlState *s, hwaddr offset) break; case 0x38: case 0x3C: - default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset); value = 0; break; + default: + value = aspeed_timer_read_common(s, offset); + break; } + trace_aspeed_timer_read(offset, value); return value; } @@ -495,10 +511,12 @@ static void aspeed_2400_timer_write(AspeedTimerCtrlState *s, hwaddr offset, break; case 0x38: case 0x3C: - default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset); break; + default: + aspeed_timer_write_common(s, offset, value); + break; } } @@ -514,12 +532,15 @@ static uint64_t aspeed_2500_timer_read(AspeedTimerCtrlState *s, hwaddr offset) value = s->ctrl3 & BIT(0); break; case 0x3C: - default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset); value = 0; break; + default: + value = aspeed_timer_read_common(s, offset); + break; } + trace_aspeed_timer_read(offset, value); return value; } @@ -548,8 +569,7 @@ static void aspeed_2500_timer_write(AspeedTimerCtrlState *s, hwaddr offset, break; default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", - __func__, offset); + aspeed_timer_write_common(s, offset, value); break; } } @@ -564,12 +584,15 @@ static uint64_t aspeed_2600_timer_read(AspeedTimerCtrlState *s, hwaddr offset) break; case 0x38: case 0x3C: - default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset); value = 0; break; + default: + value = aspeed_timer_read_common(s, offset); + break; } + trace_aspeed_timer_read(offset, value); return value; } @@ -586,10 +609,203 @@ static void aspeed_2600_timer_write(AspeedTimerCtrlState *s, hwaddr offset, aspeed_timer_set_ctrl(s, s->ctrl & ~tv); break; case 0x38: - default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, offset); break; + default: + aspeed_timer_write_common(s, offset, value); + break; + } +} + +static void aspeed_2700_timer_set_ctrl(AspeedTimerCtrlState *s, int index, + uint32_t reg) +{ + const uint8_t overflow_interrupt_mask = BIT(op_overflow_interrupt); + const uint8_t external_clock_mask = BIT(op_external_clock); + const uint8_t pulse_enable_mask = BIT(op_pulse_enable); + const uint8_t enable_mask = BIT(op_enable); + AspeedTimer *t; + uint8_t t_old; + uint8_t t_new; + int shift; + + /* + * Only 1 will set the specific bits to 1 + * Handle a dependency between the 'enable' and remaining three + * configuration bits - i.e. if more than one bit in the control set has + * set, including the 'enable' bit, perform configuration and then + * enable the timer. + * Interrupt Status bit should not be set. + */ + + t = &s->timers[index]; + shift = index * TIMER_CTRL_BITS; + + t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK; + t_new = reg & TIMER_CTRL_MASK; + + if (!(t_old & external_clock_mask) && + (t_new & external_clock_mask)) { + aspeed_timer_ctrl_external_clock(t, true); + s->ctrl = deposit32(s->ctrl, shift + op_external_clock, 1, 1); + } + + if (!(t_old & overflow_interrupt_mask) && + (t_new & overflow_interrupt_mask)) { + aspeed_timer_ctrl_overflow_interrupt(t, true); + s->ctrl = deposit32(s->ctrl, shift + op_overflow_interrupt, 1, 1); + } + + + if (!(t_old & pulse_enable_mask) && + (t_new & pulse_enable_mask)) { + aspeed_timer_ctrl_pulse_enable(t, true); + s->ctrl = deposit32(s->ctrl, shift + op_pulse_enable, 1, 1); + } + + /* If we are enabling, do so last */ + if (!(t_old & enable_mask) && + (t_new & enable_mask)) { + aspeed_timer_ctrl_enable(t, true); + s->ctrl = deposit32(s->ctrl, shift + op_enable, 1, 1); + } +} + +static void aspeed_2700_timer_clear_ctrl(AspeedTimerCtrlState *s, int index, + uint32_t reg) +{ + const uint8_t overflow_interrupt_mask = BIT(op_overflow_interrupt); + const uint8_t external_clock_mask = BIT(op_external_clock); + const uint8_t pulse_enable_mask = BIT(op_pulse_enable); + const uint8_t enable_mask = BIT(op_enable); + AspeedTimer *t; + uint8_t t_old; + uint8_t t_new; + int shift; + + /* + * Only 1 will clear the specific bits to 0 + * Handle a dependency between the 'enable' and remaining three + * configuration bits - i.e. if more than one bit in the control set has + * clear, including the 'enable' bit, then disable the timer and perform + * configuration + */ + + t = &s->timers[index]; + shift = index * TIMER_CTRL_BITS; + + t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK; + t_new = reg & TIMER_CTRL_MASK; + + /* If we are disabling, do so first */ + if ((t_old & enable_mask) && + (t_new & enable_mask)) { + aspeed_timer_ctrl_enable(t, false); + s->ctrl = deposit32(s->ctrl, shift + op_enable, 1, 0); + } + + if ((t_old & external_clock_mask) && + (t_new & external_clock_mask)) { + aspeed_timer_ctrl_external_clock(t, false); + s->ctrl = deposit32(s->ctrl, shift + op_external_clock, 1, 0); + } + + if ((t_old & overflow_interrupt_mask) && + (t_new & overflow_interrupt_mask)) { + aspeed_timer_ctrl_overflow_interrupt(t, false); + s->ctrl = deposit32(s->ctrl, shift + op_overflow_interrupt, 1, 0); + } + + if ((t_old & pulse_enable_mask) && + (t_new & pulse_enable_mask)) { + aspeed_timer_ctrl_pulse_enable(t, false); + s->ctrl = deposit32(s->ctrl, shift + op_pulse_enable, 1, 0); + } + + /* Clear interrupt status */ + if (reg & 0x10000) { + s->irq_sts = deposit32(s->irq_sts, index, 1, 0); + } +} + +static uint64_t aspeed_2700_timer_read(AspeedTimerCtrlState *s, hwaddr offset) +{ + uint32_t timer_offset = offset & 0x3f; + int timer_index = offset >> 6; + uint64_t value = 0; + + if (timer_index >= ASPEED_TIMER_NR_TIMERS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: offset 0x%" PRIx64 " out of bounds\n", + __func__, offset); + return 0; + } + + switch (timer_offset) { + /* + * Counter Status + * Counter Reload + * Counter First Matching + * Counter Second Matching + */ + case 0x00 ... 0x0C: + value = aspeed_timer_get_value(&s->timers[timer_index], + timer_offset >> 2); + break; + /* Counter Control and Interrupt Status */ + case 0x10: + value = deposit64(value, 0, 4, + extract32(s->ctrl, timer_index * 4, 4)); + value = deposit64(value, 16, 1, + extract32(s->irq_sts, timer_index, 1)); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: no getter for offset 0x%" + PRIx64"\n", __func__, offset); + value = 0; + break; + } + trace_aspeed_timer_read(offset, value); + return value; +} + +static void aspeed_2700_timer_write(AspeedTimerCtrlState *s, hwaddr offset, + uint64_t value) +{ + const uint32_t timer_value = (uint32_t)(value & 0xFFFFFFFF); + uint32_t timer_offset = offset & 0x3f; + int timer_index = offset >> 6; + + if (timer_index >= ASPEED_TIMER_NR_TIMERS) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: offset 0x%" PRIx64 " out of bounds\n", + __func__, offset); + } + + switch (timer_offset) { + /* + * Counter Status + * Counter Reload + * Counter First Matching + * Counter Second Matching + */ + case 0x00 ... 0x0C: + aspeed_timer_set_value(s, timer_index, timer_offset >> 2, + timer_value); + break; + /* Counter Control Set and Interrupt Status */ + case 0x10: + aspeed_2700_timer_set_ctrl(s, timer_index, timer_value); + break; + /* Counter Control Clear and Interrupr Status */ + case 0x14: + aspeed_2700_timer_clear_ctrl(s, timer_index, timer_value); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: no setter for offset 0x%" + PRIx64"\n", __func__, offset); + break; } } @@ -763,6 +979,22 @@ static const TypeInfo aspeed_1030_timer_info = { .class_init = aspeed_1030_timer_class_init, }; +static void aspeed_2700_timer_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass); + + dc->desc = "ASPEED 2700 Timer"; + awc->read = aspeed_2700_timer_read; + awc->write = aspeed_2700_timer_write; +} + +static const TypeInfo aspeed_2700_timer_info = { + .name = TYPE_ASPEED_2700_TIMER, + .parent = TYPE_ASPEED_TIMER, + .class_init = aspeed_2700_timer_class_init, +}; + static void aspeed_timer_register_types(void) { type_register_static(&aspeed_timer_info); @@ -770,6 +1002,7 @@ static void aspeed_timer_register_types(void) type_register_static(&aspeed_2500_timer_info); type_register_static(&aspeed_2600_timer_info); type_register_static(&aspeed_1030_timer_info); + type_register_static(&aspeed_2700_timer_info); } type_init(aspeed_timer_register_types) diff --git a/hw/timer/trace-events b/hw/timer/trace-events index 5cfc369fba..c5b6db49f5 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -31,7 +31,7 @@ aspeed_timer_ctrl_overflow_interrupt(uint8_t i, bool enable) "Timer %" PRIu8 ": aspeed_timer_ctrl_pulse_enable(uint8_t i, bool enable) "Timer %" PRIu8 ": %d" aspeed_timer_set_ctrl2(uint32_t value) "Value: 0x%" PRIx32 aspeed_timer_set_value(int timer, int reg, uint32_t value) "Timer %d register %d: 0x%" PRIx32 -aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRIx64 ": of size %u: 0x%" PRIx64 +aspeed_timer_read(uint64_t offset, uint64_t value) "From 0x%" PRIx64 ": 0x%" PRIx64 # armv7m_systick.c systick_reload(void) "systick reload" diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c index fae212f053..e2d66179e0 100644 --- a/hw/usb/canokey.c +++ b/hw/usb/canokey.c @@ -197,8 +197,8 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p) switch (p->pid) { case USB_TOKEN_OUT: trace_canokey_handle_data_out(ep_out, p->iov.size); - usb_packet_copy(p, key->ep_out_buffer[ep_out], p->iov.size); out_pos = 0; + /* segment packet into (possibly multiple) ep_out */ while (out_pos != p->iov.size) { /* * key->ep_out[ep_out] set by prepare_receive @@ -207,8 +207,8 @@ static void canokey_handle_data(USBDevice *dev, USBPacket *p) * to be the buffer length */ out_len = MIN(p->iov.size - out_pos, key->ep_out_size[ep_out]); - memcpy(key->ep_out[ep_out], - key->ep_out_buffer[ep_out] + out_pos, out_len); + /* usb_packet_copy would update the pos offset internally */ + usb_packet_copy(p, key->ep_out[ep_out], out_len); out_pos += out_len; /* update ep_out_size to actual len */ key->ep_out_size[ep_out] = out_len; diff --git a/hw/usb/canokey.h b/hw/usb/canokey.h index e528889d33..1b60d73485 100644 --- a/hw/usb/canokey.h +++ b/hw/usb/canokey.h @@ -24,8 +24,6 @@ #define CANOKEY_EP_NUM 3 /* BULK/INTR IN can be up to 1352 bytes, e.g. get key info */ #define CANOKEY_EP_IN_BUFFER_SIZE 2048 -/* BULK OUT can be up to 270 bytes, e.g. PIV import cert */ -#define CANOKEY_EP_OUT_BUFFER_SIZE 512 typedef enum { CANOKEY_EP_IN_WAIT, @@ -59,8 +57,6 @@ typedef struct CanoKeyState { /* OUT pointer to canokey recv buffer */ uint8_t *ep_out[CANOKEY_EP_NUM]; uint32_t ep_out_size[CANOKEY_EP_NUM]; - /* For large BULK OUT, multiple write to ep_out is needed */ - uint8_t ep_out_buffer[CANOKEY_EP_NUM][CANOKEY_EP_OUT_BUFFER_SIZE]; /* Properties */ char *file; /* canokey-file */ diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c index 81f5c5189a..d94b83c109 100644 --- a/hw/watchdog/wdt_aspeed.c +++ b/hw/watchdog/wdt_aspeed.c @@ -51,11 +51,20 @@ #define WDT_TIMEOUT_CLEAR (0x14 / 4) #define WDT_RESTART_MAGIC 0x4755 +#define WDT_SW_RESET_ENABLE 0xAEEDF123 #define AST2600_SCU_RESET_CONTROL1 (0x40 / 4) #define SCU_RESET_CONTROL1 (0x04 / 4) #define SCU_RESET_SDRAM BIT(0) +static bool aspeed_wdt_is_soc_reset_mode(const AspeedWDTState *s) +{ + uint32_t mode; + + mode = extract32(s->regs[WDT_CTRL], 5, 2); + return (mode == WDT_CTRL_RESET_MODE_SOC); +} + static bool aspeed_wdt_is_enabled(const AspeedWDTState *s) { return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE; @@ -199,13 +208,18 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data, case WDT_TIMEOUT_STATUS: case WDT_TIMEOUT_CLEAR: case WDT_RESET_MASK2: - case WDT_SW_RESET_CTRL: case WDT_SW_RESET_MASK1: case WDT_SW_RESET_MASK2: qemu_log_mask(LOG_UNIMP, "%s: uninmplemented write at offset 0x%" HWADDR_PRIx "\n", __func__, offset); break; + case WDT_SW_RESET_CTRL: + if (aspeed_wdt_is_soc_reset_mode(s) && + (data == WDT_SW_RESET_ENABLE)) { + watchdog_perform_action(); + } + break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", @@ -278,7 +292,8 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp) s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev); - /* FIXME: This setting should be derived from the SCU hw strapping + /* + * FIXME: This setting should be derived from the SCU hw strapping * register SCU70 */ s->pclk_freq = PCLK_HZ; diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h index dceee23c82..4cb30a4822 100644 --- a/include/fpu/softfloat-helpers.h +++ b/include/fpu/softfloat-helpers.h @@ -124,58 +124,61 @@ static inline void set_no_signaling_nans(bool val, float_status *status) status->no_signaling_nans = val; } -static inline bool get_float_detect_tininess(float_status *status) +static inline bool get_float_detect_tininess(const float_status *status) { return status->tininess_before_rounding; } -static inline FloatRoundMode get_float_rounding_mode(float_status *status) +static inline FloatRoundMode get_float_rounding_mode(const float_status *status) { return status->float_rounding_mode; } -static inline int get_float_exception_flags(float_status *status) +static inline int get_float_exception_flags(const float_status *status) { return status->float_exception_flags; } static inline FloatX80RoundPrec -get_floatx80_rounding_precision(float_status *status) +get_floatx80_rounding_precision(const float_status *status) { return status->floatx80_rounding_precision; } -static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status) +static inline Float2NaNPropRule +get_float_2nan_prop_rule(const float_status *status) { return status->float_2nan_prop_rule; } -static inline Float3NaNPropRule get_float_3nan_prop_rule(float_status *status) +static inline Float3NaNPropRule +get_float_3nan_prop_rule(const float_status *status) { return status->float_3nan_prop_rule; } -static inline FloatInfZeroNaNRule get_float_infzeronan_rule(float_status *status) +static inline FloatInfZeroNaNRule +get_float_infzeronan_rule(const float_status *status) { return status->float_infzeronan_rule; } -static inline uint8_t get_float_default_nan_pattern(float_status *status) +static inline uint8_t get_float_default_nan_pattern(const float_status *status) { return status->default_nan_pattern; } -static inline bool get_flush_to_zero(float_status *status) +static inline bool get_flush_to_zero(const float_status *status) { return status->flush_to_zero; } -static inline bool get_flush_inputs_to_zero(float_status *status) +static inline bool get_flush_inputs_to_zero(const float_status *status) { return status->flush_inputs_to_zero; } -static inline bool get_default_nan_mode(float_status *status) +static inline bool get_default_nan_mode(const float_status *status) { return status->default_nan_mode; } diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index 9d37cdfaa8..616c290145 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -154,8 +154,10 @@ enum { float_flag_overflow = 0x0004, float_flag_underflow = 0x0008, float_flag_inexact = 0x0010, - float_flag_input_denormal = 0x0020, - float_flag_output_denormal = 0x0040, + /* We flushed an input denormal to 0 (because of flush_inputs_to_zero) */ + float_flag_input_denormal_flushed = 0x0020, + /* We flushed an output denormal to 0 (because of flush_to_zero) */ + float_flag_output_denormal_flushed = 0x0040, float_flag_invalid_isi = 0x0080, /* inf - inf */ float_flag_invalid_imz = 0x0100, /* inf * 0 */ float_flag_invalid_idi = 0x0200, /* inf / inf */ @@ -300,9 +302,9 @@ typedef struct float_status { Float3NaNPropRule float_3nan_prop_rule; FloatInfZeroNaNRule float_infzeronan_rule; bool tininess_before_rounding; - /* should denormalised results go to zero and set the inexact flag? */ + /* should denormalised results go to zero and set output_denormal_flushed? */ bool flush_to_zero; - /* should denormalised inputs go to zero and set the input_denormal flag? */ + /* should denormalised inputs go to zero and set input_denormal_flushed? */ bool flush_inputs_to_zero; bool default_nan_mode; /* diff --git a/include/hw/arm/aspeed.h b/include/hw/arm/aspeed.h index cbeacb214c..9cae45a1c9 100644 --- a/include/hw/arm/aspeed.h +++ b/include/hw/arm/aspeed.h @@ -39,6 +39,7 @@ struct AspeedMachineClass { uint32_t macs_mask; void (*i2c_init)(AspeedMachineState *bmc); uint32_t uart_default; + bool sdhci_wp_inverted; }; diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h index 61c593ffd2..9da32fc189 100644 --- a/include/hw/arm/fsl-imx6.h +++ b/include/hw/arm/fsl-imx6.h @@ -33,6 +33,7 @@ #include "hw/usb/chipidea.h" #include "hw/usb/imx-usb-phy.h" #include "hw/pci-host/designware.h" +#include "hw/or-irq.h" #include "exec/memory.h" #include "cpu.h" #include "qom/object.h" @@ -73,6 +74,7 @@ struct FslIMX6State { ChipideaState usb[FSL_IMX6_NUM_USBS]; IMXFECState eth; DesignwarePCIEHost pcie; + OrIRQState pcie4_msi_irq; MemoryRegion rom; MemoryRegion caam; MemoryRegion ocram; @@ -457,7 +459,7 @@ struct FslIMX6State { #define FSL_IMX6_PCIE1_IRQ 120 #define FSL_IMX6_PCIE2_IRQ 121 #define FSL_IMX6_PCIE3_IRQ 122 -#define FSL_IMX6_PCIE4_IRQ 123 +#define FSL_IMX6_PCIE4_MSI_IRQ 123 #define FSL_IMX6_DCIC1_IRQ 124 #define FSL_IMX6_DCIC2_IRQ 125 #define FSL_IMX6_MLB150_HIGH_IRQ 126 diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h index 411fa1c2e3..aa7818c499 100644 --- a/include/hw/arm/fsl-imx7.h +++ b/include/hw/arm/fsl-imx7.h @@ -36,6 +36,7 @@ #include "hw/net/imx_fec.h" #include "hw/pci-host/designware.h" #include "hw/usb/chipidea.h" +#include "hw/or-irq.h" #include "cpu.h" #include "qom/object.h" #include "qemu/units.h" @@ -85,6 +86,7 @@ struct FslIMX7State { IMX7GPRState gpr; ChipideaState usb[FSL_IMX7_NUM_USBS]; DesignwarePCIEHost pcie; + OrIRQState pcie4_msi_irq; MemoryRegion rom; MemoryRegion caam; MemoryRegion ocram; @@ -428,7 +430,7 @@ enum FslIMX7IRQs { FSL_IMX7_PCI_INTA_IRQ = 125, FSL_IMX7_PCI_INTB_IRQ = 124, FSL_IMX7_PCI_INTC_IRQ = 123, - FSL_IMX7_PCI_INTD_IRQ = 122, + FSL_IMX7_PCI_INTD_MSI_IRQ = 122, FSL_IMX7_UART7_IRQ = 126, diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h index e52a56e75e..f88ab1b7d3 100644 --- a/include/hw/arm/nrf51_soc.h +++ b/include/hw/arm/nrf51_soc.h @@ -30,7 +30,7 @@ struct NRF51State { SysBusDevice parent_obj; /*< public >*/ - ARMv7MState cpu; + ARMv7MState armv7m; NRF51UARTState uart; NRF51RNGState rng; diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h index 65f0e97c76..90ba3ff18c 100644 --- a/include/hw/char/imx_serial.h +++ b/include/hw/char/imx_serial.h @@ -109,13 +109,13 @@ struct IMXSerialState { uint32_t ucr1; uint32_t ucr2; uint32_t uts1; + uint32_t ufcr; /* * The registers below are implemented just so that the * guest OS sees what it has written */ uint32_t onems; - uint32_t ufcr; uint32_t ubmr; uint32_t ubrc; uint32_t ucr3; diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h index c484e377a8..bf8b278978 100644 --- a/include/hw/pci-host/designware.h +++ b/include/hw/pci-host/designware.h @@ -86,6 +86,7 @@ struct DesignwarePCIEHost { MemoryRegion io; qemu_irq irqs[4]; + qemu_irq msi; } pci; MemoryRegion mmio; diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h index 6cd2822f1d..38c08e2859 100644 --- a/include/hw/sd/sdhci.h +++ b/include/hw/sd/sdhci.h @@ -100,6 +100,11 @@ struct SDHCIState { uint8_t sd_spec_version; uint8_t uhs_mode; uint8_t vendor; /* For vendor specific functionality */ + /* + * Write Protect pin default active low for detecting SD card + * to be protected. Set wp_inverted to invert the signal. + */ + bool wp_inverted; }; typedef struct SDHCIState SDHCIState; diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h index 07dc6b6f2c..767cae4b05 100644 --- a/include/hw/timer/aspeed_timer.h +++ b/include/hw/timer/aspeed_timer.h @@ -32,6 +32,7 @@ OBJECT_DECLARE_TYPE(AspeedTimerCtrlState, AspeedTimerClass, ASPEED_TIMER) #define TYPE_ASPEED_2500_TIMER TYPE_ASPEED_TIMER "-ast2500" #define TYPE_ASPEED_2600_TIMER TYPE_ASPEED_TIMER "-ast2600" #define TYPE_ASPEED_1030_TIMER TYPE_ASPEED_TIMER "-ast1030" +#define TYPE_ASPEED_2700_TIMER TYPE_ASPEED_TIMER "-ast2700" #define ASPEED_TIMER_NR_TIMERS 8 diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h index 546eb49c11..9383e295f4 100644 --- a/include/tcg/tcg-opc.h +++ b/include/tcg/tcg-opc.h @@ -33,20 +33,13 @@ DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT) /* variable number of parameters */ DEF(call, 0, 0, 3, TCG_OPF_CALL_CLOBBER | TCG_OPF_NOT_PRESENT) -DEF(br, 0, 0, 1, TCG_OPF_BB_END) +DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT) -#define IMPL(X) (__builtin_constant_p(X) && (X) <= 0 ? TCG_OPF_NOT_PRESENT : 0) -#if TCG_TARGET_REG_BITS == 32 -# define IMPL64 TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT -#else -# define IMPL64 TCG_OPF_64BIT -#endif - -DEF(mb, 0, 0, 1, 0) +DEF(mb, 0, 0, 1, TCG_OPF_NOT_PRESENT) DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT) DEF(setcond_i32, 1, 2, 1, 0) -DEF(negsetcond_i32, 1, 2, 1, IMPL(TCG_TARGET_HAS_negsetcond_i32)) +DEF(negsetcond_i32, 1, 2, 1, 0) DEF(movcond_i32, 1, 4, 1, 0) /* load/store */ DEF(ld8u_i32, 1, 1, 1, 0) @@ -61,12 +54,12 @@ DEF(st_i32, 0, 2, 1, 0) DEF(add_i32, 1, 2, 0, 0) DEF(sub_i32, 1, 2, 0, 0) DEF(mul_i32, 1, 2, 0, 0) -DEF(div_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32)) -DEF(divu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32)) -DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32)) -DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32)) -DEF(div2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32)) -DEF(divu2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32)) +DEF(div_i32, 1, 2, 0, 0) +DEF(divu_i32, 1, 2, 0, 0) +DEF(rem_i32, 1, 2, 0, 0) +DEF(remu_i32, 1, 2, 0, 0) +DEF(div2_i32, 2, 3, 0, 0) +DEF(divu2_i32, 2, 3, 0, 0) DEF(and_i32, 1, 2, 0, 0) DEF(or_i32, 1, 2, 0, 0) DEF(xor_i32, 1, 2, 0, 0) @@ -74,127 +67,122 @@ DEF(xor_i32, 1, 2, 0, 0) DEF(shl_i32, 1, 2, 0, 0) DEF(shr_i32, 1, 2, 0, 0) DEF(sar_i32, 1, 2, 0, 0) -DEF(rotl_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32)) -DEF(rotr_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32)) -DEF(deposit_i32, 1, 2, 2, IMPL(TCG_TARGET_HAS_deposit_i32)) -DEF(extract_i32, 1, 1, 2, IMPL(TCG_TARGET_HAS_extract_i32)) -DEF(sextract_i32, 1, 1, 2, IMPL(TCG_TARGET_HAS_sextract_i32)) -DEF(extract2_i32, 1, 2, 1, IMPL(TCG_TARGET_HAS_extract2_i32)) +DEF(rotl_i32, 1, 2, 0, 0) +DEF(rotr_i32, 1, 2, 0, 0) +DEF(deposit_i32, 1, 2, 2, 0) +DEF(extract_i32, 1, 1, 2, 0) +DEF(sextract_i32, 1, 1, 2, 0) +DEF(extract2_i32, 1, 2, 1, 0) DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_COND_BRANCH) -DEF(add2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_add2_i32)) -DEF(sub2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_sub2_i32)) -DEF(mulu2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_mulu2_i32)) -DEF(muls2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_muls2_i32)) -DEF(muluh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_muluh_i32)) -DEF(mulsh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i32)) -DEF(brcond2_i32, 0, 4, 2, - TCG_OPF_BB_END | TCG_OPF_COND_BRANCH | IMPL(TCG_TARGET_REG_BITS == 32)) -DEF(setcond2_i32, 1, 4, 1, IMPL(TCG_TARGET_REG_BITS == 32)) - -DEF(ext8s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8s_i32)) -DEF(ext16s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16s_i32)) -DEF(ext8u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8u_i32)) -DEF(ext16u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16u_i32)) -DEF(bswap16_i32, 1, 1, 1, IMPL(TCG_TARGET_HAS_bswap16_i32)) -DEF(bswap32_i32, 1, 1, 1, IMPL(TCG_TARGET_HAS_bswap32_i32)) -DEF(not_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_not_i32)) +DEF(add2_i32, 2, 4, 0, 0) +DEF(sub2_i32, 2, 4, 0, 0) +DEF(mulu2_i32, 2, 2, 0, 0) +DEF(muls2_i32, 2, 2, 0, 0) +DEF(muluh_i32, 1, 2, 0, 0) +DEF(mulsh_i32, 1, 2, 0, 0) +DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | TCG_OPF_COND_BRANCH) +DEF(setcond2_i32, 1, 4, 1, 0) + +DEF(ext8s_i32, 1, 1, 0, 0) +DEF(ext16s_i32, 1, 1, 0, 0) +DEF(ext8u_i32, 1, 1, 0, 0) +DEF(ext16u_i32, 1, 1, 0, 0) +DEF(bswap16_i32, 1, 1, 1, 0) +DEF(bswap32_i32, 1, 1, 1, 0) +DEF(not_i32, 1, 1, 0, 0) DEF(neg_i32, 1, 1, 0, 0) -DEF(andc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_andc_i32)) -DEF(orc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_orc_i32)) -DEF(eqv_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_eqv_i32)) -DEF(nand_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nand_i32)) -DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32)) -DEF(clz_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_clz_i32)) -DEF(ctz_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_ctz_i32)) -DEF(ctpop_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ctpop_i32)) - -DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT) -DEF(setcond_i64, 1, 2, 1, IMPL64) -DEF(negsetcond_i64, 1, 2, 1, IMPL64 | IMPL(TCG_TARGET_HAS_negsetcond_i64)) -DEF(movcond_i64, 1, 4, 1, IMPL64) +DEF(andc_i32, 1, 2, 0, 0) +DEF(orc_i32, 1, 2, 0, 0) +DEF(eqv_i32, 1, 2, 0, 0) +DEF(nand_i32, 1, 2, 0, 0) +DEF(nor_i32, 1, 2, 0, 0) +DEF(clz_i32, 1, 2, 0, 0) +DEF(ctz_i32, 1, 2, 0, 0) +DEF(ctpop_i32, 1, 1, 0, 0) + +DEF(mov_i64, 1, 1, 0, TCG_OPF_NOT_PRESENT) +DEF(setcond_i64, 1, 2, 1, 0) +DEF(negsetcond_i64, 1, 2, 1, 0) +DEF(movcond_i64, 1, 4, 1, 0) /* load/store */ -DEF(ld8u_i64, 1, 1, 1, IMPL64) -DEF(ld8s_i64, 1, 1, 1, IMPL64) -DEF(ld16u_i64, 1, 1, 1, IMPL64) -DEF(ld16s_i64, 1, 1, 1, IMPL64) -DEF(ld32u_i64, 1, 1, 1, IMPL64) -DEF(ld32s_i64, 1, 1, 1, IMPL64) -DEF(ld_i64, 1, 1, 1, IMPL64) -DEF(st8_i64, 0, 2, 1, IMPL64) -DEF(st16_i64, 0, 2, 1, IMPL64) -DEF(st32_i64, 0, 2, 1, IMPL64) -DEF(st_i64, 0, 2, 1, IMPL64) +DEF(ld8u_i64, 1, 1, 1, 0) +DEF(ld8s_i64, 1, 1, 1, 0) +DEF(ld16u_i64, 1, 1, 1, 0) +DEF(ld16s_i64, 1, 1, 1, 0) +DEF(ld32u_i64, 1, 1, 1, 0) +DEF(ld32s_i64, 1, 1, 1, 0) +DEF(ld_i64, 1, 1, 1, 0) +DEF(st8_i64, 0, 2, 1, 0) +DEF(st16_i64, 0, 2, 1, 0) +DEF(st32_i64, 0, 2, 1, 0) +DEF(st_i64, 0, 2, 1, 0) /* arith */ -DEF(add_i64, 1, 2, 0, IMPL64) -DEF(sub_i64, 1, 2, 0, IMPL64) -DEF(mul_i64, 1, 2, 0, IMPL64) -DEF(div_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64)) -DEF(divu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64)) -DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64)) -DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64)) -DEF(div2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64)) -DEF(divu2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64)) -DEF(and_i64, 1, 2, 0, IMPL64) -DEF(or_i64, 1, 2, 0, IMPL64) -DEF(xor_i64, 1, 2, 0, IMPL64) +DEF(add_i64, 1, 2, 0, 0) +DEF(sub_i64, 1, 2, 0, 0) +DEF(mul_i64, 1, 2, 0, 0) +DEF(div_i64, 1, 2, 0, 0) +DEF(divu_i64, 1, 2, 0, 0) +DEF(rem_i64, 1, 2, 0, 0) +DEF(remu_i64, 1, 2, 0, 0) +DEF(div2_i64, 2, 3, 0, 0) +DEF(divu2_i64, 2, 3, 0, 0) +DEF(and_i64, 1, 2, 0, 0) +DEF(or_i64, 1, 2, 0, 0) +DEF(xor_i64, 1, 2, 0, 0) /* shifts/rotates */ -DEF(shl_i64, 1, 2, 0, IMPL64) -DEF(shr_i64, 1, 2, 0, IMPL64) -DEF(sar_i64, 1, 2, 0, IMPL64) -DEF(rotl_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64)) -DEF(rotr_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64)) -DEF(deposit_i64, 1, 2, 2, IMPL64 | IMPL(TCG_TARGET_HAS_deposit_i64)) -DEF(extract_i64, 1, 1, 2, IMPL64 | IMPL(TCG_TARGET_HAS_extract_i64)) -DEF(sextract_i64, 1, 1, 2, IMPL64 | IMPL(TCG_TARGET_HAS_sextract_i64)) -DEF(extract2_i64, 1, 2, 1, IMPL64 | IMPL(TCG_TARGET_HAS_extract2_i64)) +DEF(shl_i64, 1, 2, 0, 0) +DEF(shr_i64, 1, 2, 0, 0) +DEF(sar_i64, 1, 2, 0, 0) +DEF(rotl_i64, 1, 2, 0, 0) +DEF(rotr_i64, 1, 2, 0, 0) +DEF(deposit_i64, 1, 2, 2, 0) +DEF(extract_i64, 1, 1, 2, 0) +DEF(sextract_i64, 1, 1, 2, 0) +DEF(extract2_i64, 1, 2, 1, 0) /* size changing ops */ -DEF(ext_i32_i64, 1, 1, 0, IMPL64) -DEF(extu_i32_i64, 1, 1, 0, IMPL64) -DEF(extrl_i64_i32, 1, 1, 0, - IMPL(TCG_TARGET_HAS_extr_i64_i32) - | (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0)) -DEF(extrh_i64_i32, 1, 1, 0, - IMPL(TCG_TARGET_HAS_extr_i64_i32) - | (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0)) - -DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_COND_BRANCH | IMPL64) -DEF(ext8s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8s_i64)) -DEF(ext16s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16s_i64)) -DEF(ext32s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32s_i64)) -DEF(ext8u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8u_i64)) -DEF(ext16u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16u_i64)) -DEF(ext32u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32u_i64)) -DEF(bswap16_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap16_i64)) -DEF(bswap32_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap32_i64)) -DEF(bswap64_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap64_i64)) -DEF(not_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_not_i64)) -DEF(neg_i64, 1, 1, 0, IMPL64) -DEF(andc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_andc_i64)) -DEF(orc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_orc_i64)) -DEF(eqv_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_eqv_i64)) -DEF(nand_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_nand_i64)) -DEF(nor_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_nor_i64)) -DEF(clz_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_clz_i64)) -DEF(ctz_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ctz_i64)) -DEF(ctpop_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ctpop_i64)) - -DEF(add2_i64, 2, 4, 0, IMPL64 | IMPL(TCG_TARGET_HAS_add2_i64)) -DEF(sub2_i64, 2, 4, 0, IMPL64 | IMPL(TCG_TARGET_HAS_sub2_i64)) -DEF(mulu2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_mulu2_i64)) -DEF(muls2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muls2_i64)) -DEF(muluh_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muluh_i64)) -DEF(mulsh_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_mulsh_i64)) +DEF(ext_i32_i64, 1, 1, 0, 0) +DEF(extu_i32_i64, 1, 1, 0, 0) +DEF(extrl_i64_i32, 1, 1, 0, 0) +DEF(extrh_i64_i32, 1, 1, 0, 0) + +DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_COND_BRANCH) +DEF(ext8s_i64, 1, 1, 0, 0) +DEF(ext16s_i64, 1, 1, 0, 0) +DEF(ext32s_i64, 1, 1, 0, 0) +DEF(ext8u_i64, 1, 1, 0, 0) +DEF(ext16u_i64, 1, 1, 0, 0) +DEF(ext32u_i64, 1, 1, 0, 0) +DEF(bswap16_i64, 1, 1, 1, 0) +DEF(bswap32_i64, 1, 1, 1, 0) +DEF(bswap64_i64, 1, 1, 1, 0) +DEF(not_i64, 1, 1, 0, 0) +DEF(neg_i64, 1, 1, 0, 0) +DEF(andc_i64, 1, 2, 0, 0) +DEF(orc_i64, 1, 2, 0, 0) +DEF(eqv_i64, 1, 2, 0, 0) +DEF(nand_i64, 1, 2, 0, 0) +DEF(nor_i64, 1, 2, 0, 0) +DEF(clz_i64, 1, 2, 0, 0) +DEF(ctz_i64, 1, 2, 0, 0) +DEF(ctpop_i64, 1, 1, 0, 0) + +DEF(add2_i64, 2, 4, 0, 0) +DEF(sub2_i64, 2, 4, 0, 0) +DEF(mulu2_i64, 2, 2, 0, 0) +DEF(muls2_i64, 2, 2, 0, 0) +DEF(muluh_i64, 1, 2, 0, 0) +DEF(mulsh_i64, 1, 2, 0, 0) #define DATA64_ARGS (TCG_TARGET_REG_BITS == 64 ? 1 : 2) /* There are tcg_ctx->insn_start_words here, not just one. */ DEF(insn_start, 0, 0, DATA64_ARGS, TCG_OPF_NOT_PRESENT) -DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END) -DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END) +DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT) +DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT) DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_EXIT | TCG_OPF_BB_END) DEF(plugin_cb, 0, 0, 1, TCG_OPF_NOT_PRESENT) @@ -206,113 +194,90 @@ DEF(qemu_ld_a32_i32, 1, 1, 1, DEF(qemu_st_a32_i32, 0, 1 + 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) DEF(qemu_ld_a32_i64, DATA64_ARGS, 1, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT) + TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) DEF(qemu_st_a32_i64, 0, DATA64_ARGS + 1, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT) + TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) DEF(qemu_ld_a64_i32, 1, DATA64_ARGS, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) DEF(qemu_st_a64_i32, 0, 1 + DATA64_ARGS, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) DEF(qemu_ld_a64_i64, DATA64_ARGS, DATA64_ARGS, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT) + TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) DEF(qemu_st_a64_i64, 0, DATA64_ARGS + DATA64_ARGS, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT) + TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) /* Only used by i386 to cope with stupid register constraints. */ DEF(qemu_st8_a32_i32, 0, 1 + 1, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | - IMPL(TCG_TARGET_HAS_qemu_st8_i32)) + TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) DEF(qemu_st8_a64_i32, 0, 1 + DATA64_ARGS, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | - IMPL(TCG_TARGET_HAS_qemu_st8_i32)) + TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) /* Only for 64-bit hosts at the moment. */ -DEF(qemu_ld_a32_i128, 2, 1, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT | - IMPL(TCG_TARGET_HAS_qemu_ldst_i128)) -DEF(qemu_ld_a64_i128, 2, 1, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT | - IMPL(TCG_TARGET_HAS_qemu_ldst_i128)) -DEF(qemu_st_a32_i128, 0, 3, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT | - IMPL(TCG_TARGET_HAS_qemu_ldst_i128)) -DEF(qemu_st_a64_i128, 0, 3, 1, - TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT | - IMPL(TCG_TARGET_HAS_qemu_ldst_i128)) +DEF(qemu_ld_a32_i128, 2, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) +DEF(qemu_ld_a64_i128, 2, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) +DEF(qemu_st_a32_i128, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) +DEF(qemu_st_a64_i128, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS) /* Host vector support. */ -#define IMPLVEC TCG_OPF_VECTOR | IMPL(TCG_TARGET_MAYBE_vec) - DEF(mov_vec, 1, 1, 0, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT) -DEF(dup_vec, 1, 1, 0, IMPLVEC) -DEF(dup2_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_REG_BITS == 32)) - -DEF(ld_vec, 1, 1, 1, IMPLVEC) -DEF(st_vec, 0, 2, 1, IMPLVEC) -DEF(dupm_vec, 1, 1, 1, IMPLVEC) - -DEF(add_vec, 1, 2, 0, IMPLVEC) -DEF(sub_vec, 1, 2, 0, IMPLVEC) -DEF(mul_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_mul_vec)) -DEF(neg_vec, 1, 1, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_neg_vec)) -DEF(abs_vec, 1, 1, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_abs_vec)) -DEF(ssadd_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_sat_vec)) -DEF(usadd_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_sat_vec)) -DEF(sssub_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_sat_vec)) -DEF(ussub_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_sat_vec)) -DEF(smin_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_minmax_vec)) -DEF(umin_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_minmax_vec)) -DEF(smax_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_minmax_vec)) -DEF(umax_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_minmax_vec)) - -DEF(and_vec, 1, 2, 0, IMPLVEC) -DEF(or_vec, 1, 2, 0, IMPLVEC) -DEF(xor_vec, 1, 2, 0, IMPLVEC) -DEF(andc_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_andc_vec)) -DEF(orc_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_orc_vec)) -DEF(nand_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_nand_vec)) -DEF(nor_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_nor_vec)) -DEF(eqv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_eqv_vec)) -DEF(not_vec, 1, 1, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_not_vec)) - -DEF(shli_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) -DEF(shri_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) -DEF(sari_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_shi_vec)) -DEF(rotli_vec, 1, 1, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_roti_vec)) - -DEF(shls_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) -DEF(shrs_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) -DEF(sars_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shs_vec)) -DEF(rotls_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_rots_vec)) - -DEF(shlv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) -DEF(shrv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) -DEF(sarv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_shv_vec)) -DEF(rotlv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_rotv_vec)) -DEF(rotrv_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_rotv_vec)) - -DEF(cmp_vec, 1, 2, 1, IMPLVEC) - -DEF(bitsel_vec, 1, 3, 0, IMPLVEC | IMPL(TCG_TARGET_HAS_bitsel_vec)) -DEF(cmpsel_vec, 1, 4, 1, IMPLVEC | IMPL(TCG_TARGET_HAS_cmpsel_vec)) +DEF(dup_vec, 1, 1, 0, TCG_OPF_VECTOR) +DEF(dup2_vec, 1, 2, 0, TCG_OPF_VECTOR) + +DEF(ld_vec, 1, 1, 1, TCG_OPF_VECTOR) +DEF(st_vec, 0, 2, 1, TCG_OPF_VECTOR) +DEF(dupm_vec, 1, 1, 1, TCG_OPF_VECTOR) + +DEF(add_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(sub_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(mul_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(neg_vec, 1, 1, 0, TCG_OPF_VECTOR) +DEF(abs_vec, 1, 1, 0, TCG_OPF_VECTOR) +DEF(ssadd_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(usadd_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(sssub_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(ussub_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(smin_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(umin_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(smax_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(umax_vec, 1, 2, 0, TCG_OPF_VECTOR) + +DEF(and_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(or_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(xor_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(andc_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(orc_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(nand_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(nor_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(eqv_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(not_vec, 1, 1, 0, TCG_OPF_VECTOR) + +DEF(shli_vec, 1, 1, 1, TCG_OPF_VECTOR) +DEF(shri_vec, 1, 1, 1, TCG_OPF_VECTOR) +DEF(sari_vec, 1, 1, 1, TCG_OPF_VECTOR) +DEF(rotli_vec, 1, 1, 1, TCG_OPF_VECTOR) + +DEF(shls_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(shrs_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(sars_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(rotls_vec, 1, 2, 0, TCG_OPF_VECTOR) + +DEF(shlv_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(shrv_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(sarv_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(rotlv_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(rotrv_vec, 1, 2, 0, TCG_OPF_VECTOR) + +DEF(cmp_vec, 1, 2, 1, TCG_OPF_VECTOR) + +DEF(bitsel_vec, 1, 3, 0, TCG_OPF_VECTOR) +DEF(cmpsel_vec, 1, 4, 1, TCG_OPF_VECTOR) DEF(last_generic, 0, 0, 0, TCG_OPF_NOT_PRESENT) -#if TCG_TARGET_MAYBE_vec -#include "tcg-target.opc.h" -#endif - -#ifdef TCG_TARGET_INTERPRETER -/* These opcodes are only for use between the tci generator and interpreter. */ -DEF(tci_movi, 1, 0, 1, TCG_OPF_NOT_PRESENT) -DEF(tci_movl, 1, 0, 1, TCG_OPF_NOT_PRESENT) -#endif +#include "tcg-target-opc.h.inc" #undef DATA64_ARGS -#undef IMPL -#undef IMPL64 -#undef IMPLVEC #undef DEF diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index a77ed12b9d..1d1d668f52 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -64,111 +64,6 @@ typedef uint64_t TCGRegSet; #error unsupported #endif -#if TCG_TARGET_REG_BITS == 32 -/* Turn some undef macros into false macros. */ -#define TCG_TARGET_HAS_extr_i64_i32 0 -#define TCG_TARGET_HAS_div_i64 0 -#define TCG_TARGET_HAS_rem_i64 0 -#define TCG_TARGET_HAS_div2_i64 0 -#define TCG_TARGET_HAS_rot_i64 0 -#define TCG_TARGET_HAS_ext8s_i64 0 -#define TCG_TARGET_HAS_ext16s_i64 0 -#define TCG_TARGET_HAS_ext32s_i64 0 -#define TCG_TARGET_HAS_ext8u_i64 0 -#define TCG_TARGET_HAS_ext16u_i64 0 -#define TCG_TARGET_HAS_ext32u_i64 0 -#define TCG_TARGET_HAS_bswap16_i64 0 -#define TCG_TARGET_HAS_bswap32_i64 0 -#define TCG_TARGET_HAS_bswap64_i64 0 -#define TCG_TARGET_HAS_not_i64 0 -#define TCG_TARGET_HAS_andc_i64 0 -#define TCG_TARGET_HAS_orc_i64 0 -#define TCG_TARGET_HAS_eqv_i64 0 -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 0 -#define TCG_TARGET_HAS_clz_i64 0 -#define TCG_TARGET_HAS_ctz_i64 0 -#define TCG_TARGET_HAS_ctpop_i64 0 -#define TCG_TARGET_HAS_deposit_i64 0 -#define TCG_TARGET_HAS_extract_i64 0 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_negsetcond_i64 0 -#define TCG_TARGET_HAS_add2_i64 0 -#define TCG_TARGET_HAS_sub2_i64 0 -#define TCG_TARGET_HAS_mulu2_i64 0 -#define TCG_TARGET_HAS_muls2_i64 0 -#define TCG_TARGET_HAS_muluh_i64 0 -#define TCG_TARGET_HAS_mulsh_i64 0 -/* Turn some undef macros into true macros. */ -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#endif - -#ifndef TCG_TARGET_deposit_i32_valid -#define TCG_TARGET_deposit_i32_valid(ofs, len) 1 -#endif -#ifndef TCG_TARGET_deposit_i64_valid -#define TCG_TARGET_deposit_i64_valid(ofs, len) 1 -#endif -#ifndef TCG_TARGET_extract_i32_valid -#define TCG_TARGET_extract_i32_valid(ofs, len) 1 -#endif -#ifndef TCG_TARGET_extract_i64_valid -#define TCG_TARGET_extract_i64_valid(ofs, len) 1 -#endif - -/* Only one of DIV or DIV2 should be defined. */ -#if defined(TCG_TARGET_HAS_div_i32) -#define TCG_TARGET_HAS_div2_i32 0 -#elif defined(TCG_TARGET_HAS_div2_i32) -#define TCG_TARGET_HAS_div_i32 0 -#define TCG_TARGET_HAS_rem_i32 0 -#endif -#if defined(TCG_TARGET_HAS_div_i64) -#define TCG_TARGET_HAS_div2_i64 0 -#elif defined(TCG_TARGET_HAS_div2_i64) -#define TCG_TARGET_HAS_div_i64 0 -#define TCG_TARGET_HAS_rem_i64 0 -#endif - -#if !defined(TCG_TARGET_HAS_v64) \ - && !defined(TCG_TARGET_HAS_v128) \ - && !defined(TCG_TARGET_HAS_v256) -#define TCG_TARGET_MAYBE_vec 0 -#define TCG_TARGET_HAS_abs_vec 0 -#define TCG_TARGET_HAS_neg_vec 0 -#define TCG_TARGET_HAS_not_vec 0 -#define TCG_TARGET_HAS_andc_vec 0 -#define TCG_TARGET_HAS_orc_vec 0 -#define TCG_TARGET_HAS_nand_vec 0 -#define TCG_TARGET_HAS_nor_vec 0 -#define TCG_TARGET_HAS_eqv_vec 0 -#define TCG_TARGET_HAS_roti_vec 0 -#define TCG_TARGET_HAS_rots_vec 0 -#define TCG_TARGET_HAS_rotv_vec 0 -#define TCG_TARGET_HAS_shi_vec 0 -#define TCG_TARGET_HAS_shs_vec 0 -#define TCG_TARGET_HAS_shv_vec 0 -#define TCG_TARGET_HAS_mul_vec 0 -#define TCG_TARGET_HAS_sat_vec 0 -#define TCG_TARGET_HAS_minmax_vec 0 -#define TCG_TARGET_HAS_bitsel_vec 0 -#define TCG_TARGET_HAS_cmpsel_vec 0 -#define TCG_TARGET_HAS_tst_vec 0 -#else -#define TCG_TARGET_MAYBE_vec 1 -#endif -#ifndef TCG_TARGET_HAS_v64 -#define TCG_TARGET_HAS_v64 0 -#endif -#ifndef TCG_TARGET_HAS_v128 -#define TCG_TARGET_HAS_v128 0 -#endif -#ifndef TCG_TARGET_HAS_v256 -#define TCG_TARGET_HAS_v256 0 -#endif - typedef enum TCGOpcode { #define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name, #include "tcg/tcg-opc.h" @@ -439,7 +334,8 @@ struct TCGOp { #define TCGOP_CALLI(X) (X)->param1 #define TCGOP_CALLO(X) (X)->param2 -#define TCGOP_VECL(X) (X)->param1 +#define TCGOP_TYPE(X) (X)->param1 +#define TCGOP_FLAGS(X) (X)->param2 #define TCGOP_VECE(X) (X)->param2 /* Make sure operands fit in the bitfields above. */ @@ -497,12 +393,8 @@ struct TCGContext { CPUState *cpu; /* *_trans */ /* These structures are private to tcg-target.c.inc. */ -#ifdef TCG_TARGET_NEED_LDST_LABELS QSIMPLEQ_HEAD(, TCGLabelQemuLdst) ldst_labels; -#endif -#ifdef TCG_TARGET_NEED_POOL_LABELS struct TCGLabelPoolData *pool_labels; -#endif TCGLabel *exitreq_label; @@ -746,10 +638,51 @@ void tcg_region_reset_all(void); size_t tcg_code_size(void); size_t tcg_code_capacity(void); +/** + * tcg_tb_insert: + * @tb: translation block to insert + * + * Insert @tb into the region trees. + */ void tcg_tb_insert(TranslationBlock *tb); + +/** + * tcg_tb_remove: + * @tb: translation block to remove + * + * Remove @tb from the region trees. + */ void tcg_tb_remove(TranslationBlock *tb); + +/** + * tcg_tb_lookup: + * @tc_ptr: host PC to look up + * + * Look up a translation block inside the region trees by @tc_ptr. This is + * useful for exception handling, but must not be used for the purposes of + * executing the returned translation block. See struct tb_tc for more + * information. + * + * Returns: a translation block previously inserted into the region trees, + * such that @tc_ptr points anywhere inside the code generated for it, or + * NULL. + */ TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr); + +/** + * tcg_tb_foreach: + * @func: callback + * @user_data: opaque value to pass to @callback + * + * Call @func for each translation block inserted into the region trees. + */ void tcg_tb_foreach(GTraverseFunc func, gpointer user_data); + +/** + * tcg_nb_tbs: + * + * Returns: the number of translation blocks inserted into the region trees. + */ size_t tcg_nb_tbs(void); /* user-mode: Called with mmap_lock held. */ @@ -807,8 +740,6 @@ enum { /* Instruction has side effects: it cannot be removed if its outputs are not used, and might trigger exceptions. */ TCG_OPF_SIDE_EFFECTS = 0x08, - /* Instruction operands are 64-bits (otherwise 32-bits). */ - TCG_OPF_64BIT = 0x10, /* Instruction is optional and not implemented by the host, or insn is generic and should not be implemented by the host. */ TCG_OPF_NOT_PRESENT = 0x20, @@ -822,18 +753,23 @@ typedef struct TCGOpDef { const char *name; uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args; uint8_t flags; - TCGArgConstraint *args_ct; } TCGOpDef; -extern TCGOpDef tcg_op_defs[]; +extern const TCGOpDef tcg_op_defs[]; extern const size_t tcg_op_defs_max; -typedef struct TCGTargetOpDef { - TCGOpcode op; - const char *args_ct_str[TCG_MAX_OP_ARGS]; -} TCGTargetOpDef; - -bool tcg_op_supported(TCGOpcode op); +/* + * tcg_op_supported: + * Query if @op, for @type and @flags, is supported by the host + * on which we are currently executing. + */ +bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags); +/* + * tcg_op_deposit_valid: + * Query if a deposit into (ofs, len) is supported for @type by + * the host on which we are currently executing. + */ +bool tcg_op_deposit_valid(TCGType type, unsigned ofs, unsigned len); void tcg_gen_call0(void *func, TCGHelperInfo *, TCGTemp *ret); void tcg_gen_call1(void *func, TCGHelperInfo *, TCGTemp *ret, TCGTemp *); @@ -854,10 +790,6 @@ void tcg_gen_call7(void *func, TCGHelperInfo *, TCGTemp *ret, TCGOp *tcg_emit_op(TCGOpcode opc, unsigned nargs); void tcg_op_remove(TCGContext *s, TCGOp *op); -TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *op, - TCGOpcode opc, unsigned nargs); -TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, - TCGOpcode opc, unsigned nargs); /** * tcg_remove_ops_after: @@ -1016,17 +948,10 @@ extern tcg_prologue_fn *tcg_qemu_tb_exec; void tcg_register_jit(const void *buf, size_t buf_size); -#if TCG_TARGET_MAYBE_vec /* Return zero if the tuple (opc, type, vece) is unsupportable; return > 0 if it is directly supportable; return < 0 if we must call tcg_expand_vec_op. */ int tcg_can_emit_vec_op(TCGOpcode, TCGType, unsigned); -#else -static inline int tcg_can_emit_vec_op(TCGOpcode o, TCGType t, unsigned ve) -{ - return 0; -} -#endif /* Expand the tuple (opc, type, vece) on the given arguments. */ void tcg_expand_vec_op(TCGOpcode, TCGType, unsigned, TCGArg, ...); diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index c04a97c73a..f83d1f79d5 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -25,12 +25,32 @@ #ifdef CONFIG_RTNETLINK #include <linux/rtnetlink.h> #include <linux/if_bridge.h> +#include <linux/neighbour.h> #endif #include "qemu.h" #include "user-internals.h" #include "fd-trans.h" #include "signal-common.h" +#define NDM_RTA(r) ((struct rtattr*)(((char*)(r)) + \ + NLMSG_ALIGN(sizeof(struct ndmsg)))) + +enum { + QEMU_IFA_UNSPEC, + QEMU_IFA_ADDRESS, + QEMU_IFA_LOCAL, + QEMU_IFA_LABEL, + QEMU_IFA_BROADCAST, + QEMU_IFA_ANYCAST, + QEMU_IFA_CACHEINFO, + QEMU_IFA_MULTICAST, + QEMU_IFA_FLAGS, + QEMU_IFA_RT_PRIORITY, + QEMU_IFA_TARGET_NETNSID, + QEMU_IFA_PROTO, + QEMU__IFA__MAX, +}; + enum { QEMU_IFLA_BR_UNSPEC, QEMU_IFLA_BR_FORWARD_DELAY, @@ -141,6 +161,14 @@ enum { QEMU_IFLA_PROTO_DOWN_REASON, QEMU_IFLA_PARENT_DEV_NAME, QEMU_IFLA_PARENT_DEV_BUS_NAME, + QEMU_IFLA_GRO_MAX_SIZE, + QEMU_IFLA_TSO_MAX_SIZE, + QEMU_IFLA_TSO_MAX_SEGS, + QEMU_IFLA_ALLMULTI, + QEMU_IFLA_DEVLINK_PORT, + QEMU_IFLA_GSO_IPV4_MAX_SIZE, + QEMU_IFLA_GRO_IPV4_MAX_SIZE, + QEMU_IFLA_DPLL_PIN, QEMU___IFLA_MAX }; @@ -982,6 +1010,22 @@ static abi_long host_to_target_data_vfinfo_nlattr(struct nlattr *nlattr, return 0; } +static abi_long host_to_target_data_prop_nlattr(struct nlattr *nlattr, + void *context) +{ + switch (nlattr->nla_type) { + /* string */ + case QEMU_IFLA_ALT_IFNAME: + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown host PROP type: %d\n", + nlattr->nla_type); + break; + } + return 0; +} + + static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) { uint32_t *u32; @@ -990,7 +1034,7 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) struct rtnl_link_ifmap *map; struct linkinfo_context li_context; - switch (rtattr->rta_type) { + switch (rtattr->rta_type & NLA_TYPE_MASK) { /* binary stream */ case QEMU_IFLA_ADDRESS: case QEMU_IFLA_BROADCAST: @@ -1028,6 +1072,12 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) case QEMU_IFLA_CARRIER_DOWN_COUNT: case QEMU_IFLA_MIN_MTU: case QEMU_IFLA_MAX_MTU: + case QEMU_IFLA_GRO_MAX_SIZE: + case QEMU_IFLA_TSO_MAX_SIZE: + case QEMU_IFLA_TSO_MAX_SEGS: + case QEMU_IFLA_ALLMULTI: + case QEMU_IFLA_GSO_IPV4_MAX_SIZE: + case QEMU_IFLA_GRO_IPV4_MAX_SIZE: u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); break; @@ -1123,6 +1173,10 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, NULL, host_to_target_data_vfinfo_nlattr); + case QEMU_IFLA_PROP_LIST: + return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, + NULL, + host_to_target_data_prop_nlattr); default: qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n", rtattr->rta_type); @@ -1138,20 +1192,21 @@ static abi_long host_to_target_data_addr_rtattr(struct rtattr *rtattr) switch (rtattr->rta_type) { /* binary: depends on family type */ - case IFA_ADDRESS: - case IFA_LOCAL: + case QEMU_IFA_ADDRESS: + case QEMU_IFA_LOCAL: + case QEMU_IFA_PROTO: break; /* string */ - case IFA_LABEL: + case QEMU_IFA_LABEL: break; /* u32 */ - case IFA_FLAGS: - case IFA_BROADCAST: + case QEMU_IFA_FLAGS: + case QEMU_IFA_BROADCAST: u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); break; /* struct ifa_cacheinfo */ - case IFA_CACHEINFO: + case QEMU_IFA_CACHEINFO: ci = RTA_DATA(rtattr); ci->ifa_prefered = tswap32(ci->ifa_prefered); ci->ifa_valid = tswap32(ci->ifa_valid); @@ -1209,6 +1264,35 @@ static abi_long host_to_target_data_route_rtattr(struct rtattr *rtattr) return 0; } +static abi_long host_to_target_data_neigh_rtattr(struct rtattr *rtattr) +{ + struct nda_cacheinfo *ndac; + uint32_t *u32; + + switch (rtattr->rta_type) { + case NDA_UNSPEC: + case NDA_DST: + case NDA_LLADDR: + break; + case NDA_PROBES: + u32 = RTA_DATA(rtattr); + *u32 = tswap32(*u32); + break; + case NDA_CACHEINFO: + ndac = RTA_DATA(rtattr); + ndac->ndm_confirmed = tswap32(ndac->ndm_confirmed); + ndac->ndm_used = tswap32(ndac->ndm_used); + ndac->ndm_updated = tswap32(ndac->ndm_updated); + ndac->ndm_refcnt = tswap32(ndac->ndm_refcnt); + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown host to target NEIGH type: %d\n", + rtattr->rta_type); + break; + } + return 0; +} + static abi_long host_to_target_link_rtattr(struct rtattr *rtattr, uint32_t rtattr_len) { @@ -1230,12 +1314,20 @@ static abi_long host_to_target_route_rtattr(struct rtattr *rtattr, host_to_target_data_route_rtattr); } +static abi_long host_to_target_neigh_rtattr(struct rtattr *rtattr, + uint32_t rtattr_len) +{ + return host_to_target_for_each_rtattr(rtattr, rtattr_len, + host_to_target_data_neigh_rtattr); +} + static abi_long host_to_target_data_route(struct nlmsghdr *nlh) { uint32_t nlmsg_len; struct ifinfomsg *ifi; struct ifaddrmsg *ifa; struct rtmsg *rtm; + struct ndmsg *ndm; nlmsg_len = nlh->nlmsg_len; switch (nlh->nlmsg_type) { @@ -1262,6 +1354,17 @@ static abi_long host_to_target_data_route(struct nlmsghdr *nlh) nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); } break; + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + case RTM_GETNEIGH: + if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ndm))) { + ndm = NLMSG_DATA(nlh); + ndm->ndm_ifindex = tswap32(ndm->ndm_ifindex); + ndm->ndm_state = tswap16(ndm->ndm_state); + host_to_target_neigh_rtattr(NDM_RTA(ndm), + nlmsg_len - NLMSG_LENGTH(sizeof(*ndm))); + } + break; case RTM_NEWROUTE: case RTM_DELROUTE: case RTM_GETROUTE: @@ -1398,8 +1501,8 @@ static abi_long target_to_host_data_addr_rtattr(struct rtattr *rtattr) { switch (rtattr->rta_type) { /* binary: depends on family type */ - case IFA_LOCAL: - case IFA_ADDRESS: + case QEMU_IFA_LOCAL: + case QEMU_IFA_ADDRESS: break; default: qemu_log_mask(LOG_UNIMP, "Unknown target IFA type: %d\n", @@ -1409,6 +1512,35 @@ static abi_long target_to_host_data_addr_rtattr(struct rtattr *rtattr) return 0; } +static abi_long target_to_host_data_neigh_rtattr(struct rtattr *rtattr) +{ + struct nda_cacheinfo *ndac; + uint32_t *u32; + + switch (rtattr->rta_type) { + case NDA_UNSPEC: + case NDA_DST: + case NDA_LLADDR: + break; + case NDA_PROBES: + u32 = RTA_DATA(rtattr); + *u32 = tswap32(*u32); + break; + case NDA_CACHEINFO: + ndac = RTA_DATA(rtattr); + ndac->ndm_confirmed = tswap32(ndac->ndm_confirmed); + ndac->ndm_used = tswap32(ndac->ndm_used); + ndac->ndm_updated = tswap32(ndac->ndm_updated); + ndac->ndm_refcnt = tswap32(ndac->ndm_refcnt); + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown target NEIGH type: %d\n", + rtattr->rta_type); + break; + } + return 0; +} + static abi_long target_to_host_data_route_rtattr(struct rtattr *rtattr) { uint32_t *u32; @@ -1447,6 +1579,13 @@ static void target_to_host_addr_rtattr(struct rtattr *rtattr, target_to_host_data_addr_rtattr); } +static void target_to_host_neigh_rtattr(struct rtattr *rtattr, + uint32_t rtattr_len) +{ + target_to_host_for_each_rtattr(rtattr, rtattr_len, + target_to_host_data_neigh_rtattr); +} + static void target_to_host_route_rtattr(struct rtattr *rtattr, uint32_t rtattr_len) { @@ -1459,6 +1598,7 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh) struct ifinfomsg *ifi; struct ifaddrmsg *ifa; struct rtmsg *rtm; + struct ndmsg *ndm; switch (nlh->nlmsg_type) { case RTM_NEWLINK: @@ -1485,6 +1625,17 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh) NLMSG_LENGTH(sizeof(*ifa))); } break; + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + case RTM_GETNEIGH: + if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ndm))) { + ndm = NLMSG_DATA(nlh); + ndm->ndm_ifindex = tswap32(ndm->ndm_ifindex); + ndm->ndm_state = tswap16(ndm->ndm_state); + target_to_host_neigh_rtattr(NDM_RTA(ndm), nlh->nlmsg_len - + NLMSG_LENGTH(sizeof(*ndm))); + } + break; case RTM_NEWROUTE: case RTM_DELROUTE: case RTM_GETROUTE: diff --git a/linux-user/sparc/target_proc.h b/linux-user/sparc/target_proc.h index 3bb3134a47..744fa10730 100644 --- a/linux-user/sparc/target_proc.h +++ b/linux-user/sparc/target_proc.h @@ -8,7 +8,25 @@ static int open_cpuinfo(CPUArchState *cpu_env, int fd) { - dprintf(fd, "type\t\t: sun4u\n"); + int i, num_cpus; + const char *cpu_type; + + num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (cpu_env->def.features & CPU_FEATURE_HYPV) { + cpu_type = "sun4v"; + } else { + cpu_type = "sun4u"; + } + + dprintf(fd, "cpu\t\t: %s (QEMU)\n", cpu_env->def.name); + dprintf(fd, "type\t\t: %s\n", cpu_type); + dprintf(fd, "ncpus probed\t: %d\n", num_cpus); + dprintf(fd, "ncpus active\t: %d\n", num_cpus); + dprintf(fd, "State:\n"); + for (i = 0; i < num_cpus; i++) { + dprintf(fd, "CPU%d:\t\t: online\n", i); + } + return 0; } #define HAVE_ARCH_PROC_CPUINFO diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 78c7c0b34e..6ee02383da 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1827,7 +1827,7 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, *dst = tswap32(*dst); } } else { - qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n", + qemu_log_mask(LOG_UNIMP, "Unsupported target ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); memcpy(data, target_data, len); } @@ -1998,6 +1998,16 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, (void *) &errh->offender, sizeof(errh->offender)); break; } + case IP_PKTINFO: + { + struct in_pktinfo *pkti = data; + struct target_in_pktinfo *target_pi = target_data; + + __put_user(pkti->ipi_ifindex, &target_pi->ipi_ifindex); + target_pi->ipi_spec_dst.s_addr = pkti->ipi_spec_dst.s_addr; + target_pi->ipi_addr.s_addr = pkti->ipi_addr.s_addr; + break; + } default: goto unimplemented; } @@ -2049,7 +2059,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, default: unimplemented: - qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n", + qemu_log_mask(LOG_UNIMP, "Unsupported host ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); memcpy(target_data, data, MIN(len, tgt_len)); if (tgt_len > len) { @@ -2120,16 +2130,23 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, } ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); break; + case IP_MULTICAST_IF: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: { struct ip_mreqn ip_mreq; struct target_ip_mreqn *target_smreqn; + int min_size; QEMU_BUILD_BUG_ON(sizeof(struct ip_mreq) != sizeof(struct target_ip_mreq)); - if (optlen < sizeof (struct target_ip_mreq) || + if (optname == IP_MULTICAST_IF) { + min_size = sizeof(struct in_addr); + } else { + min_size = sizeof(struct target_ip_mreq); + } + if (optlen < min_size || optlen > sizeof (struct target_ip_mreqn)) { return -TARGET_EINVAL; } @@ -2139,13 +2156,14 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, return -TARGET_EFAULT; } ip_mreq.imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr; - ip_mreq.imr_address.s_addr = target_smreqn->imr_address.s_addr; - if (optlen == sizeof(struct target_ip_mreqn)) { - ip_mreq.imr_ifindex = tswapal(target_smreqn->imr_ifindex); - optlen = sizeof(struct ip_mreqn); + if (optlen >= sizeof(struct target_ip_mreq)) { + ip_mreq.imr_address.s_addr = target_smreqn->imr_address.s_addr; + if (optlen >= sizeof(struct target_ip_mreqn)) { + __put_user(target_smreqn->imr_ifindex, &ip_mreq.imr_ifindex); + optlen = sizeof(struct ip_mreqn); + } } unlock_user(target_smreqn, optval_addr, 0); - ret = get_errno(setsockopt(sockfd, level, optname, &ip_mreq, optlen)); break; } diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index faad9147c9..86d773add7 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2622,6 +2622,12 @@ struct target_ucred { abi_uint gid; }; +struct target_in_pktinfo { + abi_int ipi_ifindex; + struct target_in_addr ipi_spec_dst; + struct target_in_addr ipi_addr; +}; + typedef abi_int target_timer_t; #define TARGET_SIGEV_MAX_SIZE 64 diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img index 0cbedf0fa6..47240f0a74 100644 --- a/pc-bios/s390-ccw.img +++ b/pc-bios/s390-ccw.img Binary files differdiff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index 56f2f75640..0f8baa0198 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -336,8 +336,7 @@ static int run_eckd_boot_script(block_number_t bmt_block_nr, debug_print_int("loadparm", loadparm); if (loadparm >= MAX_BOOT_ENTRIES) { - puts("loadparm value greater than max number of boot entries allowed"); - return -EINVAL; + panic("loadparm value greater than max number of boot entries allowed"); } memset(sec, FREE_SPACE_FILLER, sizeof(sec)); @@ -348,8 +347,8 @@ static int run_eckd_boot_script(block_number_t bmt_block_nr, block_nr = gen_eckd_block_num(&bmt->entry[loadparm].xeckd, ldipl); if (block_nr == NULL_BLOCK_NR) { - puts("Cannot find Boot Map Table Entry"); - return -EIO; + printf("The requested boot entry (%d) is invalid\n", loadparm); + panic("Invalid loadparm"); } memset(sec, FREE_SPACE_FILLER, sizeof(sec)); @@ -792,8 +791,12 @@ static int ipl_scsi(void) debug_print_int("loadparm", loadparm); if (loadparm >= MAX_BOOT_ENTRIES) { - puts("loadparm value greater than max number of boot entries allowed"); - return -EINVAL; + panic("loadparm value greater than max number of boot entries allowed"); + } + + if (!valid_entries[loadparm]) { + printf("The requested boot entry (%d) is invalid\n", loadparm); + panic("Invalid loadparm"); } return zipl_run(&prog_table->entry[loadparm].scsi); diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c index e46e470db4..719a547ada 100644 --- a/pc-bios/s390-ccw/netmain.c +++ b/pc-bios/s390-ccw/netmain.c @@ -153,19 +153,10 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len) return rc; } -static int net_init(filename_ip_t *fn_ip) +static int net_init_ip(filename_ip_t *fn_ip) { int rc; - memset(fn_ip, 0, sizeof(filename_ip_t)); - - rc = virtio_net_init(mac); - if (rc < 0) { - puts("Could not initialize network device"); - return -101; - } - fn_ip->fd = rc; - printf(" Using MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); @@ -177,6 +168,14 @@ static int net_init(filename_ip_t *fn_ip) if (fn_ip->ip_version == 4) { set_ipv4_address(fn_ip->own_ip); } + } else if (rc == -2) { + printf("ARP request to TFTP server (%d.%d.%d.%d) failed\n", + (fn_ip->server_ip >> 24) & 0xFF, (fn_ip->server_ip >> 16) & 0xFF, + (fn_ip->server_ip >> 8) & 0xFF, fn_ip->server_ip & 0xFF); + return -102; + } else if (rc == -4 || rc == -3) { + puts("Can't obtain TFTP server IP address"); + return -107; } else { puts("Could not get IP address"); return -101; @@ -192,17 +191,6 @@ static int net_init(filename_ip_t *fn_ip) printf(" Using IPv6 address: %s\n", ip6_str); } - if (rc == -2) { - printf("ARP request to TFTP server (%d.%d.%d.%d) failed\n", - (fn_ip->server_ip >> 24) & 0xFF, (fn_ip->server_ip >> 16) & 0xFF, - (fn_ip->server_ip >> 8) & 0xFF, fn_ip->server_ip & 0xFF); - return -102; - } - if (rc == -4 || rc == -3) { - puts("Can't obtain TFTP server IP address"); - return -107; - } - printf(" Using TFTP server: "); if (fn_ip->ip_version == 4) { printf("%d.%d.%d.%d\n", @@ -221,11 +209,33 @@ static int net_init(filename_ip_t *fn_ip) return rc; } +static int net_init(filename_ip_t *fn_ip) +{ + int rc; + + memset(fn_ip, 0, sizeof(filename_ip_t)); + + rc = virtio_net_init(mac); + if (rc < 0) { + puts("Could not initialize network device"); + return -101; + } + fn_ip->fd = rc; + + rc = net_init_ip(fn_ip); + if (rc < 0) { + virtio_net_deinit(); + } + + return rc; +} + static void net_release(filename_ip_t *fn_ip) { if (fn_ip->ip_version == 4) { dhcp_send_release(fn_ip->fd); } + virtio_net_deinit(); } /** diff --git a/pc-bios/s390-ccw/virtio-net.c b/pc-bios/s390-ccw/virtio-net.c index 578c89d0c5..301445bf97 100644 --- a/pc-bios/s390-ccw/virtio-net.c +++ b/pc-bios/s390-ccw/virtio-net.c @@ -140,3 +140,8 @@ int recv(int fd, void *buf, int maxlen, int flags) return len; } + +void virtio_net_deinit(void) +{ + virtio_reset(virtio_get_device()); +} diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 8b5a370bb3..cd6c99c7e3 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -217,6 +217,11 @@ int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd) return 0; } +int virtio_reset(VDev *vdev) +{ + return run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false); +} + int virtio_setup_ccw(VDev *vdev) { int i, cfg_size = 0; @@ -235,7 +240,7 @@ int virtio_setup_ccw(VDev *vdev) vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */ vdev->guessed_disk_nature = VIRTIO_GDN_NONE; - run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false); + virtio_reset(vdev); status = VIRTIO_CONFIG_S_ACKNOWLEDGE; if (run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false)) { diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index 9faf3986b1..5c5e808a50 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -274,8 +274,10 @@ void vring_send_buf(VRing *vr, void *p, int len, int flags); int vr_poll(VRing *vr); int vring_wait_reply(void); int virtio_run(VDev *vdev, int vqid, VirtioCmd *cmd); +int virtio_reset(VDev *vdev); int virtio_setup_ccw(VDev *vdev); int virtio_net_init(void *mac_addr); +void virtio_net_deinit(void); #endif /* VIRTIO_H */ diff --git a/target/arm/cpu.c b/target/arm/cpu.c index dc0231233a..7a83b9ee34 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -572,9 +572,11 @@ static void arm_cpu_reset_hold(Object *obj, ResetType type) set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status); set_default_nan_mode(1, &env->vfp.standard_fp_status); set_default_nan_mode(1, &env->vfp.standard_fp_status_f16); - arm_set_default_fp_behaviours(&env->vfp.fp_status); + arm_set_default_fp_behaviours(&env->vfp.fp_status_a32); + arm_set_default_fp_behaviours(&env->vfp.fp_status_a64); arm_set_default_fp_behaviours(&env->vfp.standard_fp_status); - arm_set_default_fp_behaviours(&env->vfp.fp_status_f16); + arm_set_default_fp_behaviours(&env->vfp.fp_status_f16_a32); + arm_set_default_fp_behaviours(&env->vfp.fp_status_f16_a64); arm_set_default_fp_behaviours(&env->vfp.standard_fp_status_f16); #ifndef CONFIG_USER_ONLY diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 9a6e8e589c..2213c27734 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -633,8 +633,10 @@ typedef struct CPUArchState { /* There are a number of distinct float control structures: * - * fp_status: is the "normal" fp status. - * fp_status_fp16: used for half-precision calculations + * fp_status_a32: is the "normal" fp status for AArch32 insns + * fp_status_a64: is the "normal" fp status for AArch64 insns + * fp_status_fp16_a32: used for AArch32 half-precision calculations + * fp_status_fp16_a64: used for AArch64 half-precision calculations * standard_fp_status : the ARM "Standard FPSCR Value" * standard_fp_status_fp16 : used for half-precision * calculations with the ARM "Standard FPSCR Value" @@ -658,8 +660,10 @@ typedef struct CPUArchState { * only thing which needs to read the exception flags being * an explicit FPSCR read. */ - float_status fp_status; - float_status fp_status_f16; + float_status fp_status_a32; + float_status fp_status_a64; + float_status fp_status_f16_a32; + float_status fp_status_f16_a64; float_status standard_fp_status; float_status standard_fp_status_f16; diff --git a/target/arm/helper.c b/target/arm/helper.c index 6399767851..40bdfc851a 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6413,7 +6413,7 @@ static void arm_reset_sve_state(CPUARMState *env) memset(env->vfp.zregs, 0, sizeof(env->vfp.zregs)); /* Recall that FFR is stored as pregs[16]. */ memset(env->vfp.pregs, 0, sizeof(env->vfp.pregs)); - vfp_set_fpcr(env, 0x0800009f); + vfp_set_fpsr(env, 0x0800009f); } void aarch64_set_svcr(CPUARMState *env, uint64_t new, uint64_t mask) diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c index 3b226daee7..05036089dd 100644 --- a/target/arm/tcg/helper-a64.c +++ b/target/arm/tcg/helper-a64.c @@ -439,15 +439,6 @@ uint32_t ADVSIMD_HELPER(name, h)(uint32_t a, uint32_t b, float_status *fpst) \ return float16_ ## name(a, b, fpst); \ } -ADVSIMD_HALFOP(add) -ADVSIMD_HALFOP(sub) -ADVSIMD_HALFOP(mul) -ADVSIMD_HALFOP(div) -ADVSIMD_HALFOP(min) -ADVSIMD_HALFOP(max) -ADVSIMD_HALFOP(minnum) -ADVSIMD_HALFOP(maxnum) - #define ADVSIMD_TWOHALFOP(name) \ uint32_t ADVSIMD_HELPER(name, 2h)(uint32_t two_a, uint32_t two_b, \ float_status *fpst) \ diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h index 0c120bf388..bac12fbe55 100644 --- a/target/arm/tcg/helper-a64.h +++ b/target/arm/tcg/helper-a64.h @@ -47,14 +47,6 @@ DEF_HELPER_FLAGS_2(frecpx_f16, TCG_CALL_NO_RWG, f16, f16, fpst) DEF_HELPER_FLAGS_2(fcvtx_f64_to_f32, TCG_CALL_NO_RWG, f32, f64, fpst) DEF_HELPER_FLAGS_3(crc32_64, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32) DEF_HELPER_FLAGS_3(crc32c_64, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32) -DEF_HELPER_FLAGS_3(advsimd_maxh, TCG_CALL_NO_RWG, f16, f16, f16, fpst) -DEF_HELPER_FLAGS_3(advsimd_minh, TCG_CALL_NO_RWG, f16, f16, f16, fpst) -DEF_HELPER_FLAGS_3(advsimd_maxnumh, TCG_CALL_NO_RWG, f16, f16, f16, fpst) -DEF_HELPER_FLAGS_3(advsimd_minnumh, TCG_CALL_NO_RWG, f16, f16, f16, fpst) -DEF_HELPER_3(advsimd_addh, f16, f16, f16, fpst) -DEF_HELPER_3(advsimd_subh, f16, f16, f16, fpst) -DEF_HELPER_3(advsimd_mulh, f16, f16, f16, fpst) -DEF_HELPER_3(advsimd_divh, f16, f16, f16, fpst) DEF_HELPER_3(advsimd_ceq_f16, i32, f16, f16, fpst) DEF_HELPER_3(advsimd_cge_f16, i32, f16, f16, fpst) DEF_HELPER_3(advsimd_cgt_f16, i32, f16, f16, fpst) diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c index a0e6b4a41e..727c085f37 100644 --- a/target/arm/tcg/sme_helper.c +++ b/target/arm/tcg/sme_helper.c @@ -1038,13 +1038,13 @@ void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn, float_status fpst_odd, fpst_std, fpst_f16; /* - * Make copies of fp_status and fp_status_f16, because this operation + * Make copies of the fp status fields we use, because this operation * does not update the cumulative fp exception status. It also * produces default NaNs. We also need a second copy of fp_status with * round-to-odd -- see above. */ - fpst_f16 = env->vfp.fp_status_f16; - fpst_std = env->vfp.fp_status; + fpst_f16 = env->vfp.fp_status_f16_a64; + fpst_std = env->vfp.fp_status_a64; set_default_nan_mode(true, &fpst_std); set_default_nan_mode(true, &fpst_f16); fpst_odd = fpst_std; diff --git a/target/arm/tcg/sve_helper.c b/target/arm/tcg/sve_helper.c index d0865dece3..9837c5bc7a 100644 --- a/target/arm/tcg/sve_helper.c +++ b/target/arm/tcg/sve_helper.c @@ -4658,7 +4658,7 @@ static int16_t do_float16_logb_as_int(float16 a, float_status *s) return -15 - clz32(frac); } /* flush to zero */ - float_raise(float_flag_input_denormal, s); + float_raise(float_flag_input_denormal_flushed, s); } } else if (unlikely(exp == 0x1f)) { if (frac == 0) { @@ -4686,7 +4686,7 @@ static int32_t do_float32_logb_as_int(float32 a, float_status *s) return -127 - clz32(frac); } /* flush to zero */ - float_raise(float_flag_input_denormal, s); + float_raise(float_flag_input_denormal_flushed, s); } } else if (unlikely(exp == 0xff)) { if (frac == 0) { @@ -4714,7 +4714,7 @@ static int64_t do_float64_logb_as_int(float64 a, float_status *s) return -1023 - clz64(frac); } /* flush to zero */ - float_raise(float_flag_input_denormal, s); + float_raise(float_flag_input_denormal_flushed, s); } } else if (unlikely(exp == 0x7ff)) { if (frac == 0) { diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index 7c65fc3a3b..0b76a2cdb7 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -726,7 +726,7 @@ static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn, int rm, bool is_fp16, int data, gen_helper_gvec_3_ptr *fn) { - TCGv_ptr fpst = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(is_fp16 ? FPST_A64_F16 : FPST_A64); tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), vec_full_reg_offset(s, rm), fpst, @@ -768,7 +768,7 @@ static void gen_gvec_op4_fpst(DisasContext *s, bool is_q, int rd, int rn, int rm, int ra, bool is_fp16, int data, gen_helper_gvec_4_ptr *fn) { - TCGv_ptr fpst = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(is_fp16 ? FPST_A64_F16 : FPST_A64); tcg_gen_gvec_4_ptr(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), vec_full_reg_offset(s, rm), @@ -5043,7 +5043,7 @@ static bool do_fp3_scalar(DisasContext *s, arg_rrr_e *a, const FPScalar *f) if (fp_access_check(s)) { TCGv_i64 t0 = read_fp_dreg(s, a->rn); TCGv_i64 t1 = read_fp_dreg(s, a->rm); - f->gen_d(t0, t0, t1, fpstatus_ptr(FPST_FPCR)); + f->gen_d(t0, t0, t1, fpstatus_ptr(FPST_A64)); write_fp_dreg(s, a->rd, t0); } break; @@ -5051,7 +5051,7 @@ static bool do_fp3_scalar(DisasContext *s, arg_rrr_e *a, const FPScalar *f) if (fp_access_check(s)) { TCGv_i32 t0 = read_fp_sreg(s, a->rn); TCGv_i32 t1 = read_fp_sreg(s, a->rm); - f->gen_s(t0, t0, t1, fpstatus_ptr(FPST_FPCR)); + f->gen_s(t0, t0, t1, fpstatus_ptr(FPST_A64)); write_fp_sreg(s, a->rd, t0); } break; @@ -5062,7 +5062,7 @@ static bool do_fp3_scalar(DisasContext *s, arg_rrr_e *a, const FPScalar *f) if (fp_access_check(s)) { TCGv_i32 t0 = read_fp_hreg(s, a->rn); TCGv_i32 t1 = read_fp_hreg(s, a->rm); - f->gen_h(t0, t0, t1, fpstatus_ptr(FPST_FPCR_F16)); + f->gen_h(t0, t0, t1, fpstatus_ptr(FPST_A64_F16)); write_fp_sreg(s, a->rd, t0); } break; @@ -5101,28 +5101,28 @@ static const FPScalar f_scalar_fmul = { TRANS(FMUL_s, do_fp3_scalar, a, &f_scalar_fmul) static const FPScalar f_scalar_fmax = { - gen_helper_advsimd_maxh, + gen_helper_vfp_maxh, gen_helper_vfp_maxs, gen_helper_vfp_maxd, }; TRANS(FMAX_s, do_fp3_scalar, a, &f_scalar_fmax) static const FPScalar f_scalar_fmin = { - gen_helper_advsimd_minh, + gen_helper_vfp_minh, gen_helper_vfp_mins, gen_helper_vfp_mind, }; TRANS(FMIN_s, do_fp3_scalar, a, &f_scalar_fmin) static const FPScalar f_scalar_fmaxnm = { - gen_helper_advsimd_maxnumh, + gen_helper_vfp_maxnumh, gen_helper_vfp_maxnums, gen_helper_vfp_maxnumd, }; TRANS(FMAXNM_s, do_fp3_scalar, a, &f_scalar_fmaxnm) static const FPScalar f_scalar_fminnm = { - gen_helper_advsimd_minnumh, + gen_helper_vfp_minnumh, gen_helper_vfp_minnums, gen_helper_vfp_minnumd, }; @@ -5243,9 +5243,9 @@ static bool do_fcmp0_s(DisasContext *s, arg_rr_e *a, TCGv_i64 t0 = read_fp_dreg(s, a->rn); TCGv_i64 t1 = tcg_constant_i64(0); if (swap) { - f->gen_d(t0, t1, t0, fpstatus_ptr(FPST_FPCR)); + f->gen_d(t0, t1, t0, fpstatus_ptr(FPST_A64)); } else { - f->gen_d(t0, t0, t1, fpstatus_ptr(FPST_FPCR)); + f->gen_d(t0, t0, t1, fpstatus_ptr(FPST_A64)); } write_fp_dreg(s, a->rd, t0); } @@ -5255,9 +5255,9 @@ static bool do_fcmp0_s(DisasContext *s, arg_rr_e *a, TCGv_i32 t0 = read_fp_sreg(s, a->rn); TCGv_i32 t1 = tcg_constant_i32(0); if (swap) { - f->gen_s(t0, t1, t0, fpstatus_ptr(FPST_FPCR)); + f->gen_s(t0, t1, t0, fpstatus_ptr(FPST_A64)); } else { - f->gen_s(t0, t0, t1, fpstatus_ptr(FPST_FPCR)); + f->gen_s(t0, t0, t1, fpstatus_ptr(FPST_A64)); } write_fp_sreg(s, a->rd, t0); } @@ -5270,9 +5270,9 @@ static bool do_fcmp0_s(DisasContext *s, arg_rr_e *a, TCGv_i32 t0 = read_fp_hreg(s, a->rn); TCGv_i32 t1 = tcg_constant_i32(0); if (swap) { - f->gen_h(t0, t1, t0, fpstatus_ptr(FPST_FPCR_F16)); + f->gen_h(t0, t1, t0, fpstatus_ptr(FPST_A64_F16)); } else { - f->gen_h(t0, t0, t1, fpstatus_ptr(FPST_FPCR_F16)); + f->gen_h(t0, t0, t1, fpstatus_ptr(FPST_A64_F16)); } write_fp_sreg(s, a->rd, t0); } @@ -6207,7 +6207,7 @@ static bool do_fp3_scalar_idx(DisasContext *s, arg_rrx_e *a, const FPScalar *f) TCGv_i64 t1 = tcg_temp_new_i64(); read_vec_element(s, t1, a->rm, a->idx, MO_64); - f->gen_d(t0, t0, t1, fpstatus_ptr(FPST_FPCR)); + f->gen_d(t0, t0, t1, fpstatus_ptr(FPST_A64)); write_fp_dreg(s, a->rd, t0); } break; @@ -6217,7 +6217,7 @@ static bool do_fp3_scalar_idx(DisasContext *s, arg_rrx_e *a, const FPScalar *f) TCGv_i32 t1 = tcg_temp_new_i32(); read_vec_element_i32(s, t1, a->rm, a->idx, MO_32); - f->gen_s(t0, t0, t1, fpstatus_ptr(FPST_FPCR)); + f->gen_s(t0, t0, t1, fpstatus_ptr(FPST_A64)); write_fp_sreg(s, a->rd, t0); } break; @@ -6230,7 +6230,7 @@ static bool do_fp3_scalar_idx(DisasContext *s, arg_rrx_e *a, const FPScalar *f) TCGv_i32 t1 = tcg_temp_new_i32(); read_vec_element_i32(s, t1, a->rm, a->idx, MO_16); - f->gen_h(t0, t0, t1, fpstatus_ptr(FPST_FPCR_F16)); + f->gen_h(t0, t0, t1, fpstatus_ptr(FPST_A64_F16)); write_fp_sreg(s, a->rd, t0); } break; @@ -6256,7 +6256,7 @@ static bool do_fmla_scalar_idx(DisasContext *s, arg_rrx_e *a, bool neg) if (neg) { gen_vfp_negd(t1, t1); } - gen_helper_vfp_muladdd(t0, t1, t2, t0, fpstatus_ptr(FPST_FPCR)); + gen_helper_vfp_muladdd(t0, t1, t2, t0, fpstatus_ptr(FPST_A64)); write_fp_dreg(s, a->rd, t0); } break; @@ -6270,7 +6270,7 @@ static bool do_fmla_scalar_idx(DisasContext *s, arg_rrx_e *a, bool neg) if (neg) { gen_vfp_negs(t1, t1); } - gen_helper_vfp_muladds(t0, t1, t2, t0, fpstatus_ptr(FPST_FPCR)); + gen_helper_vfp_muladds(t0, t1, t2, t0, fpstatus_ptr(FPST_A64)); write_fp_sreg(s, a->rd, t0); } break; @@ -6288,7 +6288,7 @@ static bool do_fmla_scalar_idx(DisasContext *s, arg_rrx_e *a, bool neg) gen_vfp_negh(t1, t1); } gen_helper_advsimd_muladdh(t0, t1, t2, t0, - fpstatus_ptr(FPST_FPCR_F16)); + fpstatus_ptr(FPST_A64_F16)); write_fp_sreg(s, a->rd, t0); } break; @@ -6601,7 +6601,7 @@ static bool do_fp3_scalar_pair(DisasContext *s, arg_rr_e *a, const FPScalar *f) read_vec_element(s, t0, a->rn, 0, MO_64); read_vec_element(s, t1, a->rn, 1, MO_64); - f->gen_d(t0, t0, t1, fpstatus_ptr(FPST_FPCR)); + f->gen_d(t0, t0, t1, fpstatus_ptr(FPST_A64)); write_fp_dreg(s, a->rd, t0); } break; @@ -6612,7 +6612,7 @@ static bool do_fp3_scalar_pair(DisasContext *s, arg_rr_e *a, const FPScalar *f) read_vec_element_i32(s, t0, a->rn, 0, MO_32); read_vec_element_i32(s, t1, a->rn, 1, MO_32); - f->gen_s(t0, t0, t1, fpstatus_ptr(FPST_FPCR)); + f->gen_s(t0, t0, t1, fpstatus_ptr(FPST_A64)); write_fp_sreg(s, a->rd, t0); } break; @@ -6626,7 +6626,7 @@ static bool do_fp3_scalar_pair(DisasContext *s, arg_rr_e *a, const FPScalar *f) read_vec_element_i32(s, t0, a->rn, 0, MO_16); read_vec_element_i32(s, t1, a->rn, 1, MO_16); - f->gen_h(t0, t0, t1, fpstatus_ptr(FPST_FPCR_F16)); + f->gen_h(t0, t0, t1, fpstatus_ptr(FPST_A64_F16)); write_fp_sreg(s, a->rd, t0); } break; @@ -6762,7 +6762,7 @@ static bool do_fmadd(DisasContext *s, arg_rrrr_e *a, bool neg_a, bool neg_n) if (neg_n) { gen_vfp_negd(tn, tn); } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A64); gen_helper_vfp_muladdd(ta, tn, tm, ta, fpst); write_fp_dreg(s, a->rd, ta); } @@ -6780,7 +6780,7 @@ static bool do_fmadd(DisasContext *s, arg_rrrr_e *a, bool neg_a, bool neg_n) if (neg_n) { gen_vfp_negs(tn, tn); } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A64); gen_helper_vfp_muladds(ta, tn, tm, ta, fpst); write_fp_sreg(s, a->rd, ta); } @@ -6801,7 +6801,7 @@ static bool do_fmadd(DisasContext *s, arg_rrrr_e *a, bool neg_a, bool neg_n) if (neg_n) { gen_vfp_negh(tn, tn); } - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A64_F16); gen_helper_advsimd_muladdh(ta, tn, tm, ta, fpst); write_fp_sreg(s, a->rd, ta); } @@ -6895,17 +6895,17 @@ static bool do_fp_reduction(DisasContext *s, arg_qrr_e *a, if (fp_access_check(s)) { MemOp esz = a->esz; int elts = (a->q ? 16 : 8) >> esz; - TCGv_ptr fpst = fpstatus_ptr(esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(esz == MO_16 ? FPST_A64_F16 : FPST_A64); TCGv_i32 res = do_reduction_op(s, a->rn, esz, 0, elts, fpst, fn); write_fp_sreg(s, a->rd, res); } return true; } -TRANS_FEAT(FMAXNMV_h, aa64_fp16, do_fp_reduction, a, gen_helper_advsimd_maxnumh) -TRANS_FEAT(FMINNMV_h, aa64_fp16, do_fp_reduction, a, gen_helper_advsimd_minnumh) -TRANS_FEAT(FMAXV_h, aa64_fp16, do_fp_reduction, a, gen_helper_advsimd_maxh) -TRANS_FEAT(FMINV_h, aa64_fp16, do_fp_reduction, a, gen_helper_advsimd_minh) +TRANS_FEAT(FMAXNMV_h, aa64_fp16, do_fp_reduction, a, gen_helper_vfp_maxnumh) +TRANS_FEAT(FMINNMV_h, aa64_fp16, do_fp_reduction, a, gen_helper_vfp_minnumh) +TRANS_FEAT(FMAXV_h, aa64_fp16, do_fp_reduction, a, gen_helper_vfp_maxh) +TRANS_FEAT(FMINV_h, aa64_fp16, do_fp_reduction, a, gen_helper_vfp_minh) TRANS(FMAXNMV_s, do_fp_reduction, a, gen_helper_vfp_maxnums) TRANS(FMINNMV_s, do_fp_reduction, a, gen_helper_vfp_minnums) @@ -6939,7 +6939,7 @@ static void handle_fp_compare(DisasContext *s, int size, bool cmp_with_zero, bool signal_all_nans) { TCGv_i64 tcg_flags = tcg_temp_new_i64(); - TCGv_ptr fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(size == MO_16 ? FPST_A64_F16 : FPST_A64); if (size == MO_64) { TCGv_i64 tcg_vn, tcg_vm; @@ -8219,6 +8219,7 @@ static bool trans_CCMP(DisasContext *s, arg_CCMP *a) TCGv_i64 tcg_rn, tcg_y; DisasCompare c; unsigned nzcv; + bool has_andc; /* Set T0 = !COND. */ arm_test_cc(&c, a->cond); @@ -8249,17 +8250,18 @@ static bool trans_CCMP(DisasContext *s, arg_CCMP *a) tcg_gen_subi_i32(tcg_t2, tcg_t0, 1); nzcv = a->nzcv; + has_andc = tcg_op_supported(INDEX_op_andc_i32, TCG_TYPE_I32, 0); if (nzcv & 8) { /* N */ tcg_gen_or_i32(cpu_NF, cpu_NF, tcg_t1); } else { - if (TCG_TARGET_HAS_andc_i32) { + if (has_andc) { tcg_gen_andc_i32(cpu_NF, cpu_NF, tcg_t1); } else { tcg_gen_and_i32(cpu_NF, cpu_NF, tcg_t2); } } if (nzcv & 4) { /* Z */ - if (TCG_TARGET_HAS_andc_i32) { + if (has_andc) { tcg_gen_andc_i32(cpu_ZF, cpu_ZF, tcg_t1); } else { tcg_gen_and_i32(cpu_ZF, cpu_ZF, tcg_t2); @@ -8270,7 +8272,7 @@ static bool trans_CCMP(DisasContext *s, arg_CCMP *a) if (nzcv & 2) { /* C */ tcg_gen_or_i32(cpu_CF, cpu_CF, tcg_t0); } else { - if (TCG_TARGET_HAS_andc_i32) { + if (has_andc) { tcg_gen_andc_i32(cpu_CF, cpu_CF, tcg_t1); } else { tcg_gen_and_i32(cpu_CF, cpu_CF, tcg_t2); @@ -8279,7 +8281,7 @@ static bool trans_CCMP(DisasContext *s, arg_CCMP *a) if (nzcv & 1) { /* V */ tcg_gen_or_i32(cpu_VF, cpu_VF, tcg_t1); } else { - if (TCG_TARGET_HAS_andc_i32) { + if (has_andc) { tcg_gen_andc_i32(cpu_VF, cpu_VF, tcg_t1); } else { tcg_gen_and_i32(cpu_VF, cpu_VF, tcg_t2); @@ -8405,7 +8407,7 @@ static bool do_fp1_scalar(DisasContext *s, arg_rr_e *a, return check == 0; } - fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); if (rmode >= 0) { tcg_rmode = gen_set_rmode(rmode, fpst); } @@ -8511,7 +8513,7 @@ static bool trans_FCVT_s_ds(DisasContext *s, arg_rr *a) if (fp_access_check(s)) { TCGv_i32 tcg_rn = read_fp_sreg(s, a->rn); TCGv_i64 tcg_rd = tcg_temp_new_i64(); - TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(FPST_A64); gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, fpst); write_fp_dreg(s, a->rd, tcg_rd); @@ -8524,7 +8526,7 @@ static bool trans_FCVT_s_hs(DisasContext *s, arg_rr *a) if (fp_access_check(s)) { TCGv_i32 tmp = read_fp_sreg(s, a->rn); TCGv_i32 ahp = get_ahp_flag(); - TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(FPST_A64); gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp); /* write_fp_sreg is OK here because top half of result is zero */ @@ -8538,7 +8540,7 @@ static bool trans_FCVT_s_sd(DisasContext *s, arg_rr *a) if (fp_access_check(s)) { TCGv_i64 tcg_rn = read_fp_dreg(s, a->rn); TCGv_i32 tcg_rd = tcg_temp_new_i32(); - TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(FPST_A64); gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, fpst); write_fp_sreg(s, a->rd, tcg_rd); @@ -8552,7 +8554,7 @@ static bool trans_FCVT_s_hd(DisasContext *s, arg_rr *a) TCGv_i64 tcg_rn = read_fp_dreg(s, a->rn); TCGv_i32 tcg_rd = tcg_temp_new_i32(); TCGv_i32 ahp = get_ahp_flag(); - TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(FPST_A64); gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, fpst, ahp); /* write_fp_sreg is OK here because top half of tcg_rd is zero */ @@ -8566,7 +8568,7 @@ static bool trans_FCVT_s_sh(DisasContext *s, arg_rr *a) if (fp_access_check(s)) { TCGv_i32 tcg_rn = read_fp_hreg(s, a->rn); TCGv_i32 tcg_rd = tcg_temp_new_i32(); - TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_A64_F16); TCGv_i32 tcg_ahp = get_ahp_flag(); gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp); @@ -8580,7 +8582,7 @@ static bool trans_FCVT_s_dh(DisasContext *s, arg_rr *a) if (fp_access_check(s)) { TCGv_i32 tcg_rn = read_fp_hreg(s, a->rn); TCGv_i64 tcg_rd = tcg_temp_new_i64(); - TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_A64_F16); TCGv_i32 tcg_ahp = get_ahp_flag(); gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp); @@ -8596,7 +8598,7 @@ static bool do_cvtf_scalar(DisasContext *s, MemOp esz, int rd, int shift, TCGv_i32 tcg_shift, tcg_single; TCGv_i64 tcg_double; - tcg_fpstatus = fpstatus_ptr(esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + tcg_fpstatus = fpstatus_ptr(esz == MO_16 ? FPST_A64_F16 : FPST_A64); tcg_shift = tcg_constant_i32(shift); switch (esz) { @@ -8691,7 +8693,7 @@ static void do_fcvt_scalar(DisasContext *s, MemOp out, MemOp esz, TCGv_ptr tcg_fpstatus; TCGv_i32 tcg_shift, tcg_rmode, tcg_single; - tcg_fpstatus = fpstatus_ptr(esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + tcg_fpstatus = fpstatus_ptr(esz == MO_16 ? FPST_A64_F16 : FPST_A64); tcg_shift = tcg_constant_i32(shift); tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus); @@ -8855,7 +8857,7 @@ static bool trans_FJCVTZS(DisasContext *s, arg_FJCVTZS *a) } if (fp_access_check(s)) { TCGv_i64 t = read_fp_dreg(s, a->rn); - TCGv_ptr fpstatus = fpstatus_ptr(FPST_FPCR); + TCGv_ptr fpstatus = fpstatus_ptr(FPST_A64); gen_helper_fjcvtzs(t, t, fpstatus); @@ -9113,7 +9115,7 @@ static void gen_fcvtxn_sd(TCGv_i64 d, TCGv_i64 n) * with von Neumann rounding (round to odd) */ TCGv_i32 tmp = tcg_temp_new_i32(); - gen_helper_fcvtx_f64_to_f32(tmp, n, fpstatus_ptr(FPST_FPCR)); + gen_helper_fcvtx_f64_to_f32(tmp, n, fpstatus_ptr(FPST_A64)); tcg_gen_extu_i32_i64(d, tmp); } @@ -9206,7 +9208,7 @@ static void gen_fcvtn_hs(TCGv_i64 d, TCGv_i64 n) { TCGv_i32 tcg_lo = tcg_temp_new_i32(); TCGv_i32 tcg_hi = tcg_temp_new_i32(); - TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(FPST_A64); TCGv_i32 ahp = get_ahp_flag(); tcg_gen_extr_i64_i32(tcg_lo, tcg_hi, n); @@ -9219,7 +9221,7 @@ static void gen_fcvtn_hs(TCGv_i64 d, TCGv_i64 n) static void gen_fcvtn_sd(TCGv_i64 d, TCGv_i64 n) { TCGv_i32 tmp = tcg_temp_new_i32(); - TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(FPST_A64); gen_helper_vfp_fcvtsd(tmp, n, fpst); tcg_gen_extu_i32_i64(d, tmp); @@ -9235,7 +9237,7 @@ TRANS(FCVTXN_v, do_2misc_narrow_vector, a, f_scalar_fcvtxn) static void gen_bfcvtn_hs(TCGv_i64 d, TCGv_i64 n) { - TCGv_ptr fpst = fpstatus_ptr(FPST_FPCR); + TCGv_ptr fpst = fpstatus_ptr(FPST_A64); TCGv_i32 tmp = tcg_temp_new_i32(); gen_helper_bfcvt_pair(tmp, n, fpst); tcg_gen_extu_i32_i64(d, tmp); @@ -9310,7 +9312,7 @@ static bool do_fp1_vector(DisasContext *s, arg_qrr_e *a, return check == 0; } - fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); if (rmode >= 0) { tcg_rmode = gen_set_rmode(rmode, fpst); } @@ -9370,7 +9372,7 @@ static bool do_gvec_op2_fpst(DisasContext *s, MemOp esz, bool is_q, return check == 0; } - fpst = fpstatus_ptr(esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + fpst = fpstatus_ptr(esz == MO_16 ? FPST_A64_F16 : FPST_A64); tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn), fpst, is_q ? 16 : 8, vec_full_reg_size(s), @@ -9509,13 +9511,14 @@ static bool trans_FCVTL_v(DisasContext *s, arg_qrr_e *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR); if (a->esz == MO_64) { /* 32 -> 64 bit fp conversion */ TCGv_i64 tcg_res[2]; TCGv_i32 tcg_op = tcg_temp_new_i32(); int srcelt = a->q ? 2 : 0; + fpst = fpstatus_ptr(FPST_A64); + for (pass = 0; pass < 2; pass++) { tcg_res[pass] = tcg_temp_new_i64(); read_vec_element_i32(s, tcg_op, a->rn, srcelt + pass, MO_32); @@ -9530,6 +9533,8 @@ static bool trans_FCVTL_v(DisasContext *s, arg_qrr_e *a) TCGv_i32 tcg_res[4]; TCGv_i32 ahp = get_ahp_flag(); + fpst = fpstatus_ptr(FPST_A64_F16); + for (pass = 0; pass < 4; pass++) { tcg_res[pass] = tcg_temp_new_i32(); read_vec_element_i32(s, tcg_res[pass], a->rn, srcelt + pass, MO_16); diff --git a/target/arm/tcg/translate-sme.c b/target/arm/tcg/translate-sme.c index 01ece57016..fcbb350016 100644 --- a/target/arm/tcg/translate-sme.c +++ b/target/arm/tcg/translate-sme.c @@ -358,9 +358,9 @@ static bool do_outprod_env(DisasContext *s, arg_op *a, MemOp esz, TRANS_FEAT(FMOPA_h, aa64_sme, do_outprod_env, a, MO_32, gen_helper_sme_fmopa_h) TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst, a, - MO_32, FPST_FPCR, gen_helper_sme_fmopa_s) + MO_32, FPST_A64, gen_helper_sme_fmopa_s) TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst, a, - MO_64, FPST_FPCR, gen_helper_sme_fmopa_d) + MO_64, FPST_A64, gen_helper_sme_fmopa_d) TRANS_FEAT(BFMOPA, aa64_sme, do_outprod_env, a, MO_32, gen_helper_sme_bfmopa) diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c index 49d32fabc9..e1788330aa 100644 --- a/target/arm/tcg/translate-sve.c +++ b/target/arm/tcg/translate-sve.c @@ -141,7 +141,7 @@ static bool gen_gvec_fpst_arg_zz(DisasContext *s, gen_helper_gvec_2_ptr *fn, arg_rr_esz *a, int data) { return gen_gvec_fpst_zz(s, fn, a->rd, a->rn, data, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); } /* Invoke an out-of-line helper on 3 Zregs. */ @@ -191,7 +191,7 @@ static bool gen_gvec_fpst_arg_zzz(DisasContext *s, gen_helper_gvec_3_ptr *fn, arg_rrr_esz *a, int data) { return gen_gvec_fpst_zzz(s, fn, a->rd, a->rn, a->rm, data, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); } /* Invoke an out-of-line helper on 4 Zregs. */ @@ -397,7 +397,7 @@ static bool gen_gvec_fpst_arg_zpzz(DisasContext *s, gen_helper_gvec_4_ptr *fn, arg_rprr_esz *a) { return gen_gvec_fpst_zzzp(s, fn, a->rd, a->rn, a->rm, a->pg, 0, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); } /* Invoke a vector expander on two Zregs and an immediate. */ @@ -596,14 +596,8 @@ static void gen_bsl1n_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 k) static void gen_bsl1n_vec(unsigned vece, TCGv_vec d, TCGv_vec n, TCGv_vec m, TCGv_vec k) { - if (TCG_TARGET_HAS_bitsel_vec) { - tcg_gen_not_vec(vece, n, n); - tcg_gen_bitsel_vec(vece, d, k, n, m); - } else { - tcg_gen_andc_vec(vece, n, k, n); - tcg_gen_andc_vec(vece, m, m, k); - tcg_gen_or_vec(vece, d, n, m); - } + tcg_gen_not_vec(vece, n, n); + tcg_gen_bitsel_vec(vece, d, k, n, m); } static void gen_bsl1n(unsigned vece, uint32_t d, uint32_t n, uint32_t m, @@ -628,7 +622,7 @@ static void gen_bsl2n_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 k) * = | ~(m | k) */ tcg_gen_and_i64(n, n, k); - if (TCG_TARGET_HAS_orc_i64) { + if (tcg_op_supported(INDEX_op_orc_i64, TCG_TYPE_I64, 0)) { tcg_gen_or_i64(m, m, k); tcg_gen_orc_i64(d, n, m); } else { @@ -640,14 +634,8 @@ static void gen_bsl2n_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 k) static void gen_bsl2n_vec(unsigned vece, TCGv_vec d, TCGv_vec n, TCGv_vec m, TCGv_vec k) { - if (TCG_TARGET_HAS_bitsel_vec) { - tcg_gen_not_vec(vece, m, m); - tcg_gen_bitsel_vec(vece, d, k, n, m); - } else { - tcg_gen_and_vec(vece, n, n, k); - tcg_gen_or_vec(vece, m, m, k); - tcg_gen_orc_vec(vece, d, n, m); - } + tcg_gen_not_vec(vece, m, m); + tcg_gen_bitsel_vec(vece, d, k, n, m); } static void gen_bsl2n(unsigned vece, uint32_t d, uint32_t n, uint32_t m, @@ -3529,7 +3517,7 @@ static bool do_FMLA_zzxz(DisasContext *s, arg_rrxr_esz *a, bool sub) }; return gen_gvec_fpst_zzzz(s, fns[a->esz], a->rd, a->rn, a->rm, a->ra, (a->index << 1) | sub, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); } TRANS_FEAT(FMLA_zzxz, aa64_sve, do_FMLA_zzxz, a, false) @@ -3545,7 +3533,7 @@ static gen_helper_gvec_3_ptr * const fmul_idx_fns[4] = { }; TRANS_FEAT(FMUL_zzx, aa64_sve, gen_gvec_fpst_zzz, fmul_idx_fns[a->esz], a->rd, a->rn, a->rm, a->index, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) /* *** SVE Floating Point Fast Reduction Group @@ -3578,7 +3566,7 @@ static bool do_reduce(DisasContext *s, arg_rpr_esz *a, tcg_gen_addi_ptr(t_zn, tcg_env, vec_full_reg_offset(s, a->rn)); tcg_gen_addi_ptr(t_pg, tcg_env, pred_full_reg_offset(s, a->pg)); - status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + status = fpstatus_ptr(a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); fn(temp, t_zn, t_pg, status, t_desc); @@ -3630,7 +3618,7 @@ static bool do_ppz_fp(DisasContext *s, arg_rpr_esz *a, if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); TCGv_ptr status = - fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + fpstatus_ptr(a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); tcg_gen_gvec_3_ptr(pred_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), @@ -3666,7 +3654,7 @@ static gen_helper_gvec_3_ptr * const ftmad_fns[4] = { }; TRANS_FEAT_NONSTREAMING(FTMAD, aa64_sve, gen_gvec_fpst_zzz, ftmad_fns[a->esz], a->rd, a->rn, a->rm, a->imm, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) /* *** SVE Floating Point Accumulating Reduction Group @@ -3699,7 +3687,7 @@ static bool trans_FADDA(DisasContext *s, arg_rprr_esz *a) t_pg = tcg_temp_new_ptr(); tcg_gen_addi_ptr(t_rm, tcg_env, vec_full_reg_offset(s, a->rm)); tcg_gen_addi_ptr(t_pg, tcg_env, pred_full_reg_offset(s, a->pg)); - t_fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + t_fpst = fpstatus_ptr(a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); t_desc = tcg_constant_i32(simd_desc(vsz, vsz, 0)); fns[a->esz - 1](t_val, t_val, t_rm, t_pg, t_fpst, t_desc); @@ -3774,7 +3762,7 @@ static void do_fp_scalar(DisasContext *s, int zd, int zn, int pg, bool is_fp16, tcg_gen_addi_ptr(t_zn, tcg_env, vec_full_reg_offset(s, zn)); tcg_gen_addi_ptr(t_pg, tcg_env, pred_full_reg_offset(s, pg)); - status = fpstatus_ptr(is_fp16 ? FPST_FPCR_F16 : FPST_FPCR); + status = fpstatus_ptr(is_fp16 ? FPST_A64_F16 : FPST_A64); desc = tcg_constant_i32(simd_desc(vsz, vsz, 0)); fn(t_zd, t_zn, t_pg, scalar, status, desc); } @@ -3826,7 +3814,7 @@ static bool do_fp_cmp(DisasContext *s, arg_rprr_esz *a, } if (sve_access_check(s)) { unsigned vsz = vec_full_reg_size(s); - TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + TCGv_ptr status = fpstatus_ptr(a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); tcg_gen_gvec_4_ptr(pred_full_reg_offset(s, a->rd), vec_full_reg_offset(s, a->rn), vec_full_reg_offset(s, a->rm), @@ -3859,7 +3847,7 @@ static gen_helper_gvec_4_ptr * const fcadd_fns[] = { }; TRANS_FEAT(FCADD, aa64_sve, gen_gvec_fpst_zzzp, fcadd_fns[a->esz], a->rd, a->rn, a->rm, a->pg, a->rot, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) #define DO_FMLA(NAME, name) \ static gen_helper_gvec_5_ptr * const name##_fns[4] = { \ @@ -3868,7 +3856,7 @@ TRANS_FEAT(FCADD, aa64_sve, gen_gvec_fpst_zzzp, fcadd_fns[a->esz], }; \ TRANS_FEAT(NAME, aa64_sve, gen_gvec_fpst_zzzzp, name##_fns[a->esz], \ a->rd, a->rn, a->rm, a->ra, a->pg, 0, \ - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) DO_FMLA(FMLA_zpzzz, fmla_zpzzz) DO_FMLA(FMLS_zpzzz, fmls_zpzzz) @@ -3883,66 +3871,66 @@ static gen_helper_gvec_5_ptr * const fcmla_fns[4] = { }; TRANS_FEAT(FCMLA_zpzzz, aa64_sve, gen_gvec_fpst_zzzzp, fcmla_fns[a->esz], a->rd, a->rn, a->rm, a->ra, a->pg, a->rot, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) static gen_helper_gvec_4_ptr * const fcmla_idx_fns[4] = { NULL, gen_helper_gvec_fcmlah_idx, gen_helper_gvec_fcmlas_idx, NULL }; TRANS_FEAT(FCMLA_zzxz, aa64_sve, gen_gvec_fpst_zzzz, fcmla_idx_fns[a->esz], a->rd, a->rn, a->rm, a->ra, a->index * 4 + a->rot, - a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) /* *** SVE Floating Point Unary Operations Predicated Group */ TRANS_FEAT(FCVT_sh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvt_sh, a, 0, FPST_FPCR) + gen_helper_sve_fcvt_sh, a, 0, FPST_A64) TRANS_FEAT(FCVT_hs, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvt_hs, a, 0, FPST_FPCR) + gen_helper_sve_fcvt_hs, a, 0, FPST_A64_F16) TRANS_FEAT(BFCVT, aa64_sve_bf16, gen_gvec_fpst_arg_zpz, - gen_helper_sve_bfcvt, a, 0, FPST_FPCR) + gen_helper_sve_bfcvt, a, 0, FPST_A64) TRANS_FEAT(FCVT_dh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvt_dh, a, 0, FPST_FPCR) + gen_helper_sve_fcvt_dh, a, 0, FPST_A64) TRANS_FEAT(FCVT_hd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvt_hd, a, 0, FPST_FPCR) + gen_helper_sve_fcvt_hd, a, 0, FPST_A64_F16) TRANS_FEAT(FCVT_ds, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvt_ds, a, 0, FPST_FPCR) + gen_helper_sve_fcvt_ds, a, 0, FPST_A64) TRANS_FEAT(FCVT_sd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvt_sd, a, 0, FPST_FPCR) + gen_helper_sve_fcvt_sd, a, 0, FPST_A64) TRANS_FEAT(FCVTZS_hh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzs_hh, a, 0, FPST_FPCR_F16) + gen_helper_sve_fcvtzs_hh, a, 0, FPST_A64_F16) TRANS_FEAT(FCVTZU_hh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzu_hh, a, 0, FPST_FPCR_F16) + gen_helper_sve_fcvtzu_hh, a, 0, FPST_A64_F16) TRANS_FEAT(FCVTZS_hs, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzs_hs, a, 0, FPST_FPCR_F16) + gen_helper_sve_fcvtzs_hs, a, 0, FPST_A64_F16) TRANS_FEAT(FCVTZU_hs, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzu_hs, a, 0, FPST_FPCR_F16) + gen_helper_sve_fcvtzu_hs, a, 0, FPST_A64_F16) TRANS_FEAT(FCVTZS_hd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzs_hd, a, 0, FPST_FPCR_F16) + gen_helper_sve_fcvtzs_hd, a, 0, FPST_A64_F16) TRANS_FEAT(FCVTZU_hd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzu_hd, a, 0, FPST_FPCR_F16) + gen_helper_sve_fcvtzu_hd, a, 0, FPST_A64_F16) TRANS_FEAT(FCVTZS_ss, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzs_ss, a, 0, FPST_FPCR) + gen_helper_sve_fcvtzs_ss, a, 0, FPST_A64) TRANS_FEAT(FCVTZU_ss, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzu_ss, a, 0, FPST_FPCR) + gen_helper_sve_fcvtzu_ss, a, 0, FPST_A64) TRANS_FEAT(FCVTZS_sd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzs_sd, a, 0, FPST_FPCR) + gen_helper_sve_fcvtzs_sd, a, 0, FPST_A64) TRANS_FEAT(FCVTZU_sd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzu_sd, a, 0, FPST_FPCR) + gen_helper_sve_fcvtzu_sd, a, 0, FPST_A64) TRANS_FEAT(FCVTZS_ds, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzs_ds, a, 0, FPST_FPCR) + gen_helper_sve_fcvtzs_ds, a, 0, FPST_A64) TRANS_FEAT(FCVTZU_ds, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzu_ds, a, 0, FPST_FPCR) + gen_helper_sve_fcvtzu_ds, a, 0, FPST_A64) TRANS_FEAT(FCVTZS_dd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzs_dd, a, 0, FPST_FPCR) + gen_helper_sve_fcvtzs_dd, a, 0, FPST_A64) TRANS_FEAT(FCVTZU_dd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_fcvtzu_dd, a, 0, FPST_FPCR) + gen_helper_sve_fcvtzu_dd, a, 0, FPST_A64) static gen_helper_gvec_3_ptr * const frint_fns[] = { NULL, @@ -3951,7 +3939,7 @@ static gen_helper_gvec_3_ptr * const frint_fns[] = { gen_helper_sve_frint_d }; TRANS_FEAT(FRINTI, aa64_sve, gen_gvec_fpst_arg_zpz, frint_fns[a->esz], - a, 0, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) static gen_helper_gvec_3_ptr * const frintx_fns[] = { NULL, @@ -3960,7 +3948,7 @@ static gen_helper_gvec_3_ptr * const frintx_fns[] = { gen_helper_sve_frintx_d }; TRANS_FEAT(FRINTX, aa64_sve, gen_gvec_fpst_arg_zpz, frintx_fns[a->esz], - a, 0, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, ARMFPRounding mode, gen_helper_gvec_3_ptr *fn) @@ -3977,7 +3965,7 @@ static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, } vsz = vec_full_reg_size(s); - status = fpstatus_ptr(a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR); + status = fpstatus_ptr(a->esz == MO_16 ? FPST_A64_F16 : FPST_A64); tmode = gen_set_rmode(mode, status); tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd), @@ -4005,48 +3993,48 @@ static gen_helper_gvec_3_ptr * const frecpx_fns[] = { gen_helper_sve_frecpx_s, gen_helper_sve_frecpx_d, }; TRANS_FEAT(FRECPX, aa64_sve, gen_gvec_fpst_arg_zpz, frecpx_fns[a->esz], - a, 0, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) static gen_helper_gvec_3_ptr * const fsqrt_fns[] = { NULL, gen_helper_sve_fsqrt_h, gen_helper_sve_fsqrt_s, gen_helper_sve_fsqrt_d, }; TRANS_FEAT(FSQRT, aa64_sve, gen_gvec_fpst_arg_zpz, fsqrt_fns[a->esz], - a, 0, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) TRANS_FEAT(SCVTF_hh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_scvt_hh, a, 0, FPST_FPCR_F16) + gen_helper_sve_scvt_hh, a, 0, FPST_A64_F16) TRANS_FEAT(SCVTF_sh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_scvt_sh, a, 0, FPST_FPCR_F16) + gen_helper_sve_scvt_sh, a, 0, FPST_A64_F16) TRANS_FEAT(SCVTF_dh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_scvt_dh, a, 0, FPST_FPCR_F16) + gen_helper_sve_scvt_dh, a, 0, FPST_A64_F16) TRANS_FEAT(SCVTF_ss, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_scvt_ss, a, 0, FPST_FPCR) + gen_helper_sve_scvt_ss, a, 0, FPST_A64) TRANS_FEAT(SCVTF_ds, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_scvt_ds, a, 0, FPST_FPCR) + gen_helper_sve_scvt_ds, a, 0, FPST_A64) TRANS_FEAT(SCVTF_sd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_scvt_sd, a, 0, FPST_FPCR) + gen_helper_sve_scvt_sd, a, 0, FPST_A64) TRANS_FEAT(SCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_scvt_dd, a, 0, FPST_FPCR) + gen_helper_sve_scvt_dd, a, 0, FPST_A64) TRANS_FEAT(UCVTF_hh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_ucvt_hh, a, 0, FPST_FPCR_F16) + gen_helper_sve_ucvt_hh, a, 0, FPST_A64_F16) TRANS_FEAT(UCVTF_sh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_ucvt_sh, a, 0, FPST_FPCR_F16) + gen_helper_sve_ucvt_sh, a, 0, FPST_A64_F16) TRANS_FEAT(UCVTF_dh, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_ucvt_dh, a, 0, FPST_FPCR_F16) + gen_helper_sve_ucvt_dh, a, 0, FPST_A64_F16) TRANS_FEAT(UCVTF_ss, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_ucvt_ss, a, 0, FPST_FPCR) + gen_helper_sve_ucvt_ss, a, 0, FPST_A64) TRANS_FEAT(UCVTF_ds, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_ucvt_ds, a, 0, FPST_FPCR) + gen_helper_sve_ucvt_ds, a, 0, FPST_A64) TRANS_FEAT(UCVTF_sd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_ucvt_sd, a, 0, FPST_FPCR) + gen_helper_sve_ucvt_sd, a, 0, FPST_A64) TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz, - gen_helper_sve_ucvt_dd, a, 0, FPST_FPCR) + gen_helper_sve_ucvt_dd, a, 0, FPST_A64) /* *** SVE Memory - 32-bit Gather and Unsized Contiguous Group @@ -6928,10 +6916,10 @@ DO_ZPZZ_FP(FMINP, aa64_sve2, sve2_fminp_zpzz) TRANS_FEAT_NONSTREAMING(FMMLA_s, aa64_sve_f32mm, gen_gvec_fpst_zzzz, gen_helper_fmmla_s, a->rd, a->rn, a->rm, a->ra, - 0, FPST_FPCR) + 0, FPST_A64) TRANS_FEAT_NONSTREAMING(FMMLA_d, aa64_sve_f64mm, gen_gvec_fpst_zzzz, gen_helper_fmmla_d, a->rd, a->rn, a->rm, a->ra, - 0, FPST_FPCR) + 0, FPST_A64) static gen_helper_gvec_4 * const sqdmlal_zzzw_fns[] = { NULL, gen_helper_sve2_sqdmlal_zzzw_h, @@ -7047,17 +7035,17 @@ TRANS_FEAT_NONSTREAMING(RAX1, aa64_sve2_sha3, gen_gvec_fn_arg_zzz, gen_gvec_rax1, a) TRANS_FEAT(FCVTNT_sh, aa64_sve2, gen_gvec_fpst_arg_zpz, - gen_helper_sve2_fcvtnt_sh, a, 0, FPST_FPCR) + gen_helper_sve2_fcvtnt_sh, a, 0, FPST_A64) TRANS_FEAT(FCVTNT_ds, aa64_sve2, gen_gvec_fpst_arg_zpz, - gen_helper_sve2_fcvtnt_ds, a, 0, FPST_FPCR) + gen_helper_sve2_fcvtnt_ds, a, 0, FPST_A64) TRANS_FEAT(BFCVTNT, aa64_sve_bf16, gen_gvec_fpst_arg_zpz, - gen_helper_sve_bfcvtnt, a, 0, FPST_FPCR) + gen_helper_sve_bfcvtnt, a, 0, FPST_A64) TRANS_FEAT(FCVTLT_hs, aa64_sve2, gen_gvec_fpst_arg_zpz, - gen_helper_sve2_fcvtlt_hs, a, 0, FPST_FPCR) + gen_helper_sve2_fcvtlt_hs, a, 0, FPST_A64) TRANS_FEAT(FCVTLT_sd, aa64_sve2, gen_gvec_fpst_arg_zpz, - gen_helper_sve2_fcvtlt_sd, a, 0, FPST_FPCR) + gen_helper_sve2_fcvtlt_sd, a, 0, FPST_A64) TRANS_FEAT(FCVTX_ds, aa64_sve2, do_frint_mode, a, FPROUNDING_ODD, gen_helper_sve_fcvt_ds) @@ -7069,7 +7057,7 @@ static gen_helper_gvec_3_ptr * const flogb_fns[] = { gen_helper_flogb_s, gen_helper_flogb_d }; TRANS_FEAT(FLOGB, aa64_sve2, gen_gvec_fpst_arg_zpz, flogb_fns[a->esz], - a, 0, a->esz == MO_16 ? FPST_FPCR_F16 : FPST_FPCR) + a, 0, a->esz == MO_16 ? FPST_A64_F16 : FPST_A64) static bool do_FMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sub, bool sel) { @@ -7113,7 +7101,7 @@ TRANS_FEAT_NONSTREAMING(BFMMLA, aa64_sve_bf16, gen_gvec_env_arg_zzzz, static bool do_BFMLAL_zzzw(DisasContext *s, arg_rrrr_esz *a, bool sel) { return gen_gvec_fpst_zzzz(s, gen_helper_gvec_bfmlal, - a->rd, a->rn, a->rm, a->ra, sel, FPST_FPCR); + a->rd, a->rn, a->rm, a->ra, sel, FPST_A64); } TRANS_FEAT(BFMLALB_zzzw, aa64_sve_bf16, do_BFMLAL_zzzw, a, false) @@ -7123,7 +7111,7 @@ static bool do_BFMLAL_zzxw(DisasContext *s, arg_rrxr_esz *a, bool sel) { return gen_gvec_fpst_zzzz(s, gen_helper_gvec_bfmlal_idx, a->rd, a->rn, a->rm, a->ra, - (a->index << 1) | sel, FPST_FPCR); + (a->index << 1) | sel, FPST_A64); } TRANS_FEAT(BFMLALB_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, false) diff --git a/target/arm/tcg/translate-vfp.c b/target/arm/tcg/translate-vfp.c index 3cbe9a7418..8d9d1ab877 100644 --- a/target/arm/tcg/translate-vfp.c +++ b/target/arm/tcg/translate-vfp.c @@ -460,9 +460,9 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a) } if (sz == 1) { - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); } else { - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); } tcg_rmode = gen_set_rmode(rounding, fpst); @@ -527,9 +527,9 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a) } if (sz == 1) { - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); } else { - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); } tcg_shift = tcg_constant_i32(0); @@ -1398,7 +1398,7 @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn, f0 = tcg_temp_new_i32(); f1 = tcg_temp_new_i32(); fd = tcg_temp_new_i32(); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); vfp_load_reg32(f0, vn); vfp_load_reg32(f1, vm); @@ -1433,7 +1433,7 @@ static bool do_vfp_3op_hp(DisasContext *s, VFPGen3OpSPFn *fn, /* * Do a half-precision operation. Functionally this is * the same as do_vfp_3op_sp(), except: - * - it uses the FPST_FPCR_F16 + * - it uses the FPST_A32_F16 * - it doesn't need the VFP vector handling (fp16 is a * v8 feature, and in v8 VFP vectors don't exist) * - it does the aa32_fp16_arith feature test @@ -1456,7 +1456,7 @@ static bool do_vfp_3op_hp(DisasContext *s, VFPGen3OpSPFn *fn, f0 = tcg_temp_new_i32(); f1 = tcg_temp_new_i32(); fd = tcg_temp_new_i32(); - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); vfp_load_reg16(f0, vn); vfp_load_reg16(f1, vm); @@ -1517,7 +1517,7 @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn, f0 = tcg_temp_new_i64(); f1 = tcg_temp_new_i64(); fd = tcg_temp_new_i64(); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); vfp_load_reg64(f0, vn); vfp_load_reg64(f1, vm); @@ -2122,7 +2122,7 @@ static bool do_vfm_hp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) /* VFNMA, VFNMS */ gen_vfp_negh(vd, vd); } - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); gen_helper_vfp_muladdh(vd, vn, vm, vd, fpst); vfp_store_reg32(vd, a->vd); return true; @@ -2181,7 +2181,7 @@ static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d) /* VFNMA, VFNMS */ gen_vfp_negs(vd, vd); } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); gen_helper_vfp_muladds(vd, vn, vm, vd, fpst); vfp_store_reg32(vd, a->vd); return true; @@ -2246,7 +2246,7 @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d) /* VFNMA, VFNMS */ gen_vfp_negd(vd, vd); } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); gen_helper_vfp_muladdd(vd, vn, vm, vd, fpst); vfp_store_reg64(vd, a->vd); return true; @@ -2424,17 +2424,17 @@ DO_VFP_2OP(VNEG, dp, gen_vfp_negd, aa32_fpdp_v2) static void gen_VSQRT_hp(TCGv_i32 vd, TCGv_i32 vm) { - gen_helper_vfp_sqrth(vd, vm, fpstatus_ptr(FPST_FPCR_F16)); + gen_helper_vfp_sqrth(vd, vm, fpstatus_ptr(FPST_A32_F16)); } static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm) { - gen_helper_vfp_sqrts(vd, vm, fpstatus_ptr(FPST_FPCR)); + gen_helper_vfp_sqrts(vd, vm, fpstatus_ptr(FPST_A32)); } static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm) { - gen_helper_vfp_sqrtd(vd, vm, fpstatus_ptr(FPST_FPCR)); + gen_helper_vfp_sqrtd(vd, vm, fpstatus_ptr(FPST_A32)); } DO_VFP_2OP(VSQRT, hp, gen_VSQRT_hp, aa32_fp16_arith) @@ -2565,7 +2565,7 @@ static bool trans_VCVT_f32_f16(DisasContext *s, arg_VCVT_f32_f16 *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); ahp_mode = get_ahp_flag(); tmp = tcg_temp_new_i32(); /* The T bit tells us if we want the low or high 16 bits of Vm */ @@ -2599,7 +2599,7 @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); ahp_mode = get_ahp_flag(); tmp = tcg_temp_new_i32(); /* The T bit tells us if we want the low or high 16 bits of Vm */ @@ -2623,7 +2623,7 @@ static bool trans_VCVT_b16_f32(DisasContext *s, arg_VCVT_b16_f32 *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); tmp = tcg_temp_new_i32(); vfp_load_reg32(tmp, a->vm); @@ -2646,7 +2646,7 @@ static bool trans_VCVT_f16_f32(DisasContext *s, arg_VCVT_f16_f32 *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); ahp_mode = get_ahp_flag(); tmp = tcg_temp_new_i32(); @@ -2680,7 +2680,7 @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); ahp_mode = get_ahp_flag(); tmp = tcg_temp_new_i32(); vm = tcg_temp_new_i64(); @@ -2706,7 +2706,7 @@ static bool trans_VRINTR_hp(DisasContext *s, arg_VRINTR_sp *a) tmp = tcg_temp_new_i32(); vfp_load_reg16(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); gen_helper_rinth(tmp, tmp, fpst); vfp_store_reg32(tmp, a->vd); return true; @@ -2727,7 +2727,7 @@ static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a) tmp = tcg_temp_new_i32(); vfp_load_reg32(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); gen_helper_rints(tmp, tmp, fpst); vfp_store_reg32(tmp, a->vd); return true; @@ -2757,7 +2757,7 @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a) tmp = tcg_temp_new_i64(); vfp_load_reg64(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); gen_helper_rintd(tmp, tmp, fpst); vfp_store_reg64(tmp, a->vd); return true; @@ -2779,7 +2779,7 @@ static bool trans_VRINTZ_hp(DisasContext *s, arg_VRINTZ_sp *a) tmp = tcg_temp_new_i32(); vfp_load_reg16(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); tcg_rmode = gen_set_rmode(FPROUNDING_ZERO, fpst); gen_helper_rinth(tmp, tmp, fpst); gen_restore_rmode(tcg_rmode, fpst); @@ -2803,7 +2803,7 @@ static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a) tmp = tcg_temp_new_i32(); vfp_load_reg32(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); tcg_rmode = gen_set_rmode(FPROUNDING_ZERO, fpst); gen_helper_rints(tmp, tmp, fpst); gen_restore_rmode(tcg_rmode, fpst); @@ -2836,7 +2836,7 @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a) tmp = tcg_temp_new_i64(); vfp_load_reg64(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); tcg_rmode = gen_set_rmode(FPROUNDING_ZERO, fpst); gen_helper_rintd(tmp, tmp, fpst); gen_restore_rmode(tcg_rmode, fpst); @@ -2859,7 +2859,7 @@ static bool trans_VRINTX_hp(DisasContext *s, arg_VRINTX_sp *a) tmp = tcg_temp_new_i32(); vfp_load_reg16(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); gen_helper_rinth_exact(tmp, tmp, fpst); vfp_store_reg32(tmp, a->vd); return true; @@ -2880,7 +2880,7 @@ static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a) tmp = tcg_temp_new_i32(); vfp_load_reg32(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); gen_helper_rints_exact(tmp, tmp, fpst); vfp_store_reg32(tmp, a->vd); return true; @@ -2910,7 +2910,7 @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a) tmp = tcg_temp_new_i64(); vfp_load_reg64(tmp, a->vm); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); gen_helper_rintd_exact(tmp, tmp, fpst); vfp_store_reg64(tmp, a->vd); return true; @@ -2937,7 +2937,7 @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a) vm = tcg_temp_new_i32(); vd = tcg_temp_new_i64(); vfp_load_reg32(vm, a->vm); - gen_helper_vfp_fcvtds(vd, vm, fpstatus_ptr(FPST_FPCR)); + gen_helper_vfp_fcvtds(vd, vm, fpstatus_ptr(FPST_A32)); vfp_store_reg64(vd, a->vd); return true; } @@ -2963,7 +2963,7 @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a) vd = tcg_temp_new_i32(); vm = tcg_temp_new_i64(); vfp_load_reg64(vm, a->vm); - gen_helper_vfp_fcvtsd(vd, vm, fpstatus_ptr(FPST_FPCR)); + gen_helper_vfp_fcvtsd(vd, vm, fpstatus_ptr(FPST_A32)); vfp_store_reg32(vd, a->vd); return true; } @@ -2983,7 +2983,7 @@ static bool trans_VCVT_int_hp(DisasContext *s, arg_VCVT_int_sp *a) vm = tcg_temp_new_i32(); vfp_load_reg32(vm, a->vm); - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); if (a->s) { /* i32 -> f16 */ gen_helper_vfp_sitoh(vm, vm, fpst); @@ -3010,7 +3010,7 @@ static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a) vm = tcg_temp_new_i32(); vfp_load_reg32(vm, a->vm); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); if (a->s) { /* i32 -> f32 */ gen_helper_vfp_sitos(vm, vm, fpst); @@ -3044,7 +3044,7 @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a) vm = tcg_temp_new_i32(); vd = tcg_temp_new_i64(); vfp_load_reg32(vm, a->vm); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); if (a->s) { /* i32 -> f64 */ gen_helper_vfp_sitod(vd, vm, fpst); @@ -3105,7 +3105,7 @@ static bool trans_VCVT_fix_hp(DisasContext *s, arg_VCVT_fix_sp *a) vd = tcg_temp_new_i32(); vfp_load_reg32(vd, a->vd); - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); shift = tcg_constant_i32(frac_bits); /* Switch on op:U:sx bits */ @@ -3161,7 +3161,7 @@ static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a) vd = tcg_temp_new_i32(); vfp_load_reg32(vd, a->vd); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); shift = tcg_constant_i32(frac_bits); /* Switch on op:U:sx bits */ @@ -3223,7 +3223,7 @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a) vd = tcg_temp_new_i64(); vfp_load_reg64(vd, a->vd); - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); shift = tcg_constant_i32(frac_bits); /* Switch on op:U:sx bits */ @@ -3273,7 +3273,7 @@ static bool trans_VCVT_hp_int(DisasContext *s, arg_VCVT_sp_int *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR_F16); + fpst = fpstatus_ptr(FPST_A32_F16); vm = tcg_temp_new_i32(); vfp_load_reg16(vm, a->vm); @@ -3307,7 +3307,7 @@ static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); vm = tcg_temp_new_i32(); vfp_load_reg32(vm, a->vm); @@ -3347,7 +3347,7 @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a) return true; } - fpst = fpstatus_ptr(FPST_FPCR); + fpst = fpstatus_ptr(FPST_A32); vm = tcg_temp_new_i64(); vd = tcg_temp_new_i32(); vfp_load_reg64(vm, a->vm); diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index c16b59ab88..68ac393415 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -493,7 +493,7 @@ static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { TCGv_i32 tmp = tcg_temp_new_i32(); - if (TCG_TARGET_HAS_add2_i32) { + if (tcg_op_supported(INDEX_op_add2_i32, TCG_TYPE_I32, 0)) { tcg_gen_movi_i32(tmp, 0); tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp); tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp); diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index 2d37d7c9f2..084ee63d99 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -670,8 +670,10 @@ static inline CPUARMTBFlags arm_tbflags_from_tb(const TranslationBlock *tb) * Enum for argument to fpstatus_ptr(). */ typedef enum ARMFPStatusFlavour { - FPST_FPCR, - FPST_FPCR_F16, + FPST_A32, + FPST_A64, + FPST_A32_F16, + FPST_A64_F16, FPST_STD, FPST_STD_F16, } ARMFPStatusFlavour; @@ -684,10 +686,14 @@ typedef enum ARMFPStatusFlavour { * been set up to point to the requested field in the CPU state struct. * The options are: * - * FPST_FPCR - * for non-FP16 operations controlled by the FPCR - * FPST_FPCR_F16 - * for operations controlled by the FPCR where FPCR.FZ16 is to be used + * FPST_A32 + * for AArch32 non-FP16 operations controlled by the FPCR + * FPST_A64 + * for AArch64 non-FP16 operations controlled by the FPCR + * FPST_A32_F16 + * for AArch32 operations controlled by the FPCR where FPCR.FZ16 is to be used + * FPST_A64_F16 + * for AArch64 operations controlled by the FPCR where FPCR.FZ16 is to be used * FPST_STD * for A32/T32 Neon operations using the "standard FPSCR value" * FPST_STD_F16 @@ -699,11 +705,17 @@ static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour) int offset; switch (flavour) { - case FPST_FPCR: - offset = offsetof(CPUARMState, vfp.fp_status); + case FPST_A32: + offset = offsetof(CPUARMState, vfp.fp_status_a32); break; - case FPST_FPCR_F16: - offset = offsetof(CPUARMState, vfp.fp_status_f16); + case FPST_A64: + offset = offsetof(CPUARMState, vfp.fp_status_a64); + break; + case FPST_A32_F16: + offset = offsetof(CPUARMState, vfp.fp_status_f16_a32); + break; + case FPST_A64_F16: + offset = offsetof(CPUARMState, vfp.fp_status_f16_a64); break; case FPST_STD: offset = offsetof(CPUARMState, vfp.standard_fp_status); diff --git a/target/arm/tcg/vec_helper.c b/target/arm/tcg/vec_helper.c index e3083c6e84..7330b373c3 100644 --- a/target/arm/tcg/vec_helper.c +++ b/target/arm/tcg/vec_helper.c @@ -2060,14 +2060,14 @@ void HELPER(gvec_fmlal_a32)(void *vd, void *vn, void *vm, CPUARMState *env, uint32_t desc) { do_fmlal(vd, vn, vm, &env->vfp.standard_fp_status, desc, - get_flush_inputs_to_zero(&env->vfp.fp_status_f16)); + get_flush_inputs_to_zero(&env->vfp.fp_status_f16_a32)); } void HELPER(gvec_fmlal_a64)(void *vd, void *vn, void *vm, CPUARMState *env, uint32_t desc) { - do_fmlal(vd, vn, vm, &env->vfp.fp_status, desc, - get_flush_inputs_to_zero(&env->vfp.fp_status_f16)); + do_fmlal(vd, vn, vm, &env->vfp.fp_status_a64, desc, + get_flush_inputs_to_zero(&env->vfp.fp_status_f16_a64)); } void HELPER(sve2_fmlal_zzzw_s)(void *vd, void *vn, void *vm, void *va, @@ -2076,8 +2076,8 @@ void HELPER(sve2_fmlal_zzzw_s)(void *vd, void *vn, void *vm, void *va, intptr_t i, oprsz = simd_oprsz(desc); uint16_t negn = extract32(desc, SIMD_DATA_SHIFT, 1) << 15; intptr_t sel = extract32(desc, SIMD_DATA_SHIFT + 1, 1) * sizeof(float16); - float_status *status = &env->vfp.fp_status; - bool fz16 = get_flush_inputs_to_zero(&env->vfp.fp_status_f16); + float_status *status = &env->vfp.fp_status_a64; + bool fz16 = get_flush_inputs_to_zero(&env->vfp.fp_status_f16_a64); for (i = 0; i < oprsz; i += sizeof(float32)) { float16 nn_16 = *(float16 *)(vn + H1_2(i + sel)) ^ negn; @@ -2122,14 +2122,14 @@ void HELPER(gvec_fmlal_idx_a32)(void *vd, void *vn, void *vm, CPUARMState *env, uint32_t desc) { do_fmlal_idx(vd, vn, vm, &env->vfp.standard_fp_status, desc, - get_flush_inputs_to_zero(&env->vfp.fp_status_f16)); + get_flush_inputs_to_zero(&env->vfp.fp_status_f16_a32)); } void HELPER(gvec_fmlal_idx_a64)(void *vd, void *vn, void *vm, CPUARMState *env, uint32_t desc) { - do_fmlal_idx(vd, vn, vm, &env->vfp.fp_status, desc, - get_flush_inputs_to_zero(&env->vfp.fp_status_f16)); + do_fmlal_idx(vd, vn, vm, &env->vfp.fp_status_a64, desc, + get_flush_inputs_to_zero(&env->vfp.fp_status_f16_a64)); } void HELPER(sve2_fmlal_zzxw_s)(void *vd, void *vn, void *vm, void *va, @@ -2139,8 +2139,8 @@ void HELPER(sve2_fmlal_zzxw_s)(void *vd, void *vn, void *vm, void *va, uint16_t negn = extract32(desc, SIMD_DATA_SHIFT, 1) << 15; intptr_t sel = extract32(desc, SIMD_DATA_SHIFT + 1, 1) * sizeof(float16); intptr_t idx = extract32(desc, SIMD_DATA_SHIFT + 2, 3) * sizeof(float16); - float_status *status = &env->vfp.fp_status; - bool fz16 = get_flush_inputs_to_zero(&env->vfp.fp_status_f16); + float_status *status = &env->vfp.fp_status_a64; + bool fz16 = get_flush_inputs_to_zero(&env->vfp.fp_status_f16_a64); for (i = 0; i < oprsz; i += 16) { float16 mm_16 = *(float16 *)(vm + i + idx); @@ -2808,7 +2808,7 @@ bool is_ebf(CPUARMState *env, float_status *statusp, float_status *oddstatusp) */ bool ebf = is_a64(env) && env->vfp.fpcr & FPCR_EBF; - *statusp = env->vfp.fp_status; + *statusp = is_a64(env) ? env->vfp.fp_status_a64 : env->vfp.fp_status_a32; set_default_nan_mode(true, statusp); if (ebf) { diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c index fc20a56753..3c8f3e6588 100644 --- a/target/arm/vfp_helper.c +++ b/target/arm/vfp_helper.c @@ -34,42 +34,45 @@ #ifdef CONFIG_TCG /* Convert host exception flags to vfp form. */ -static inline int vfp_exceptbits_from_host(int host_bits) +static inline uint32_t vfp_exceptbits_from_host(int host_bits) { - int target_bits = 0; + uint32_t target_bits = 0; if (host_bits & float_flag_invalid) { - target_bits |= 1; + target_bits |= FPSR_IOC; } if (host_bits & float_flag_divbyzero) { - target_bits |= 2; + target_bits |= FPSR_DZC; } if (host_bits & float_flag_overflow) { - target_bits |= 4; + target_bits |= FPSR_OFC; } - if (host_bits & (float_flag_underflow | float_flag_output_denormal)) { - target_bits |= 8; + if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) { + target_bits |= FPSR_UFC; } if (host_bits & float_flag_inexact) { - target_bits |= 0x10; + target_bits |= FPSR_IXC; } - if (host_bits & float_flag_input_denormal) { - target_bits |= 0x80; + if (host_bits & float_flag_input_denormal_flushed) { + target_bits |= FPSR_IDC; } return target_bits; } static uint32_t vfp_get_fpsr_from_host(CPUARMState *env) { - uint32_t i; + uint32_t i = 0; - i = get_float_exception_flags(&env->vfp.fp_status); + i |= get_float_exception_flags(&env->vfp.fp_status_a32); + i |= get_float_exception_flags(&env->vfp.fp_status_a64); i |= get_float_exception_flags(&env->vfp.standard_fp_status); /* FZ16 does not generate an input denormal exception. */ - i |= (get_float_exception_flags(&env->vfp.fp_status_f16) - & ~float_flag_input_denormal); + i |= (get_float_exception_flags(&env->vfp.fp_status_f16_a32) + & ~float_flag_input_denormal_flushed); + i |= (get_float_exception_flags(&env->vfp.fp_status_f16_a64) + & ~float_flag_input_denormal_flushed); i |= (get_float_exception_flags(&env->vfp.standard_fp_status_f16) - & ~float_flag_input_denormal); + & ~float_flag_input_denormal_flushed); return vfp_exceptbits_from_host(i); } @@ -80,8 +83,10 @@ static void vfp_clear_float_status_exc_flags(CPUARMState *env) * values. The caller should have arranged for env->vfp.fpsr to * be the architecturally up-to-date exception flag information first. */ - set_float_exception_flags(0, &env->vfp.fp_status); - set_float_exception_flags(0, &env->vfp.fp_status_f16); + set_float_exception_flags(0, &env->vfp.fp_status_a32); + set_float_exception_flags(0, &env->vfp.fp_status_a64); + set_float_exception_flags(0, &env->vfp.fp_status_f16_a32); + set_float_exception_flags(0, &env->vfp.fp_status_f16_a64); set_float_exception_flags(0, &env->vfp.standard_fp_status); set_float_exception_flags(0, &env->vfp.standard_fp_status_f16); } @@ -108,25 +113,33 @@ static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask) i = float_round_to_zero; break; } - set_float_rounding_mode(i, &env->vfp.fp_status); - set_float_rounding_mode(i, &env->vfp.fp_status_f16); + set_float_rounding_mode(i, &env->vfp.fp_status_a32); + set_float_rounding_mode(i, &env->vfp.fp_status_a64); + set_float_rounding_mode(i, &env->vfp.fp_status_f16_a32); + set_float_rounding_mode(i, &env->vfp.fp_status_f16_a64); } if (changed & FPCR_FZ16) { bool ftz_enabled = val & FPCR_FZ16; - set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16); + set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16_a32); + set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_f16_a64); set_flush_to_zero(ftz_enabled, &env->vfp.standard_fp_status_f16); - set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16); + set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16_a32); + set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_f16_a64); set_flush_inputs_to_zero(ftz_enabled, &env->vfp.standard_fp_status_f16); } if (changed & FPCR_FZ) { bool ftz_enabled = val & FPCR_FZ; - set_flush_to_zero(ftz_enabled, &env->vfp.fp_status); - set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status); + set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_a32); + set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_a32); + set_flush_to_zero(ftz_enabled, &env->vfp.fp_status_a64); + set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status_a64); } if (changed & FPCR_DN) { bool dnan_enabled = val & FPCR_DN; - set_default_nan_mode(dnan_enabled, &env->vfp.fp_status); - set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16); + set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_a32); + set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_a64); + set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16_a32); + set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16_a64); } } @@ -360,9 +373,9 @@ void VFP_HELPER(cmpe, P)(ARGTYPE a, ARGTYPE b, CPUARMState *env) \ softfloat_to_vfp_compare(env, \ FLOATTYPE ## _compare(a, b, &env->vfp.FPST)); \ } -DO_VFP_cmp(h, float16, dh_ctype_f16, fp_status_f16) -DO_VFP_cmp(s, float32, float32, fp_status) -DO_VFP_cmp(d, float64, float64, fp_status) +DO_VFP_cmp(h, float16, dh_ctype_f16, fp_status_f16_a32) +DO_VFP_cmp(s, float32, float32, fp_status_a32) +DO_VFP_cmp(d, float64, float64, fp_status_a32) #undef DO_VFP_cmp /* Integer to float and float to integer conversions */ @@ -1120,7 +1133,7 @@ uint64_t HELPER(fjcvtzs)(float64 value, float_status *status) /* Normal inexact, denormal with flush-to-zero, or overflow or NaN */ inexact = e_new & (float_flag_inexact | - float_flag_input_denormal | + float_flag_input_denormal_flushed | float_flag_invalid); /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */ @@ -1132,7 +1145,7 @@ uint64_t HELPER(fjcvtzs)(float64 value, float_status *status) uint32_t HELPER(vjcvt)(float64 value, CPUARMState *env) { - uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status); + uint64_t pair = HELPER(fjcvtzs)(value, &env->vfp.fp_status_a32); uint32_t result = pair; uint32_t z = (pair >> 32) == 0; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 083d4f5a56..beea42d105 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -268,6 +268,10 @@ typedef struct CPUArchState { struct {} end_reset_fields; bool is_pa20; + + target_ulong kernel_entry; /* Linux kernel was loaded here */ + target_ulong cmdline_or_bootorder; + target_ulong initrd_base, initrd_end; } CPUHPPAState; /** diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc index 3a28b0cb31..0fa1664a24 100644 --- a/target/i386/tcg/emit.c.inc +++ b/target/i386/tcg/emit.c.inc @@ -24,13 +24,9 @@ * The exact opcode to check depends on 32- vs. 64-bit. */ #ifdef TARGET_X86_64 -#define TCG_TARGET_HAS_extract2_tl TCG_TARGET_HAS_extract2_i64 -#define TCG_TARGET_deposit_tl_valid TCG_TARGET_deposit_i64_valid -#define TCG_TARGET_extract_tl_valid TCG_TARGET_extract_i64_valid +#define INDEX_op_extract2_tl INDEX_op_extract2_i64 #else -#define TCG_TARGET_HAS_extract2_tl TCG_TARGET_HAS_extract2_i32 -#define TCG_TARGET_deposit_tl_valid TCG_TARGET_deposit_i32_valid -#define TCG_TARGET_extract_tl_valid TCG_TARGET_extract_i32_valid +#define INDEX_op_extract2_tl INDEX_op_extract2_i32 #endif #define MMX_OFFSET(reg) \ @@ -3001,7 +2997,7 @@ static void gen_PMOVMSKB(DisasContext *s, X86DecodedInsn *decode) tcg_gen_ld8u_tl(s->T0, tcg_env, offsetof(CPUX86State, xmm_t0.ZMM_B(vec_len - 1))); while (vec_len > 8) { vec_len -= 8; - if (TCG_TARGET_HAS_extract2_tl) { + if (tcg_op_supported(INDEX_op_extract2_tl, TCG_TYPE_TL, 0)) { /* * Load the next byte of the result into the high byte of T. * TCG does a similar expansion of deposit to shl+extract2; by @@ -3455,7 +3451,7 @@ static void gen_RCL(DisasContext *s, X86DecodedInsn *decode) } /* Compute high part, including incoming carry. */ - if (!have_1bit_cin || TCG_TARGET_deposit_tl_valid(1, TARGET_LONG_BITS - 1)) { + if (!have_1bit_cin || tcg_op_deposit_valid(TCG_TYPE_TL, 1, TARGET_LONG_BITS - 1)) { /* high = (T0 << 1) | cin */ TCGv cin = have_1bit_cin ? decode->cc_dst : decode->cc_src; tcg_gen_deposit_tl(high, cin, s->T0, 1, TARGET_LONG_BITS - 1); @@ -3507,7 +3503,7 @@ static void gen_RCR(DisasContext *s, X86DecodedInsn *decode) } /* Save incoming carry into high, it will be shifted later. */ - if (!have_1bit_cin || TCG_TARGET_deposit_tl_valid(1, TARGET_LONG_BITS - 1)) { + if (!have_1bit_cin || tcg_op_deposit_valid(TCG_TYPE_TL, 1, TARGET_LONG_BITS - 1)) { TCGv cin = have_1bit_cin ? decode->cc_dst : decode->cc_src; tcg_gen_deposit_tl(high, cin, s->T0, 1, TARGET_LONG_BITS - 1); } else { diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c index d0a1e2f3c8..3d764bc138 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -204,7 +204,7 @@ static void merge_exception_flags(CPUX86State *env, uint8_t old_flags) (new_flags & float_flag_overflow ? FPUS_OE : 0) | (new_flags & float_flag_underflow ? FPUS_UE : 0) | (new_flags & float_flag_inexact ? FPUS_PE : 0) | - (new_flags & float_flag_input_denormal ? FPUS_DE : 0))); + (new_flags & float_flag_input_denormal_flushed ? FPUS_DE : 0))); } static inline floatx80 helper_fdiv(CPUX86State *env, floatx80 a, floatx80 b) @@ -1829,7 +1829,7 @@ void helper_fxtract(CPUX86State *env) int shift = clz64(temp.l.lower); temp.l.lower <<= shift; expdif = 1 - EXPBIAS - shift; - float_raise(float_flag_input_denormal, &env->fp_status); + float_raise(float_flag_input_denormal_flushed, &env->fp_status); } else { expdif = EXPD(temp) - EXPBIAS; } @@ -3258,7 +3258,7 @@ void update_mxcsr_from_sse_status(CPUX86State *env) uint8_t flags = get_float_exception_flags(&env->sse_status); /* * The MXCSR denormal flag has opposite semantics to - * float_flag_input_denormal (the softfloat code sets that flag + * float_flag_input_denormal_flushed (the softfloat code sets that flag * only when flushing input denormals to zero, but SSE sets it * only when not flushing them to zero), so is not converted * here. @@ -3268,7 +3268,7 @@ void update_mxcsr_from_sse_status(CPUX86State *env) (flags & float_flag_overflow ? FPUS_OE : 0) | (flags & float_flag_underflow ? FPUS_UE : 0) | (flags & float_flag_inexact ? FPUS_PE : 0) | - (flags & float_flag_output_denormal ? FPUS_UE | FPUS_PE : + (flags & float_flag_output_denormal_flushed ? FPUS_UE | FPUS_PE : 0)); } diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index d611a60470..e91f4a5239 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -19,7 +19,7 @@ #include "cpu.h" #include "internals.h" #include "fpu/softfloat-helpers.h" -#include "cpu-csr.h" +#include "csr.h" #ifndef CONFIG_USER_ONLY #include "system/reset.h" #endif @@ -375,6 +375,33 @@ static int loongarch_cpu_mmu_index(CPUState *cs, bool ifetch) return MMU_DA_IDX; } +static void loongarch_la464_init_csr(Object *obj) +{ +#ifndef CONFIG_USER_ONLY + static bool initialized; + LoongArchCPU *cpu = LOONGARCH_CPU(obj); + CPULoongArchState *env = &cpu->env; + int i, num; + + if (!initialized) { + initialized = true; + num = FIELD_EX64(env->CSR_PRCFG1, CSR_PRCFG1, SAVE_NUM); + for (i = num; i < 16; i++) { + set_csr_flag(LOONGARCH_CSR_SAVE(i), CSRFL_UNUSED); + } + set_csr_flag(LOONGARCH_CSR_IMPCTL1, CSRFL_UNUSED); + set_csr_flag(LOONGARCH_CSR_IMPCTL2, CSRFL_UNUSED); + set_csr_flag(LOONGARCH_CSR_MERRCTL, CSRFL_UNUSED); + set_csr_flag(LOONGARCH_CSR_MERRINFO1, CSRFL_UNUSED); + set_csr_flag(LOONGARCH_CSR_MERRINFO2, CSRFL_UNUSED); + set_csr_flag(LOONGARCH_CSR_MERRENTRY, CSRFL_UNUSED); + set_csr_flag(LOONGARCH_CSR_MERRERA, CSRFL_UNUSED); + set_csr_flag(LOONGARCH_CSR_MERRSAVE, CSRFL_UNUSED); + set_csr_flag(LOONGARCH_CSR_CTAG, CSRFL_UNUSED); + } +#endif +} + static void loongarch_la464_initfn(Object *obj) { LoongArchCPU *cpu = LOONGARCH_CPU(obj); @@ -470,6 +497,7 @@ static void loongarch_la464_initfn(Object *obj) env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7); env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8); + loongarch_la464_init_csr(obj); loongarch_cpu_post_init(obj); } @@ -765,6 +793,54 @@ static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model) return oc; } +static void loongarch_cpu_dump_csr(CPUState *cs, FILE *f) +{ +#ifndef CONFIG_USER_ONLY + CPULoongArchState *env = cpu_env(cs); + CSRInfo *csr_info; + int64_t *addr; + int i, j, len, col = 0; + + qemu_fprintf(f, "\n"); + + /* Dump all generic CSR register */ + for (i = 0; i < LOONGARCH_CSR_DBG; i++) { + csr_info = get_csr(i); + if (!csr_info || (csr_info->flags & CSRFL_UNUSED)) { + if (i == (col + 3)) { + qemu_fprintf(f, "\n"); + } + + continue; + } + + if ((i > (col + 3)) || (i == col)) { + col = i & ~3; + qemu_fprintf(f, " CSR%03d:", col); + } + + addr = (void *)env + csr_info->offset; + qemu_fprintf(f, " %s ", csr_info->name); + len = strlen(csr_info->name); + for (; len < 6; len++) { + qemu_fprintf(f, " "); + } + + qemu_fprintf(f, "%" PRIx64, *addr); + j = find_last_bit((void *)addr, BITS_PER_LONG) & (BITS_PER_LONG - 1); + len += j / 4 + 1; + for (; len < 22; len++) { + qemu_fprintf(f, " "); + } + + if (i == (col + 3)) { + qemu_fprintf(f, "\n"); + } + } + qemu_fprintf(f, "\n"); +#endif +} + static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) { CPULoongArchState *env = cpu_env(cs); @@ -784,22 +860,8 @@ static void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) } } - qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD); - qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD); - qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN); - qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT); - qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA); - qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV); - qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI); - qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY); - qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 "," - " PRCFG3=%016" PRIx64 "\n", - env->CSR_PRCFG1, env->CSR_PRCFG2, env->CSR_PRCFG3); - qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY); - qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV); - qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA); - qemu_fprintf(f, "TCFG=%016" PRIx64 "\n", env->CSR_TCFG); - qemu_fprintf(f, "TVAL=%016" PRIx64 "\n", env->CSR_TVAL); + /* csr */ + loongarch_cpu_dump_csr(cs, f); /* fpr */ if (flags & CPU_DUMP_FPU) { diff --git a/target/loongarch/csr.c b/target/loongarch/csr.c new file mode 100644 index 0000000000..7ea0a30450 --- /dev/null +++ b/target/loongarch/csr.c @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2025 Loongson Technology Corporation Limited + */ +#include <stddef.h> +#include "qemu/osdep.h" +#include "cpu.h" +#include "csr.h" + +#define CSR_OFF_FUNCS(NAME, FL, RD, WR) \ + [LOONGARCH_CSR_##NAME] = { \ + .name = (stringify(NAME)), \ + .offset = offsetof(CPULoongArchState, CSR_##NAME), \ + .flags = FL, .readfn = RD, .writefn = WR \ + } + +#define CSR_OFF_ARRAY(NAME, N) \ + [LOONGARCH_CSR_##NAME(N)] = { \ + .name = (stringify(NAME##N)), \ + .offset = offsetof(CPULoongArchState, CSR_##NAME[N]), \ + .flags = 0, .readfn = NULL, .writefn = NULL \ + } + +#define CSR_OFF_FLAGS(NAME, FL) CSR_OFF_FUNCS(NAME, FL, NULL, NULL) +#define CSR_OFF(NAME) CSR_OFF_FLAGS(NAME, 0) + +static CSRInfo csr_info[] = { + CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB), + CSR_OFF(PRMD), + CSR_OFF_FLAGS(EUEN, CSRFL_EXITTB), + CSR_OFF_FLAGS(MISC, CSRFL_READONLY), + CSR_OFF(ECFG), + CSR_OFF_FLAGS(ESTAT, CSRFL_EXITTB), + CSR_OFF(ERA), + CSR_OFF(BADV), + CSR_OFF_FLAGS(BADI, CSRFL_READONLY), + CSR_OFF(EENTRY), + CSR_OFF(TLBIDX), + CSR_OFF(TLBEHI), + CSR_OFF(TLBELO0), + CSR_OFF(TLBELO1), + CSR_OFF_FLAGS(ASID, CSRFL_EXITTB), + CSR_OFF(PGDL), + CSR_OFF(PGDH), + CSR_OFF_FLAGS(PGD, CSRFL_READONLY), + CSR_OFF(PWCL), + CSR_OFF(PWCH), + CSR_OFF(STLBPS), + CSR_OFF(RVACFG), + CSR_OFF_FLAGS(CPUID, CSRFL_READONLY), + CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY), + CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY), + CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY), + CSR_OFF_ARRAY(SAVE, 0), + CSR_OFF_ARRAY(SAVE, 1), + CSR_OFF_ARRAY(SAVE, 2), + CSR_OFF_ARRAY(SAVE, 3), + CSR_OFF_ARRAY(SAVE, 4), + CSR_OFF_ARRAY(SAVE, 5), + CSR_OFF_ARRAY(SAVE, 6), + CSR_OFF_ARRAY(SAVE, 7), + CSR_OFF_ARRAY(SAVE, 8), + CSR_OFF_ARRAY(SAVE, 9), + CSR_OFF_ARRAY(SAVE, 10), + CSR_OFF_ARRAY(SAVE, 11), + CSR_OFF_ARRAY(SAVE, 12), + CSR_OFF_ARRAY(SAVE, 13), + CSR_OFF_ARRAY(SAVE, 14), + CSR_OFF_ARRAY(SAVE, 15), + CSR_OFF(TID), + CSR_OFF_FLAGS(TCFG, CSRFL_IO), + CSR_OFF_FLAGS(TVAL, CSRFL_READONLY | CSRFL_IO), + CSR_OFF(CNTC), + CSR_OFF_FLAGS(TICLR, CSRFL_IO), + CSR_OFF(LLBCTL), + CSR_OFF(IMPCTL1), + CSR_OFF(IMPCTL2), + CSR_OFF(TLBRENTRY), + CSR_OFF(TLBRBADV), + CSR_OFF(TLBRERA), + CSR_OFF(TLBRSAVE), + CSR_OFF(TLBRELO0), + CSR_OFF(TLBRELO1), + CSR_OFF(TLBREHI), + CSR_OFF(TLBRPRMD), + CSR_OFF(MERRCTL), + CSR_OFF(MERRINFO1), + CSR_OFF(MERRINFO2), + CSR_OFF(MERRENTRY), + CSR_OFF(MERRERA), + CSR_OFF(MERRSAVE), + CSR_OFF(CTAG), + CSR_OFF_ARRAY(DMW, 0), + CSR_OFF_ARRAY(DMW, 1), + CSR_OFF_ARRAY(DMW, 2), + CSR_OFF_ARRAY(DMW, 3), + CSR_OFF(DBG), + CSR_OFF(DERA), + CSR_OFF(DSAVE), +}; + +CSRInfo *get_csr(unsigned int csr_num) +{ + CSRInfo *csr; + + if (csr_num >= ARRAY_SIZE(csr_info)) { + return NULL; + } + + csr = &csr_info[csr_num]; + if (csr->offset == 0) { + return NULL; + } + + return csr; +} + +bool set_csr_flag(unsigned int csr_num, int flag) +{ + CSRInfo *csr; + + csr = get_csr(csr_num); + if (!csr) { + return false; + } + + csr->flags |= flag; + return true; +} diff --git a/target/loongarch/csr.h b/target/loongarch/csr.h new file mode 100644 index 0000000000..81a656baae --- /dev/null +++ b/target/loongarch/csr.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2025 Loongson Technology Corporation Limited + */ + +#ifndef TARGET_LOONGARCH_CSR_H +#define TARGET_LOONGARCH_CSR_H + +#include "cpu-csr.h" + +typedef void (*GenCSRFunc)(void); +enum { + CSRFL_READONLY = (1 << 0), + CSRFL_EXITTB = (1 << 1), + CSRFL_IO = (1 << 2), + CSRFL_UNUSED = (1 << 3), +}; + +typedef struct { + const char *name; + int offset; + int flags; + GenCSRFunc readfn; + GenCSRFunc writefn; +} CSRInfo; + +CSRInfo *get_csr(unsigned int csr_num); +bool set_csr_flag(unsigned int csr_num, int flag); +#endif /* TARGET_LOONGARCH_CSR_H */ diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build index 7817318287..20bd3e2f0a 100644 --- a/target/loongarch/meson.build +++ b/target/loongarch/meson.build @@ -10,6 +10,7 @@ loongarch_system_ss = ss.source_set() loongarch_system_ss.add(files( 'arch_dump.c', 'cpu_helper.c', + 'csr.c', 'loongarch-qmp-cmds.c', 'machine.c', )) diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc index 30f9b83fb2..3afa23af79 100644 --- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc +++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc @@ -5,7 +5,7 @@ * LoongArch translation routines for the privileged instructions. */ -#include "cpu-csr.h" +#include "csr.h" #ifdef CONFIG_USER_ONLY @@ -45,112 +45,6 @@ GEN_FALSE_TRANS(idle) typedef void (*GenCSRRead)(TCGv dest, TCGv_ptr env); typedef void (*GenCSRWrite)(TCGv dest, TCGv_ptr env, TCGv src); -typedef struct { - int offset; - int flags; - GenCSRRead readfn; - GenCSRWrite writefn; -} CSRInfo; - -enum { - CSRFL_READONLY = (1 << 0), - CSRFL_EXITTB = (1 << 1), - CSRFL_IO = (1 << 2), -}; - -#define CSR_OFF_FUNCS(NAME, FL, RD, WR) \ - [LOONGARCH_CSR_##NAME] = { \ - .offset = offsetof(CPULoongArchState, CSR_##NAME), \ - .flags = FL, .readfn = RD, .writefn = WR \ - } - -#define CSR_OFF_ARRAY(NAME, N) \ - [LOONGARCH_CSR_##NAME(N)] = { \ - .offset = offsetof(CPULoongArchState, CSR_##NAME[N]), \ - .flags = 0, .readfn = NULL, .writefn = NULL \ - } - -#define CSR_OFF_FLAGS(NAME, FL) \ - CSR_OFF_FUNCS(NAME, FL, NULL, NULL) - -#define CSR_OFF(NAME) \ - CSR_OFF_FLAGS(NAME, 0) - -static const CSRInfo csr_info[] = { - CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB), - CSR_OFF(PRMD), - CSR_OFF_FLAGS(EUEN, CSRFL_EXITTB), - CSR_OFF_FLAGS(MISC, CSRFL_READONLY), - CSR_OFF(ECFG), - CSR_OFF_FUNCS(ESTAT, CSRFL_EXITTB, NULL, gen_helper_csrwr_estat), - CSR_OFF(ERA), - CSR_OFF(BADV), - CSR_OFF_FLAGS(BADI, CSRFL_READONLY), - CSR_OFF(EENTRY), - CSR_OFF(TLBIDX), - CSR_OFF(TLBEHI), - CSR_OFF(TLBELO0), - CSR_OFF(TLBELO1), - CSR_OFF_FUNCS(ASID, CSRFL_EXITTB, NULL, gen_helper_csrwr_asid), - CSR_OFF(PGDL), - CSR_OFF(PGDH), - CSR_OFF_FUNCS(PGD, CSRFL_READONLY, gen_helper_csrrd_pgd, NULL), - CSR_OFF_FUNCS(PWCL, 0, NULL, gen_helper_csrwr_pwcl), - CSR_OFF(PWCH), - CSR_OFF(STLBPS), - CSR_OFF(RVACFG), - CSR_OFF_FUNCS(CPUID, CSRFL_READONLY, gen_helper_csrrd_cpuid, NULL), - CSR_OFF_FLAGS(PRCFG1, CSRFL_READONLY), - CSR_OFF_FLAGS(PRCFG2, CSRFL_READONLY), - CSR_OFF_FLAGS(PRCFG3, CSRFL_READONLY), - CSR_OFF_ARRAY(SAVE, 0), - CSR_OFF_ARRAY(SAVE, 1), - CSR_OFF_ARRAY(SAVE, 2), - CSR_OFF_ARRAY(SAVE, 3), - CSR_OFF_ARRAY(SAVE, 4), - CSR_OFF_ARRAY(SAVE, 5), - CSR_OFF_ARRAY(SAVE, 6), - CSR_OFF_ARRAY(SAVE, 7), - CSR_OFF_ARRAY(SAVE, 8), - CSR_OFF_ARRAY(SAVE, 9), - CSR_OFF_ARRAY(SAVE, 10), - CSR_OFF_ARRAY(SAVE, 11), - CSR_OFF_ARRAY(SAVE, 12), - CSR_OFF_ARRAY(SAVE, 13), - CSR_OFF_ARRAY(SAVE, 14), - CSR_OFF_ARRAY(SAVE, 15), - CSR_OFF(TID), - CSR_OFF_FUNCS(TCFG, CSRFL_IO, NULL, gen_helper_csrwr_tcfg), - CSR_OFF_FUNCS(TVAL, CSRFL_READONLY | CSRFL_IO, gen_helper_csrrd_tval, NULL), - CSR_OFF(CNTC), - CSR_OFF_FUNCS(TICLR, CSRFL_IO, NULL, gen_helper_csrwr_ticlr), - CSR_OFF(LLBCTL), - CSR_OFF(IMPCTL1), - CSR_OFF(IMPCTL2), - CSR_OFF(TLBRENTRY), - CSR_OFF(TLBRBADV), - CSR_OFF(TLBRERA), - CSR_OFF(TLBRSAVE), - CSR_OFF(TLBRELO0), - CSR_OFF(TLBRELO1), - CSR_OFF(TLBREHI), - CSR_OFF(TLBRPRMD), - CSR_OFF(MERRCTL), - CSR_OFF(MERRINFO1), - CSR_OFF(MERRINFO2), - CSR_OFF(MERRENTRY), - CSR_OFF(MERRERA), - CSR_OFF(MERRSAVE), - CSR_OFF(CTAG), - CSR_OFF_ARRAY(DMW, 0), - CSR_OFF_ARRAY(DMW, 1), - CSR_OFF_ARRAY(DMW, 2), - CSR_OFF_ARRAY(DMW, 3), - CSR_OFF(DBG), - CSR_OFF(DERA), - CSR_OFF(DSAVE), -}; - static bool check_plv(DisasContext *ctx) { if (ctx->plv == MMU_PLV_USER) { @@ -160,20 +54,37 @@ static bool check_plv(DisasContext *ctx) return false; } -static const CSRInfo *get_csr(unsigned csr_num) +static bool set_csr_trans_func(unsigned int csr_num, GenCSRRead readfn, + GenCSRWrite writefn) { - const CSRInfo *csr; + CSRInfo *csr; - if (csr_num >= ARRAY_SIZE(csr_info)) { - return NULL; - } - csr = &csr_info[csr_num]; - if (csr->offset == 0) { - return NULL; + csr = get_csr(csr_num); + if (!csr) { + return false; } - return csr; + + csr->readfn = (GenCSRFunc)readfn; + csr->writefn = (GenCSRFunc)writefn; + return true; } +#define SET_CSR_FUNC(NAME, read, write) \ + set_csr_trans_func(LOONGARCH_CSR_##NAME, read, write) + +void loongarch_csr_translate_init(void) +{ + SET_CSR_FUNC(ESTAT, NULL, gen_helper_csrwr_estat); + SET_CSR_FUNC(ASID, NULL, gen_helper_csrwr_asid); + SET_CSR_FUNC(PGD, gen_helper_csrrd_pgd, NULL); + SET_CSR_FUNC(PWCL, NULL, gen_helper_csrwr_pwcl); + SET_CSR_FUNC(CPUID, gen_helper_csrrd_cpuid, NULL); + SET_CSR_FUNC(TCFG, NULL, gen_helper_csrwr_tcfg); + SET_CSR_FUNC(TVAL, gen_helper_csrrd_tval, NULL); + SET_CSR_FUNC(TICLR, NULL, gen_helper_csrwr_ticlr); +} +#undef SET_CSR_FUNC + static bool check_csr_flags(DisasContext *ctx, const CSRInfo *csr, bool write) { if ((csr->flags & CSRFL_READONLY) && write) { @@ -191,6 +102,7 @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a) { TCGv dest; const CSRInfo *csr; + GenCSRRead readfn; if (check_plv(ctx)) { return false; @@ -202,8 +114,9 @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a) } else { check_csr_flags(ctx, csr, false); dest = gpr_dst(ctx, a->rd, EXT_NONE); - if (csr->readfn) { - csr->readfn(dest, tcg_env); + readfn = (GenCSRRead)csr->readfn; + if (readfn) { + readfn(dest, tcg_env); } else { tcg_gen_ld_tl(dest, tcg_env, csr->offset); } @@ -216,6 +129,7 @@ static bool trans_csrwr(DisasContext *ctx, arg_csrwr *a) { TCGv dest, src1; const CSRInfo *csr; + GenCSRWrite writefn; if (check_plv(ctx)) { return false; @@ -231,9 +145,10 @@ static bool trans_csrwr(DisasContext *ctx, arg_csrwr *a) return false; } src1 = gpr_src(ctx, a->rd, EXT_NONE); - if (csr->writefn) { + writefn = (GenCSRWrite)csr->writefn; + if (writefn) { dest = gpr_dst(ctx, a->rd, EXT_NONE); - csr->writefn(dest, tcg_env, src1); + writefn(dest, tcg_env, src1); } else { dest = tcg_temp_new(); tcg_gen_ld_tl(dest, tcg_env, csr->offset); @@ -247,6 +162,7 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) { TCGv src1, mask, oldv, newv, temp; const CSRInfo *csr; + GenCSRWrite writefn; if (check_plv(ctx)) { return false; @@ -277,8 +193,9 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a) tcg_gen_andc_tl(temp, oldv, mask); tcg_gen_or_tl(newv, newv, temp); - if (csr->writefn) { - csr->writefn(oldv, tcg_env, newv); + writefn = (GenCSRWrite)csr->writefn; + if (writefn) { + writefn(oldv, tcg_env, newv); } else { tcg_gen_st_tl(newv, tcg_env, csr->offset); } diff --git a/target/loongarch/tcg/tcg_loongarch.h b/target/loongarch/tcg/tcg_loongarch.h new file mode 100644 index 0000000000..da2539e995 --- /dev/null +++ b/target/loongarch/tcg/tcg_loongarch.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU LoongArch TCG interface + * + * Copyright (c) 2025 Loongson Technology Corporation Limited + */ +#ifndef TARGET_LOONGARCH_TCG_LOONGARCH_H +#define TARGET_LOONGARCH_TCG_LOONGARCH_H + +void loongarch_csr_translate_init(void); + +#endif /* TARGET_LOONGARCH_TCG_LOONGARCH_H */ diff --git a/target/loongarch/tcg/translate.c b/target/loongarch/tcg/translate.c index 68be999410..3480f54c71 100644 --- a/target/loongarch/tcg/translate.c +++ b/target/loongarch/tcg/translate.c @@ -16,6 +16,7 @@ #include "exec/log.h" #include "qemu/qemu-print.h" #include "fpu/softfloat.h" +#include "tcg_loongarch.h" #include "translate.h" #include "internals.h" #include "vec.h" @@ -358,4 +359,8 @@ void loongarch_translate_init(void) offsetof(CPULoongArchState, lladdr), "lladdr"); cpu_llval = tcg_global_mem_new(tcg_env, offsetof(CPULoongArchState, llval), "llval"); + +#ifndef CONFIG_USER_ONLY + loongarch_csr_translate_init(); +#endif } diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c index e3f4a18850..339b73ad7d 100644 --- a/target/m68k/fpu_helper.c +++ b/target/m68k/fpu_helper.c @@ -175,7 +175,7 @@ static int cpu_m68k_exceptbits_from_host(int host_bits) if (host_bits & float_flag_overflow) { target_bits |= 0x40; } - if (host_bits & (float_flag_underflow | float_flag_output_denormal)) { + if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) { target_bits |= 0x20; } if (host_bits & float_flag_divbyzero) { diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c index 1d40383ca4..ec38d9fde5 100644 --- a/target/mips/tcg/msa_helper.c +++ b/target/mips/tcg/msa_helper.c @@ -6231,7 +6231,7 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED; /* Set Inexact (I) when flushing inputs to zero */ - if ((ieee_exception_flags & float_flag_input_denormal) && + if ((ieee_exception_flags & float_flag_input_denormal_flushed) && (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) { if (action & CLEAR_IS_INEXACT) { mips_exception_flags &= ~FP_INEXACT; @@ -6241,7 +6241,7 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal) } /* Set Inexact (I) and Underflow (U) when flushing outputs to zero */ - if ((ieee_exception_flags & float_flag_output_denormal) && + if ((ieee_exception_flags & float_flag_output_denormal_flushed) && (env->active_tc.msacsr & MSACSR_FS_MASK) != 0) { mips_exception_flags |= FP_INEXACT; if (action & CLEAR_FS_UNDERFLOW) { diff --git a/target/rx/op_helper.c b/target/rx/op_helper.c index 691a12b2be..b3ed822dd1 100644 --- a/target/rx/op_helper.c +++ b/target/rx/op_helper.c @@ -99,8 +99,8 @@ static void update_fpsw(CPURXState *env, float32 ret, uintptr_t retaddr) if (xcpt & float_flag_inexact) { SET_FPSW(X); } - if ((xcpt & (float_flag_input_denormal - | float_flag_output_denormal)) + if ((xcpt & (float_flag_input_denormal_flushed + | float_flag_output_denormal_flushed)) && !FIELD_EX32(env->fpsw, FPSW, DN)) { env->fpsw = FIELD_DP32(env->fpsw, FPSW, CE, 1); } diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index 5d38aea143..1b72dcc5f5 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -43,7 +43,7 @@ static inline uint8_t f_get_excp_flags(CPUTriCoreState *env) & (float_flag_invalid | float_flag_overflow | float_flag_underflow - | float_flag_output_denormal + | float_flag_output_denormal_flushed | float_flag_divbyzero | float_flag_inexact); } @@ -99,7 +99,7 @@ static void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags) some_excp = 1; } - if (flags & float_flag_underflow || flags & float_flag_output_denormal) { + if (flags & float_flag_underflow || flags & float_flag_output_denormal_flushed) { env->FPU_FU = 1 << 31; some_excp = 1; } @@ -109,7 +109,7 @@ static void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags) some_excp = 1; } - if (flags & float_flag_inexact || flags & float_flag_output_denormal) { + if (flags & float_flag_inexact || flags & float_flag_output_denormal_flushed) { env->PSW |= 1 << 26; some_excp = 1; } diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 0ef3743f3e..6819b77668 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -3980,7 +3980,7 @@ static void decode_bit_andacc(DisasContext *ctx) pos1, pos2, &tcg_gen_andc_tl, &tcg_gen_and_tl); break; case OPC2_32_BIT_AND_NOR_T: - if (TCG_TARGET_HAS_andc_i32) { + if (tcg_op_supported(INDEX_op_andc_i32, TCG_TYPE_I32, 0)) { gen_bit_2op(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], pos1, pos2, &tcg_gen_or_tl, &tcg_gen_andc_tl); } else { @@ -4113,7 +4113,7 @@ static void decode_bit_orand(DisasContext *ctx) pos1, pos2, &tcg_gen_andc_tl, &tcg_gen_or_tl); break; case OPC2_32_BIT_OR_NOR_T: - if (TCG_TARGET_HAS_orc_i32) { + if (tcg_op_supported(INDEX_op_orc_i32, TCG_TYPE_I32, 0)) { gen_bit_2op(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], pos1, pos2, &tcg_gen_or_tl, &tcg_gen_orc_tl); } else { diff --git a/tcg/aarch64/tcg-target-has.h b/tcg/aarch64/tcg-target-has.h new file mode 100644 index 0000000000..39f01c14cd --- /dev/null +++ b/tcg/aarch64/tcg-target-has.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Define target-specific opcode support + * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +#include "host/cpuinfo.h" + +#define have_lse (cpuinfo & CPUINFO_LSE) +#define have_lse2 (cpuinfo & CPUINFO_LSE2) + +/* optional instructions */ +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_andc_i32 1 +#define TCG_TARGET_HAS_orc_i32 1 +#define TCG_TARGET_HAS_eqv_i32 1 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 1 +#define TCG_TARGET_HAS_ctz_i32 1 +#define TCG_TARGET_HAS_ctpop_i32 0 +#define TCG_TARGET_HAS_extract2_i32 1 +#define TCG_TARGET_HAS_negsetcond_i32 1 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 0 +#define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_extr_i64_i32 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 1 +#define TCG_TARGET_HAS_ext16u_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_andc_i64 1 +#define TCG_TARGET_HAS_orc_i64 1 +#define TCG_TARGET_HAS_eqv_i64 1 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 1 +#define TCG_TARGET_HAS_ctz_i64 1 +#define TCG_TARGET_HAS_ctpop_i64 0 +#define TCG_TARGET_HAS_extract2_i64 1 +#define TCG_TARGET_HAS_negsetcond_i64 1 +#define TCG_TARGET_HAS_add2_i64 1 +#define TCG_TARGET_HAS_sub2_i64 1 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 + +/* + * Without FEAT_LSE2, we must use LDXP+STXP to implement atomic 128-bit load, + * which requires writable pages. We must defer to the helper for user-only, + * but in system mode all ram is writable for the host. + */ +#ifdef CONFIG_USER_ONLY +#define TCG_TARGET_HAS_qemu_ldst_i128 have_lse2 +#else +#define TCG_TARGET_HAS_qemu_ldst_i128 1 +#endif + +#define TCG_TARGET_HAS_tst 1 + +#define TCG_TARGET_HAS_v64 1 +#define TCG_TARGET_HAS_v128 1 +#define TCG_TARGET_HAS_v256 0 + +#define TCG_TARGET_HAS_andc_vec 1 +#define TCG_TARGET_HAS_orc_vec 1 +#define TCG_TARGET_HAS_nand_vec 0 +#define TCG_TARGET_HAS_nor_vec 0 +#define TCG_TARGET_HAS_eqv_vec 0 +#define TCG_TARGET_HAS_not_vec 1 +#define TCG_TARGET_HAS_neg_vec 1 +#define TCG_TARGET_HAS_abs_vec 1 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 0 +#define TCG_TARGET_HAS_shi_vec 1 +#define TCG_TARGET_HAS_shs_vec 0 +#define TCG_TARGET_HAS_shv_vec 1 +#define TCG_TARGET_HAS_mul_vec 1 +#define TCG_TARGET_HAS_sat_vec 1 +#define TCG_TARGET_HAS_minmax_vec 1 +#define TCG_TARGET_HAS_bitsel_vec 1 +#define TCG_TARGET_HAS_cmpsel_vec 0 +#define TCG_TARGET_HAS_tst_vec 1 + +#define TCG_TARGET_extract_valid(type, ofs, len) 1 +#define TCG_TARGET_sextract_valid(type, ofs, len) 1 +#define TCG_TARGET_deposit_valid(type, ofs, len) 1 + +#endif diff --git a/tcg/aarch64/tcg-target-mo.h b/tcg/aarch64/tcg-target-mo.h new file mode 100644 index 0000000000..e8e8923014 --- /dev/null +++ b/tcg/aarch64/tcg-target-mo.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Define target-specific memory model + * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +#define TCG_TARGET_DEFAULT_MO 0 + +#endif diff --git a/tcg/aarch64/tcg-target.opc.h b/tcg/aarch64/tcg-target-opc.h.inc index bce30accd9..5382315c41 100644 --- a/tcg/aarch64/tcg-target.opc.h +++ b/tcg/aarch64/tcg-target-opc.h.inc @@ -11,5 +11,5 @@ * consider these to be UNSPEC with names. */ -DEF(aa64_sshl_vec, 1, 2, 0, IMPLVEC) -DEF(aa64_sli_vec, 1, 2, 1, IMPLVEC) +DEF(aa64_sshl_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(aa64_sli_vec, 1, 2, 1, TCG_OPF_VECTOR) diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc index ffa8a3e519..66eb4b73b5 100644 --- a/tcg/aarch64/tcg-target.c.inc +++ b/tcg/aarch64/tcg-target.c.inc @@ -10,10 +10,21 @@ * See the COPYING file in the top-level directory for details. */ -#include "../tcg-ldst.c.inc" -#include "../tcg-pool.c.inc" #include "qemu/bitops.h" +/* Used for function call generation. */ +#define TCG_REG_CALL_STACK TCG_REG_SP +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_STACK_OFFSET 0 +#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL +#ifdef CONFIG_DARWIN +# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL +#else +# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN +#endif +#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL + /* We're going to re-use TCGType in setting of the SF bit, which controls the size of the operation performed. If we know the values match, it makes things much cleaner. */ @@ -2104,14 +2115,10 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, flush_idcache_range(jmp_rx, jmp_rw, 4); } -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType ext, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) { - /* 99% of the time, we can signal the use of extension registers - by looking to see if the opcode handles 64-bit data. */ - TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; - /* Hoist the loads of the most common arguments. */ TCGArg a0 = args[0]; TCGArg a1 = args[1]; @@ -2443,7 +2450,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_extract_i64: case INDEX_op_extract_i32: - tcg_out_ubfm(s, ext, a0, a1, a2, a2 + args[3] - 1); + if (a2 == 0) { + uint64_t mask = MAKE_64BIT_MASK(0, args[3]); + tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, mask); + } else { + tcg_out_ubfm(s, ext, a0, a1, a2, a2 + args[3] - 1); + } break; case INDEX_op_sextract_i64: @@ -2951,7 +2963,8 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, } } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -3147,7 +3160,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) return C_O1_I2(w, 0, w); default: - g_assert_not_reached(); + return C_NotImplemented; } } diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index 8bd9e6a5eb..0dd6e1f069 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -13,8 +13,6 @@ #ifndef AARCH64_TCG_TARGET_H #define AARCH64_TCG_TARGET_H -#include "host/cpuinfo.h" - #define TCG_TARGET_INSN_UNIT_SIZE 4 #define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) @@ -49,128 +47,4 @@ typedef enum { #define TCG_TARGET_NB_REGS 64 -/* used for function call generation */ -#define TCG_REG_CALL_STACK TCG_REG_SP -#define TCG_TARGET_STACK_ALIGN 16 -#define TCG_TARGET_CALL_STACK_OFFSET 0 -#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL -#ifdef CONFIG_DARWIN -# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL -#else -# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN -#endif -#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL - -#define have_lse (cpuinfo & CPUINFO_LSE) -#define have_lse2 (cpuinfo & CPUINFO_LSE2) - -/* optional instructions */ -#define TCG_TARGET_HAS_div_i32 1 -#define TCG_TARGET_HAS_rem_i32 1 -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_ext8u_i32 1 -#define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_andc_i32 1 -#define TCG_TARGET_HAS_orc_i32 1 -#define TCG_TARGET_HAS_eqv_i32 1 -#define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_clz_i32 1 -#define TCG_TARGET_HAS_ctz_i32 1 -#define TCG_TARGET_HAS_ctpop_i32 0 -#define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 1 -#define TCG_TARGET_HAS_sextract_i32 1 -#define TCG_TARGET_HAS_extract2_i32 1 -#define TCG_TARGET_HAS_negsetcond_i32 1 -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#define TCG_TARGET_HAS_mulu2_i32 0 -#define TCG_TARGET_HAS_muls2_i32 0 -#define TCG_TARGET_HAS_muluh_i32 0 -#define TCG_TARGET_HAS_mulsh_i32 0 -#define TCG_TARGET_HAS_extr_i64_i32 0 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -#define TCG_TARGET_HAS_div_i64 1 -#define TCG_TARGET_HAS_rem_i64 1 -#define TCG_TARGET_HAS_ext8s_i64 1 -#define TCG_TARGET_HAS_ext16s_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i64 1 -#define TCG_TARGET_HAS_ext16u_i64 1 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 1 -#define TCG_TARGET_HAS_bswap32_i64 1 -#define TCG_TARGET_HAS_bswap64_i64 1 -#define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_rot_i64 1 -#define TCG_TARGET_HAS_andc_i64 1 -#define TCG_TARGET_HAS_orc_i64 1 -#define TCG_TARGET_HAS_eqv_i64 1 -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 0 -#define TCG_TARGET_HAS_clz_i64 1 -#define TCG_TARGET_HAS_ctz_i64 1 -#define TCG_TARGET_HAS_ctpop_i64 0 -#define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 1 -#define TCG_TARGET_HAS_sextract_i64 1 -#define TCG_TARGET_HAS_extract2_i64 1 -#define TCG_TARGET_HAS_negsetcond_i64 1 -#define TCG_TARGET_HAS_add2_i64 1 -#define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i64 0 -#define TCG_TARGET_HAS_muls2_i64 0 -#define TCG_TARGET_HAS_muluh_i64 1 -#define TCG_TARGET_HAS_mulsh_i64 1 - -/* - * Without FEAT_LSE2, we must use LDXP+STXP to implement atomic 128-bit load, - * which requires writable pages. We must defer to the helper for user-only, - * but in system mode all ram is writable for the host. - */ -#ifdef CONFIG_USER_ONLY -#define TCG_TARGET_HAS_qemu_ldst_i128 have_lse2 -#else -#define TCG_TARGET_HAS_qemu_ldst_i128 1 -#endif - -#define TCG_TARGET_HAS_tst 1 - -#define TCG_TARGET_HAS_v64 1 -#define TCG_TARGET_HAS_v128 1 -#define TCG_TARGET_HAS_v256 0 - -#define TCG_TARGET_HAS_andc_vec 1 -#define TCG_TARGET_HAS_orc_vec 1 -#define TCG_TARGET_HAS_nand_vec 0 -#define TCG_TARGET_HAS_nor_vec 0 -#define TCG_TARGET_HAS_eqv_vec 0 -#define TCG_TARGET_HAS_not_vec 1 -#define TCG_TARGET_HAS_neg_vec 1 -#define TCG_TARGET_HAS_abs_vec 1 -#define TCG_TARGET_HAS_roti_vec 0 -#define TCG_TARGET_HAS_rots_vec 0 -#define TCG_TARGET_HAS_rotv_vec 0 -#define TCG_TARGET_HAS_shi_vec 1 -#define TCG_TARGET_HAS_shs_vec 0 -#define TCG_TARGET_HAS_shv_vec 1 -#define TCG_TARGET_HAS_mul_vec 1 -#define TCG_TARGET_HAS_sat_vec 1 -#define TCG_TARGET_HAS_minmax_vec 1 -#define TCG_TARGET_HAS_bitsel_vec 1 -#define TCG_TARGET_HAS_cmpsel_vec 0 -#define TCG_TARGET_HAS_tst_vec 1 - -#define TCG_TARGET_DEFAULT_MO (0) -#define TCG_TARGET_NEED_LDST_LABELS -#define TCG_TARGET_NEED_POOL_LABELS - #endif /* AARCH64_TCG_TARGET_H */ diff --git a/tcg/arm/tcg-target-has.h b/tcg/arm/tcg-target-has.h new file mode 100644 index 0000000000..e3510a8f7a --- /dev/null +++ b/tcg/arm/tcg-target-has.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2008 Fabrice Bellard + * Copyright (c) 2008 Andrzej Zaborowski + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +extern int arm_arch; + +#define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7) + +#ifdef __ARM_ARCH_EXT_IDIV__ +#define use_idiv_instructions 1 +#else +extern bool use_idiv_instructions; +#endif +#ifdef __ARM_NEON__ +#define use_neon_instructions 1 +#else +extern bool use_neon_instructions; +#endif + +/* optional instructions */ +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 0 /* and r0, r1, #0xff */ +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_andc_i32 1 +#define TCG_TARGET_HAS_orc_i32 0 +#define TCG_TARGET_HAS_eqv_i32 0 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 1 +#define TCG_TARGET_HAS_ctz_i32 use_armv7_instructions +#define TCG_TARGET_HAS_ctpop_i32 0 +#define TCG_TARGET_HAS_extract2_i32 1 +#define TCG_TARGET_HAS_negsetcond_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 1 +#define TCG_TARGET_HAS_muls2_i32 1 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_div_i32 use_idiv_instructions +#define TCG_TARGET_HAS_rem_i32 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +#define TCG_TARGET_HAS_qemu_ldst_i128 0 + +#define TCG_TARGET_HAS_tst 1 + +#define TCG_TARGET_HAS_v64 use_neon_instructions +#define TCG_TARGET_HAS_v128 use_neon_instructions +#define TCG_TARGET_HAS_v256 0 + +#define TCG_TARGET_HAS_andc_vec 1 +#define TCG_TARGET_HAS_orc_vec 1 +#define TCG_TARGET_HAS_nand_vec 0 +#define TCG_TARGET_HAS_nor_vec 0 +#define TCG_TARGET_HAS_eqv_vec 0 +#define TCG_TARGET_HAS_not_vec 1 +#define TCG_TARGET_HAS_neg_vec 1 +#define TCG_TARGET_HAS_abs_vec 1 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 0 +#define TCG_TARGET_HAS_shi_vec 1 +#define TCG_TARGET_HAS_shs_vec 0 +#define TCG_TARGET_HAS_shv_vec 0 +#define TCG_TARGET_HAS_mul_vec 1 +#define TCG_TARGET_HAS_sat_vec 1 +#define TCG_TARGET_HAS_minmax_vec 1 +#define TCG_TARGET_HAS_bitsel_vec 1 +#define TCG_TARGET_HAS_cmpsel_vec 0 +#define TCG_TARGET_HAS_tst_vec 1 + +static inline bool +tcg_target_extract_valid(TCGType type, unsigned ofs, unsigned len) +{ + if (use_armv7_instructions) { + return true; /* SBFX or UBFX */ + } + switch (len) { + case 8: /* SXTB or UXTB */ + case 16: /* SXTH or UXTH */ + return (ofs % 8) == 0; + } + return false; +} + +#define TCG_TARGET_extract_valid tcg_target_extract_valid +#define TCG_TARGET_sextract_valid tcg_target_extract_valid +#define TCG_TARGET_deposit_valid(type, ofs, len) use_armv7_instructions + +#endif diff --git a/tcg/arm/tcg-target-mo.h b/tcg/arm/tcg-target-mo.h new file mode 100644 index 0000000000..12542dfd1c --- /dev/null +++ b/tcg/arm/tcg-target-mo.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2008 Fabrice Bellard + * Copyright (c) 2008 Andrzej Zaborowski + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +#define TCG_TARGET_DEFAULT_MO 0 + +#endif diff --git a/tcg/arm/tcg-target.opc.h b/tcg/arm/tcg-target-opc.h.inc index d38af9a808..70394e0282 100644 --- a/tcg/arm/tcg-target.opc.h +++ b/tcg/arm/tcg-target-opc.h.inc @@ -11,6 +11,6 @@ * consider these to be UNSPEC with names. */ -DEF(arm_sli_vec, 1, 2, 1, IMPLVEC) -DEF(arm_sshl_vec, 1, 2, 0, IMPLVEC) -DEF(arm_ushl_vec, 1, 2, 0, IMPLVEC) +DEF(arm_sli_vec, 1, 2, 1, TCG_OPF_VECTOR) +DEF(arm_sshl_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(arm_ushl_vec, 1, 2, 0, TCG_OPF_VECTOR) diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc index 56072d89a2..12dad7307f 100644 --- a/tcg/arm/tcg-target.c.inc +++ b/tcg/arm/tcg-target.c.inc @@ -23,8 +23,6 @@ */ #include "elf.h" -#include "../tcg-ldst.c.inc" -#include "../tcg-pool.c.inc" int arm_arch = __ARM_ARCH; @@ -35,6 +33,14 @@ bool use_idiv_instructions; bool use_neon_instructions; #endif +/* Used for function call generation. */ +#define TCG_TARGET_STACK_ALIGN 8 +#define TCG_TARGET_CALL_STACK_OFFSET 0 +#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN +#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN +#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF + #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", @@ -1030,19 +1036,61 @@ static void tcg_out_deposit(TCGContext *s, ARMCond cond, TCGReg rd, static void tcg_out_extract(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn, int ofs, int len) { - /* ubfx */ - tcg_out32(s, 0x07e00050 | (cond << 28) | (rd << 12) | rn - | (ofs << 7) | ((len - 1) << 16)); + /* According to gcc, AND can be faster. */ + if (ofs == 0 && len <= 8) { + tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, + encode_imm_nofail((1 << len) - 1)); + return; + } + + if (use_armv7_instructions) { + /* ubfx */ + tcg_out32(s, 0x07e00050 | (cond << 28) | (rd << 12) | rn + | (ofs << 7) | ((len - 1) << 16)); + return; + } + + assert(ofs % 8 == 0); + switch (len) { + case 8: + /* uxtb */ + tcg_out32(s, 0x06ef0070 | (cond << 28) | (rd << 12) | (ofs << 7) | rn); + break; + case 16: + /* uxth */ + tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | (ofs << 7) | rn); + break; + default: + g_assert_not_reached(); + } } static void tcg_out_sextract(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn, int ofs, int len) { - /* sbfx */ - tcg_out32(s, 0x07a00050 | (cond << 28) | (rd << 12) | rn - | (ofs << 7) | ((len - 1) << 16)); + if (use_armv7_instructions) { + /* sbfx */ + tcg_out32(s, 0x07a00050 | (cond << 28) | (rd << 12) | rn + | (ofs << 7) | ((len - 1) << 16)); + return; + } + + assert(ofs % 8 == 0); + switch (len) { + case 8: + /* sxtb */ + tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | (ofs << 7) | rn); + break; + case 16: + /* sxth */ + tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | (ofs << 7) | rn); + break; + default: + g_assert_not_reached(); + } } + static void tcg_out_ld32u(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn, int32_t offset) { @@ -1799,7 +1847,7 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, flush_idcache_range(jmp_rx, jmp_rw, 4); } -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) { @@ -2118,7 +2166,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, } } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -2254,7 +2303,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_bitsel_vec: return C_O1_I3(w, w, w, w); default: - g_assert_not_reached(); + return C_NotImplemented; } } diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index fb7261499b..4f9f877121 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -26,10 +26,6 @@ #ifndef ARM_TCG_TARGET_H #define ARM_TCG_TARGET_H -extern int arm_arch; - -#define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7) - #define TCG_TARGET_INSN_UNIT_SIZE 4 #define MAX_CODE_GEN_BUFFER_SIZE UINT32_MAX @@ -74,86 +70,4 @@ typedef enum { #define TCG_TARGET_NB_REGS 32 -#ifdef __ARM_ARCH_EXT_IDIV__ -#define use_idiv_instructions 1 -#else -extern bool use_idiv_instructions; -#endif -#ifdef __ARM_NEON__ -#define use_neon_instructions 1 -#else -extern bool use_neon_instructions; -#endif - -/* used for function call generation */ -#define TCG_TARGET_STACK_ALIGN 8 -#define TCG_TARGET_CALL_STACK_OFFSET 0 -#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN -#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN -#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF - -/* optional instructions */ -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_ext8u_i32 0 /* and r0, r1, #0xff */ -#define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_andc_i32 1 -#define TCG_TARGET_HAS_orc_i32 0 -#define TCG_TARGET_HAS_eqv_i32 0 -#define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_clz_i32 1 -#define TCG_TARGET_HAS_ctz_i32 use_armv7_instructions -#define TCG_TARGET_HAS_ctpop_i32 0 -#define TCG_TARGET_HAS_deposit_i32 use_armv7_instructions -#define TCG_TARGET_HAS_extract_i32 use_armv7_instructions -#define TCG_TARGET_HAS_sextract_i32 use_armv7_instructions -#define TCG_TARGET_HAS_extract2_i32 1 -#define TCG_TARGET_HAS_negsetcond_i32 1 -#define TCG_TARGET_HAS_mulu2_i32 1 -#define TCG_TARGET_HAS_muls2_i32 1 -#define TCG_TARGET_HAS_muluh_i32 0 -#define TCG_TARGET_HAS_mulsh_i32 0 -#define TCG_TARGET_HAS_div_i32 use_idiv_instructions -#define TCG_TARGET_HAS_rem_i32 0 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -#define TCG_TARGET_HAS_qemu_ldst_i128 0 - -#define TCG_TARGET_HAS_tst 1 - -#define TCG_TARGET_HAS_v64 use_neon_instructions -#define TCG_TARGET_HAS_v128 use_neon_instructions -#define TCG_TARGET_HAS_v256 0 - -#define TCG_TARGET_HAS_andc_vec 1 -#define TCG_TARGET_HAS_orc_vec 1 -#define TCG_TARGET_HAS_nand_vec 0 -#define TCG_TARGET_HAS_nor_vec 0 -#define TCG_TARGET_HAS_eqv_vec 0 -#define TCG_TARGET_HAS_not_vec 1 -#define TCG_TARGET_HAS_neg_vec 1 -#define TCG_TARGET_HAS_abs_vec 1 -#define TCG_TARGET_HAS_roti_vec 0 -#define TCG_TARGET_HAS_rots_vec 0 -#define TCG_TARGET_HAS_rotv_vec 0 -#define TCG_TARGET_HAS_shi_vec 1 -#define TCG_TARGET_HAS_shs_vec 0 -#define TCG_TARGET_HAS_shv_vec 0 -#define TCG_TARGET_HAS_mul_vec 1 -#define TCG_TARGET_HAS_sat_vec 1 -#define TCG_TARGET_HAS_minmax_vec 1 -#define TCG_TARGET_HAS_bitsel_vec 1 -#define TCG_TARGET_HAS_cmpsel_vec 0 -#define TCG_TARGET_HAS_tst_vec 1 - -#define TCG_TARGET_DEFAULT_MO (0) -#define TCG_TARGET_NEED_LDST_LABELS -#define TCG_TARGET_NEED_POOL_LABELS - #endif diff --git a/tcg/i386/tcg-target-has.h b/tcg/i386/tcg-target-has.h new file mode 100644 index 0000000000..63768ff058 --- /dev/null +++ b/tcg/i386/tcg-target-has.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2008 Fabrice Bellard + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +#include "host/cpuinfo.h" + +#define have_bmi1 (cpuinfo & CPUINFO_BMI1) +#define have_popcnt (cpuinfo & CPUINFO_POPCNT) +#define have_avx1 (cpuinfo & CPUINFO_AVX1) +#define have_avx2 (cpuinfo & CPUINFO_AVX2) +#define have_movbe (cpuinfo & CPUINFO_MOVBE) + +/* + * There are interesting instructions in AVX512, so long as we have AVX512VL, + * which indicates support for EVEX on sizes smaller than 512 bits. + */ +#define have_avx512vl ((cpuinfo & CPUINFO_AVX512VL) && \ + (cpuinfo & CPUINFO_AVX512F)) +#define have_avx512bw ((cpuinfo & CPUINFO_AVX512BW) && have_avx512vl) +#define have_avx512dq ((cpuinfo & CPUINFO_AVX512DQ) && have_avx512vl) +#define have_avx512vbmi2 ((cpuinfo & CPUINFO_AVX512VBMI2) && have_avx512vl) + +/* optional instructions */ +#define TCG_TARGET_HAS_div2_i32 1 +#define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_andc_i32 have_bmi1 +#define TCG_TARGET_HAS_orc_i32 0 +#define TCG_TARGET_HAS_eqv_i32 0 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 1 +#define TCG_TARGET_HAS_ctz_i32 1 +#define TCG_TARGET_HAS_ctpop_i32 have_popcnt +#define TCG_TARGET_HAS_extract2_i32 1 +#define TCG_TARGET_HAS_negsetcond_i32 1 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 1 +#define TCG_TARGET_HAS_muls2_i32 1 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 + +#if TCG_TARGET_REG_BITS == 64 +/* Keep 32-bit values zero-extended in a register. */ +#define TCG_TARGET_HAS_extr_i64_i32 1 +#define TCG_TARGET_HAS_div2_i64 1 +#define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 1 +#define TCG_TARGET_HAS_ext16u_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_andc_i64 have_bmi1 +#define TCG_TARGET_HAS_orc_i64 0 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 1 +#define TCG_TARGET_HAS_ctz_i64 1 +#define TCG_TARGET_HAS_ctpop_i64 have_popcnt +#define TCG_TARGET_HAS_extract2_i64 1 +#define TCG_TARGET_HAS_negsetcond_i64 1 +#define TCG_TARGET_HAS_add2_i64 1 +#define TCG_TARGET_HAS_sub2_i64 1 +#define TCG_TARGET_HAS_mulu2_i64 1 +#define TCG_TARGET_HAS_muls2_i64 1 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 +#else +#define TCG_TARGET_HAS_qemu_st8_i32 1 +#endif + +#define TCG_TARGET_HAS_qemu_ldst_i128 \ + (TCG_TARGET_REG_BITS == 64 && (cpuinfo & CPUINFO_ATOMIC_VMOVDQA)) + +#define TCG_TARGET_HAS_tst 1 + +/* We do not support older SSE systems, only beginning with AVX1. */ +#define TCG_TARGET_HAS_v64 have_avx1 +#define TCG_TARGET_HAS_v128 have_avx1 +#define TCG_TARGET_HAS_v256 have_avx2 + +#define TCG_TARGET_HAS_andc_vec 1 +#define TCG_TARGET_HAS_orc_vec have_avx512vl +#define TCG_TARGET_HAS_nand_vec have_avx512vl +#define TCG_TARGET_HAS_nor_vec have_avx512vl +#define TCG_TARGET_HAS_eqv_vec have_avx512vl +#define TCG_TARGET_HAS_not_vec have_avx512vl +#define TCG_TARGET_HAS_neg_vec 0 +#define TCG_TARGET_HAS_abs_vec 1 +#define TCG_TARGET_HAS_roti_vec have_avx512vl +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec have_avx512vl +#define TCG_TARGET_HAS_shi_vec 1 +#define TCG_TARGET_HAS_shs_vec 1 +#define TCG_TARGET_HAS_shv_vec have_avx2 +#define TCG_TARGET_HAS_mul_vec 1 +#define TCG_TARGET_HAS_sat_vec 1 +#define TCG_TARGET_HAS_minmax_vec 1 +#define TCG_TARGET_HAS_bitsel_vec have_avx512vl +#define TCG_TARGET_HAS_cmpsel_vec 1 +#define TCG_TARGET_HAS_tst_vec have_avx512bw + +#define TCG_TARGET_deposit_valid(type, ofs, len) \ + (((ofs) == 0 && ((len) == 8 || (len) == 16)) || \ + (TCG_TARGET_REG_BITS == 32 && (ofs) == 8 && (len) == 8)) + +/* + * Check for the possibility of low byte/word extraction, high-byte extraction + * and zero-extending 32-bit right-shift. + * + * We cannot sign-extend from high byte to 64-bits without using the + * REX prefix that explicitly excludes access to the high-byte registers. + */ +static inline bool +tcg_target_sextract_valid(TCGType type, unsigned ofs, unsigned len) +{ + switch (ofs) { + case 0: + switch (len) { + case 8: + case 16: + return true; + case 32: + return type == TCG_TYPE_I64; + } + return false; + case 8: + return len == 8 && type == TCG_TYPE_I32; + } + return false; +} +#define TCG_TARGET_sextract_valid tcg_target_sextract_valid + +static inline bool +tcg_target_extract_valid(TCGType type, unsigned ofs, unsigned len) +{ + if (type == TCG_TYPE_I64 && ofs + len == 32) { + return true; + } + switch (ofs) { + case 0: + return len == 8 || len == 16; + case 8: + return len == 8; + } + return false; +} +#define TCG_TARGET_extract_valid tcg_target_extract_valid + +#endif diff --git a/tcg/i386/tcg-target-mo.h b/tcg/i386/tcg-target-mo.h new file mode 100644 index 0000000000..7567dc7248 --- /dev/null +++ b/tcg/i386/tcg-target-mo.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2008 Fabrice Bellard + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +/* + * This defines the natural memory order supported by this architecture + * before guarantees made by various barrier instructions. + * + * The x86 has a pretty strong memory ordering which only really + * allows for some stores to be re-ordered after loads. + */ +#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) + +#endif diff --git a/tcg/i386/tcg-target.opc.h b/tcg/i386/tcg-target-opc.h.inc index 4ffc084bda..8cc0dbaeaf 100644 --- a/tcg/i386/tcg-target.opc.h +++ b/tcg/i386/tcg-target-opc.h.inc @@ -24,14 +24,14 @@ * consider these to be UNSPEC with names. */ -DEF(x86_shufps_vec, 1, 2, 1, IMPLVEC) -DEF(x86_blend_vec, 1, 2, 1, IMPLVEC) -DEF(x86_packss_vec, 1, 2, 0, IMPLVEC) -DEF(x86_packus_vec, 1, 2, 0, IMPLVEC) -DEF(x86_psrldq_vec, 1, 1, 1, IMPLVEC) -DEF(x86_vperm2i128_vec, 1, 2, 1, IMPLVEC) -DEF(x86_punpckl_vec, 1, 2, 0, IMPLVEC) -DEF(x86_punpckh_vec, 1, 2, 0, IMPLVEC) -DEF(x86_vpshldi_vec, 1, 2, 1, IMPLVEC) -DEF(x86_vpshldv_vec, 1, 3, 0, IMPLVEC) -DEF(x86_vpshrdv_vec, 1, 3, 0, IMPLVEC) +DEF(x86_shufps_vec, 1, 2, 1, TCG_OPF_VECTOR) +DEF(x86_blend_vec, 1, 2, 1, TCG_OPF_VECTOR) +DEF(x86_packss_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(x86_packus_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(x86_psrldq_vec, 1, 1, 1, TCG_OPF_VECTOR) +DEF(x86_vperm2i128_vec, 1, 2, 1, TCG_OPF_VECTOR) +DEF(x86_punpckl_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(x86_punpckh_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(x86_vpshldi_vec, 1, 2, 1, TCG_OPF_VECTOR) +DEF(x86_vpshldv_vec, 1, 3, 0, TCG_OPF_VECTOR) +DEF(x86_vpshrdv_vec, 1, 3, 0, TCG_OPF_VECTOR) diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index 1bf50f1f62..2cac151331 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -22,8 +22,25 @@ * THE SOFTWARE. */ -#include "../tcg-ldst.c.inc" -#include "../tcg-pool.c.inc" +/* Used for function call generation. */ +#define TCG_TARGET_STACK_ALIGN 16 +#if defined(_WIN64) +#define TCG_TARGET_CALL_STACK_OFFSET 32 +#else +#define TCG_TARGET_CALL_STACK_OFFSET 0 +#endif +#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL +#if defined(_WIN64) +# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_BY_REF +# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_VEC +#elif TCG_TARGET_REG_BITS == 64 +# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL +# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL +#else +# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL +# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF +#endif #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -1312,16 +1329,31 @@ static inline void tcg_out_rolw_8(TCGContext *s, int reg) static void tcg_out_ext8u(TCGContext *s, TCGReg dest, TCGReg src) { - /* movzbl */ - tcg_debug_assert(src < 4 || TCG_TARGET_REG_BITS == 64); + if (TCG_TARGET_REG_BITS == 32 && src >= 4) { + tcg_out_mov(s, TCG_TYPE_I32, dest, src); + if (dest >= 4) { + tcg_out_modrm(s, OPC_ARITH_EvIz, ARITH_AND, dest); + tcg_out32(s, 0xff); + return; + } + src = dest; + } tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src); } static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src) { int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW; - /* movsbl */ - tcg_debug_assert(src < 4 || TCG_TARGET_REG_BITS == 64); + + if (TCG_TARGET_REG_BITS == 32 && src >= 4) { + tcg_out_mov(s, TCG_TYPE_I32, dest, src); + if (dest >= 4) { + tcg_out_shifti(s, SHIFT_SHL, dest, 24); + tcg_out_shifti(s, SHIFT_SAR, dest, 24); + return; + } + src = dest; + } tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src); } @@ -2595,17 +2627,16 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, /* no need to flush icache explicitly */ } -static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, - const TCGArg args[TCG_MAX_OP_ARGS], - const int const_args[TCG_MAX_OP_ARGS]) +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, + const TCGArg args[TCG_MAX_OP_ARGS], + const int const_args[TCG_MAX_OP_ARGS]) { TCGArg a0, a1, a2; - int c, const_a2, vexop, rexw = 0; + int c, const_a2, vexop, rexw; #if TCG_TARGET_REG_BITS == 64 # define OP_32_64(x) \ case glue(glue(INDEX_op_, x), _i64): \ - rexw = P_REXW; /* FALLTHRU */ \ case glue(glue(INDEX_op_, x), _i32) #else # define OP_32_64(x) \ @@ -2617,6 +2648,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, a1 = args[1]; a2 = args[2]; const_a2 = const_args[2]; + rexw = type == TCG_TYPE_I32 ? 0 : P_REXW; switch (opc) { case INDEX_op_goto_ptr: @@ -3003,6 +3035,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_extract_i64: if (a2 + args[3] == 32) { + if (a2 == 0) { + tcg_out_ext32u(s, a0, a1); + break; + } /* This is a 32-bit zero-extending right shift. */ tcg_out_mov(s, TCG_TYPE_I32, a0, a1); tcg_out_shifti(s, SHIFT_SHR, a0, a2); @@ -3010,28 +3046,53 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } /* FALLTHRU */ case INDEX_op_extract_i32: - /* On the off-chance that we can use the high-byte registers. - Otherwise we emit the same ext16 + shift pattern that we - would have gotten from the normal tcg-op.c expansion. */ - tcg_debug_assert(a2 == 8 && args[3] == 8); - if (a1 < 4 && a0 < 8) { - tcg_out_modrm(s, OPC_MOVZBL, a0, a1 + 4); - } else { + if (a2 == 0 && args[3] == 8) { + tcg_out_ext8u(s, a0, a1); + } else if (a2 == 0 && args[3] == 16) { tcg_out_ext16u(s, a0, a1); - tcg_out_shifti(s, SHIFT_SHR, a0, 8); + } else if (a2 == 8 && args[3] == 8) { + /* + * On the off-chance that we can use the high-byte registers. + * Otherwise we emit the same ext16 + shift pattern that we + * would have gotten from the normal tcg-op.c expansion. + */ + if (a1 < 4 && a0 < 8) { + tcg_out_modrm(s, OPC_MOVZBL, a0, a1 + 4); + } else { + tcg_out_ext16u(s, a0, a1); + tcg_out_shifti(s, SHIFT_SHR, a0, 8); + } + } else { + g_assert_not_reached(); } break; - case INDEX_op_sextract_i32: - /* We don't implement sextract_i64, as we cannot sign-extend to - 64-bits without using the REX prefix that explicitly excludes - access to the high-byte registers. */ - tcg_debug_assert(a2 == 8 && args[3] == 8); - if (a1 < 4 && a0 < 8) { - tcg_out_modrm(s, OPC_MOVSBL, a0, a1 + 4); + case INDEX_op_sextract_i64: + if (a2 == 0 && args[3] == 8) { + tcg_out_ext8s(s, TCG_TYPE_I64, a0, a1); + } else if (a2 == 0 && args[3] == 16) { + tcg_out_ext16s(s, TCG_TYPE_I64, a0, a1); + } else if (a2 == 0 && args[3] == 32) { + tcg_out_ext32s(s, a0, a1); } else { + g_assert_not_reached(); + } + break; + + case INDEX_op_sextract_i32: + if (a2 == 0 && args[3] == 8) { + tcg_out_ext8s(s, TCG_TYPE_I32, a0, a1); + } else if (a2 == 0 && args[3] == 16) { tcg_out_ext16s(s, TCG_TYPE_I32, a0, a1); - tcg_out_shifti(s, SHIFT_SAR, a0, 8); + } else if (a2 == 8 && args[3] == 8) { + if (a1 < 4 && a0 < 8) { + tcg_out_modrm(s, OPC_MOVSBL, a0, a1 + 4); + } else { + tcg_out_ext16s(s, TCG_TYPE_I32, a0, a1); + tcg_out_shifti(s, SHIFT_SAR, a0, 8); + } + } else { + g_assert_not_reached(); } break; @@ -3610,7 +3671,8 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, } } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -3713,6 +3775,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_extract_i32: case INDEX_op_extract_i64: case INDEX_op_sextract_i32: + case INDEX_op_sextract_i64: case INDEX_op_ctpop_i32: case INDEX_op_ctpop_i64: return C_O1_I1(r, r); @@ -3868,7 +3931,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) return C_O1_I4(x, x, x, xO, x); default: - g_assert_not_reached(); + return C_NotImplemented; } } diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index c68ac023d8..3cbdfbca52 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -25,8 +25,6 @@ #ifndef I386_TCG_TARGET_H #define I386_TCG_TARGET_H -#include "host/cpuinfo.h" - #define TCG_TARGET_INSN_UNIT_SIZE 1 #ifdef __x86_64__ @@ -90,164 +88,4 @@ typedef enum { TCG_REG_CALL_STACK = TCG_REG_ESP } TCGReg; -/* used for function call generation */ -#define TCG_TARGET_STACK_ALIGN 16 -#if defined(_WIN64) -#define TCG_TARGET_CALL_STACK_OFFSET 32 -#else -#define TCG_TARGET_CALL_STACK_OFFSET 0 -#endif -#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL -#if defined(_WIN64) -# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_BY_REF -# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_VEC -#elif TCG_TARGET_REG_BITS == 64 -# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL -# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL -#else -# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL -# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF -#endif - -#define have_bmi1 (cpuinfo & CPUINFO_BMI1) -#define have_popcnt (cpuinfo & CPUINFO_POPCNT) -#define have_avx1 (cpuinfo & CPUINFO_AVX1) -#define have_avx2 (cpuinfo & CPUINFO_AVX2) -#define have_movbe (cpuinfo & CPUINFO_MOVBE) - -/* - * There are interesting instructions in AVX512, so long as we have AVX512VL, - * which indicates support for EVEX on sizes smaller than 512 bits. - */ -#define have_avx512vl ((cpuinfo & CPUINFO_AVX512VL) && \ - (cpuinfo & CPUINFO_AVX512F)) -#define have_avx512bw ((cpuinfo & CPUINFO_AVX512BW) && have_avx512vl) -#define have_avx512dq ((cpuinfo & CPUINFO_AVX512DQ) && have_avx512vl) -#define have_avx512vbmi2 ((cpuinfo & CPUINFO_AVX512VBMI2) && have_avx512vl) - -/* optional instructions */ -#define TCG_TARGET_HAS_div2_i32 1 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_ext8u_i32 1 -#define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_andc_i32 have_bmi1 -#define TCG_TARGET_HAS_orc_i32 0 -#define TCG_TARGET_HAS_eqv_i32 0 -#define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_clz_i32 1 -#define TCG_TARGET_HAS_ctz_i32 1 -#define TCG_TARGET_HAS_ctpop_i32 have_popcnt -#define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 1 -#define TCG_TARGET_HAS_sextract_i32 1 -#define TCG_TARGET_HAS_extract2_i32 1 -#define TCG_TARGET_HAS_negsetcond_i32 1 -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#define TCG_TARGET_HAS_mulu2_i32 1 -#define TCG_TARGET_HAS_muls2_i32 1 -#define TCG_TARGET_HAS_muluh_i32 0 -#define TCG_TARGET_HAS_mulsh_i32 0 - -#if TCG_TARGET_REG_BITS == 64 -/* Keep 32-bit values zero-extended in a register. */ -#define TCG_TARGET_HAS_extr_i64_i32 1 -#define TCG_TARGET_HAS_div2_i64 1 -#define TCG_TARGET_HAS_rot_i64 1 -#define TCG_TARGET_HAS_ext8s_i64 1 -#define TCG_TARGET_HAS_ext16s_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i64 1 -#define TCG_TARGET_HAS_ext16u_i64 1 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 1 -#define TCG_TARGET_HAS_bswap32_i64 1 -#define TCG_TARGET_HAS_bswap64_i64 1 -#define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_andc_i64 have_bmi1 -#define TCG_TARGET_HAS_orc_i64 0 -#define TCG_TARGET_HAS_eqv_i64 0 -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 0 -#define TCG_TARGET_HAS_clz_i64 1 -#define TCG_TARGET_HAS_ctz_i64 1 -#define TCG_TARGET_HAS_ctpop_i64 have_popcnt -#define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 1 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 1 -#define TCG_TARGET_HAS_negsetcond_i64 1 -#define TCG_TARGET_HAS_add2_i64 1 -#define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i64 1 -#define TCG_TARGET_HAS_muls2_i64 1 -#define TCG_TARGET_HAS_muluh_i64 0 -#define TCG_TARGET_HAS_mulsh_i64 0 -#define TCG_TARGET_HAS_qemu_st8_i32 0 -#else -#define TCG_TARGET_HAS_qemu_st8_i32 1 -#endif - -#define TCG_TARGET_HAS_qemu_ldst_i128 \ - (TCG_TARGET_REG_BITS == 64 && (cpuinfo & CPUINFO_ATOMIC_VMOVDQA)) - -#define TCG_TARGET_HAS_tst 1 - -/* We do not support older SSE systems, only beginning with AVX1. */ -#define TCG_TARGET_HAS_v64 have_avx1 -#define TCG_TARGET_HAS_v128 have_avx1 -#define TCG_TARGET_HAS_v256 have_avx2 - -#define TCG_TARGET_HAS_andc_vec 1 -#define TCG_TARGET_HAS_orc_vec have_avx512vl -#define TCG_TARGET_HAS_nand_vec have_avx512vl -#define TCG_TARGET_HAS_nor_vec have_avx512vl -#define TCG_TARGET_HAS_eqv_vec have_avx512vl -#define TCG_TARGET_HAS_not_vec have_avx512vl -#define TCG_TARGET_HAS_neg_vec 0 -#define TCG_TARGET_HAS_abs_vec 1 -#define TCG_TARGET_HAS_roti_vec have_avx512vl -#define TCG_TARGET_HAS_rots_vec 0 -#define TCG_TARGET_HAS_rotv_vec have_avx512vl -#define TCG_TARGET_HAS_shi_vec 1 -#define TCG_TARGET_HAS_shs_vec 1 -#define TCG_TARGET_HAS_shv_vec have_avx2 -#define TCG_TARGET_HAS_mul_vec 1 -#define TCG_TARGET_HAS_sat_vec 1 -#define TCG_TARGET_HAS_minmax_vec 1 -#define TCG_TARGET_HAS_bitsel_vec have_avx512vl -#define TCG_TARGET_HAS_cmpsel_vec 1 -#define TCG_TARGET_HAS_tst_vec have_avx512bw - -#define TCG_TARGET_deposit_i32_valid(ofs, len) \ - (((ofs) == 0 && ((len) == 8 || (len) == 16)) || \ - (TCG_TARGET_REG_BITS == 32 && (ofs) == 8 && (len) == 8)) -#define TCG_TARGET_deposit_i64_valid TCG_TARGET_deposit_i32_valid - -/* Check for the possibility of high-byte extraction and, for 64-bit, - zero-extending 32-bit right-shift. */ -#define TCG_TARGET_extract_i32_valid(ofs, len) ((ofs) == 8 && (len) == 8) -#define TCG_TARGET_extract_i64_valid(ofs, len) \ - (((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32) - -/* This defines the natural memory order supported by this - * architecture before guarantees made by various barrier - * instructions. - * - * The x86 has a pretty strong memory ordering which only really - * allows for some stores to be re-ordered after loads. - */ -#include "tcg/tcg-mo.h" - -#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) -#define TCG_TARGET_NEED_LDST_LABELS -#define TCG_TARGET_NEED_POOL_LABELS - #endif diff --git a/tcg/loongarch64/tcg-target-has.h b/tcg/loongarch64/tcg-target-has.h new file mode 100644 index 0000000000..ac88522eef --- /dev/null +++ b/tcg/loongarch64/tcg-target-has.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2021 WANG Xuerui <git@xen0n.name> + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +#include "host/cpuinfo.h" + +/* optional instructions */ +#define TCG_TARGET_HAS_negsetcond_i32 0 +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 +#define TCG_TARGET_HAS_div2_i32 0 +#define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i32 0 +#define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 1 +#define TCG_TARGET_HAS_mulsh_i32 1 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_andc_i32 1 +#define TCG_TARGET_HAS_orc_i32 1 +#define TCG_TARGET_HAS_eqv_i32 0 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 1 +#define TCG_TARGET_HAS_clz_i32 1 +#define TCG_TARGET_HAS_ctz_i32 1 +#define TCG_TARGET_HAS_ctpop_i32 0 +#define TCG_TARGET_HAS_brcond2 0 +#define TCG_TARGET_HAS_setcond2 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +/* 64-bit operations */ +#define TCG_TARGET_HAS_negsetcond_i64 0 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_div2_i64 0 +#define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_extr_i64_i32 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 1 +#define TCG_TARGET_HAS_ext16u_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_andc_i64 1 +#define TCG_TARGET_HAS_orc_i64 1 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 1 +#define TCG_TARGET_HAS_clz_i64 1 +#define TCG_TARGET_HAS_ctz_i64 1 +#define TCG_TARGET_HAS_ctpop_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 + +#define TCG_TARGET_HAS_qemu_ldst_i128 (cpuinfo & CPUINFO_LSX) + +#define TCG_TARGET_HAS_tst 0 + +#define TCG_TARGET_HAS_v64 (cpuinfo & CPUINFO_LSX) +#define TCG_TARGET_HAS_v128 (cpuinfo & CPUINFO_LSX) +#define TCG_TARGET_HAS_v256 (cpuinfo & CPUINFO_LASX) + +#define TCG_TARGET_HAS_not_vec 1 +#define TCG_TARGET_HAS_neg_vec 1 +#define TCG_TARGET_HAS_abs_vec 0 +#define TCG_TARGET_HAS_andc_vec 1 +#define TCG_TARGET_HAS_orc_vec 1 +#define TCG_TARGET_HAS_nand_vec 0 +#define TCG_TARGET_HAS_nor_vec 1 +#define TCG_TARGET_HAS_eqv_vec 0 +#define TCG_TARGET_HAS_mul_vec 1 +#define TCG_TARGET_HAS_shi_vec 1 +#define TCG_TARGET_HAS_shs_vec 0 +#define TCG_TARGET_HAS_shv_vec 1 +#define TCG_TARGET_HAS_roti_vec 1 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 1 +#define TCG_TARGET_HAS_sat_vec 1 +#define TCG_TARGET_HAS_minmax_vec 1 +#define TCG_TARGET_HAS_bitsel_vec 1 +#define TCG_TARGET_HAS_cmpsel_vec 0 +#define TCG_TARGET_HAS_tst_vec 0 + +#define TCG_TARGET_extract_valid(type, ofs, len) 1 +#define TCG_TARGET_deposit_valid(type, ofs, len) 1 + +static inline bool +tcg_target_sextract_valid(TCGType type, unsigned ofs, unsigned len) +{ + if (type == TCG_TYPE_I64 && ofs + len == 32) { + return true; + } + return ofs == 0 && (len == 8 || len == 16); +} +#define TCG_TARGET_sextract_valid tcg_target_sextract_valid + +#endif diff --git a/tcg/loongarch64/tcg-target-mo.h b/tcg/loongarch64/tcg-target-mo.h new file mode 100644 index 0000000000..d35506957f --- /dev/null +++ b/tcg/loongarch64/tcg-target-mo.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2021 WANG Xuerui <git@xen0n.name> + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +#define TCG_TARGET_DEFAULT_MO 0 + +#endif diff --git a/tcg/loongarch64/tcg-target.opc.h b/tcg/loongarch64/tcg-target-opc.h.inc index fd1a40b7fd..fd1a40b7fd 100644 --- a/tcg/loongarch64/tcg-target.opc.h +++ b/tcg/loongarch64/tcg-target-opc.h.inc diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 973601aec3..cebe8dd354 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -29,9 +29,17 @@ * THE SOFTWARE. */ -#include "../tcg-ldst.c.inc" #include <asm/hwcap.h> +/* used for function call generation */ +#define TCG_REG_CALL_STACK TCG_REG_SP +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_STACK_OFFSET 0 +#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL + #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "zero", @@ -1270,7 +1278,7 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, flush_idcache_range(jmp_rx, jmp_rw, 4); } -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) { @@ -1367,10 +1375,38 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_extract_i32: - tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1); + if (a2 == 0 && args[3] <= 12) { + tcg_out_opc_andi(s, a0, a1, (1 << args[3]) - 1); + } else { + tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1); + } break; case INDEX_op_extract_i64: - tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1); + if (a2 == 0 && args[3] <= 12) { + tcg_out_opc_andi(s, a0, a1, (1 << args[3]) - 1); + } else { + tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1); + } + break; + + case INDEX_op_sextract_i64: + if (a2 + args[3] == 32) { + if (a2 == 0) { + tcg_out_ext32s(s, a0, a1); + } else { + tcg_out_opc_srai_w(s, a0, a1, a2); + } + break; + } + /* FALLTHRU */ + case INDEX_op_sextract_i32: + if (a2 == 0 && args[3] == 8) { + tcg_out_ext8s(s, TCG_TYPE_REG, a0, a1); + } else if (a2 == 0 && args[3] == 16) { + tcg_out_ext16s(s, TCG_TYPE_REG, a0, a1); + } else { + g_assert_not_reached(); + } break; case INDEX_op_deposit_i32: @@ -2183,7 +2219,8 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, g_assert_not_reached(); } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -2234,6 +2271,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_not_i64: case INDEX_op_extract_i32: case INDEX_op_extract_i64: + case INDEX_op_sextract_i32: + case INDEX_op_sextract_i64: case INDEX_op_bswap16_i32: case INDEX_op_bswap16_i64: case INDEX_op_bswap32_i32: @@ -2383,7 +2422,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) return C_O1_I3(w, w, w, w); default: - g_assert_not_reached(); + return C_NotImplemented; } } @@ -2456,6 +2495,14 @@ static void tcg_out_tb_start(TCGContext *s) /* nothing to do */ } +static void tcg_out_nop_fill(tcg_insn_unit *p, int count) +{ + for (int i = 0; i < count; ++i) { + /* Canonical nop is andi r0,r0,0 */ + p[i] = OPC_ANDI; + } +} + static void tcg_target_init(TCGContext *s) { unsigned long hwcap = qemu_getauxval(AT_HWCAP); diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h index 58bd7d258e..8533284631 100644 --- a/tcg/loongarch64/tcg-target.h +++ b/tcg/loongarch64/tcg-target.h @@ -29,8 +29,6 @@ #ifndef LOONGARCH_TCG_TARGET_H #define LOONGARCH_TCG_TARGET_H -#include "host/cpuinfo.h" - #define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_NB_REGS 64 @@ -87,117 +85,4 @@ typedef enum { TCG_VEC_TMP0 = TCG_REG_V23, } TCGReg; -/* used for function call generation */ -#define TCG_REG_CALL_STACK TCG_REG_SP -#define TCG_TARGET_STACK_ALIGN 16 -#define TCG_TARGET_CALL_STACK_OFFSET 0 -#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL - -/* optional instructions */ -#define TCG_TARGET_HAS_negsetcond_i32 0 -#define TCG_TARGET_HAS_div_i32 1 -#define TCG_TARGET_HAS_rem_i32 1 -#define TCG_TARGET_HAS_div2_i32 0 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 1 -#define TCG_TARGET_HAS_sextract_i32 0 -#define TCG_TARGET_HAS_extract2_i32 0 -#define TCG_TARGET_HAS_add2_i32 0 -#define TCG_TARGET_HAS_sub2_i32 0 -#define TCG_TARGET_HAS_mulu2_i32 0 -#define TCG_TARGET_HAS_muls2_i32 0 -#define TCG_TARGET_HAS_muluh_i32 1 -#define TCG_TARGET_HAS_mulsh_i32 1 -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_ext8u_i32 1 -#define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_andc_i32 1 -#define TCG_TARGET_HAS_orc_i32 1 -#define TCG_TARGET_HAS_eqv_i32 0 -#define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_nor_i32 1 -#define TCG_TARGET_HAS_clz_i32 1 -#define TCG_TARGET_HAS_ctz_i32 1 -#define TCG_TARGET_HAS_ctpop_i32 0 -#define TCG_TARGET_HAS_brcond2 0 -#define TCG_TARGET_HAS_setcond2 0 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -/* 64-bit operations */ -#define TCG_TARGET_HAS_negsetcond_i64 0 -#define TCG_TARGET_HAS_div_i64 1 -#define TCG_TARGET_HAS_rem_i64 1 -#define TCG_TARGET_HAS_div2_i64 0 -#define TCG_TARGET_HAS_rot_i64 1 -#define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 1 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_extr_i64_i32 1 -#define TCG_TARGET_HAS_ext8s_i64 1 -#define TCG_TARGET_HAS_ext16s_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i64 1 -#define TCG_TARGET_HAS_ext16u_i64 1 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 1 -#define TCG_TARGET_HAS_bswap32_i64 1 -#define TCG_TARGET_HAS_bswap64_i64 1 -#define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_andc_i64 1 -#define TCG_TARGET_HAS_orc_i64 1 -#define TCG_TARGET_HAS_eqv_i64 0 -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 1 -#define TCG_TARGET_HAS_clz_i64 1 -#define TCG_TARGET_HAS_ctz_i64 1 -#define TCG_TARGET_HAS_ctpop_i64 0 -#define TCG_TARGET_HAS_add2_i64 0 -#define TCG_TARGET_HAS_sub2_i64 0 -#define TCG_TARGET_HAS_mulu2_i64 0 -#define TCG_TARGET_HAS_muls2_i64 0 -#define TCG_TARGET_HAS_muluh_i64 1 -#define TCG_TARGET_HAS_mulsh_i64 1 - -#define TCG_TARGET_HAS_qemu_ldst_i128 (cpuinfo & CPUINFO_LSX) - -#define TCG_TARGET_HAS_tst 0 - -#define TCG_TARGET_HAS_v64 (cpuinfo & CPUINFO_LSX) -#define TCG_TARGET_HAS_v128 (cpuinfo & CPUINFO_LSX) -#define TCG_TARGET_HAS_v256 (cpuinfo & CPUINFO_LASX) - -#define TCG_TARGET_HAS_not_vec 1 -#define TCG_TARGET_HAS_neg_vec 1 -#define TCG_TARGET_HAS_abs_vec 0 -#define TCG_TARGET_HAS_andc_vec 1 -#define TCG_TARGET_HAS_orc_vec 1 -#define TCG_TARGET_HAS_nand_vec 0 -#define TCG_TARGET_HAS_nor_vec 1 -#define TCG_TARGET_HAS_eqv_vec 0 -#define TCG_TARGET_HAS_mul_vec 1 -#define TCG_TARGET_HAS_shi_vec 1 -#define TCG_TARGET_HAS_shs_vec 0 -#define TCG_TARGET_HAS_shv_vec 1 -#define TCG_TARGET_HAS_roti_vec 1 -#define TCG_TARGET_HAS_rots_vec 0 -#define TCG_TARGET_HAS_rotv_vec 1 -#define TCG_TARGET_HAS_sat_vec 1 -#define TCG_TARGET_HAS_minmax_vec 1 -#define TCG_TARGET_HAS_bitsel_vec 1 -#define TCG_TARGET_HAS_cmpsel_vec 0 -#define TCG_TARGET_HAS_tst_vec 0 - -#define TCG_TARGET_DEFAULT_MO (0) - -#define TCG_TARGET_NEED_LDST_LABELS - #endif /* LOONGARCH_TCG_TARGET_H */ diff --git a/tcg/mips/tcg-target-has.h b/tcg/mips/tcg-target-has.h new file mode 100644 index 0000000000..df6960fe9a --- /dev/null +++ b/tcg/mips/tcg-target-has.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org> + * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net> + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +/* MOVN/MOVZ instructions detection */ +#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \ + defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \ + defined(_MIPS_ARCH_MIPS4) +#define use_movnz_instructions 1 +#else +extern bool use_movnz_instructions; +#endif + +/* MIPS32 instruction set detection */ +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 1) +#define use_mips32_instructions 1 +#else +extern bool use_mips32_instructions; +#endif + +/* MIPS32R2 instruction set detection */ +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) +#define use_mips32r2_instructions 1 +#else +extern bool use_mips32r2_instructions; +#endif + +/* MIPS32R6 instruction set detection */ +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 6) +#define use_mips32r6_instructions 1 +#else +#define use_mips32r6_instructions 0 +#endif + +/* optional instructions */ +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_nor_i32 1 +#define TCG_TARGET_HAS_andc_i32 0 +#define TCG_TARGET_HAS_orc_i32 0 +#define TCG_TARGET_HAS_eqv_i32 0 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_mulu2_i32 (!use_mips32r6_instructions) +#define TCG_TARGET_HAS_muls2_i32 (!use_mips32r6_instructions) +#define TCG_TARGET_HAS_muluh_i32 1 +#define TCG_TARGET_HAS_mulsh_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_negsetcond_i32 0 + +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_extr_i64_i32 1 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_nor_i64 1 +#define TCG_TARGET_HAS_andc_i64 0 +#define TCG_TARGET_HAS_orc_i64 0 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64 (!use_mips32r6_instructions) +#define TCG_TARGET_HAS_muls2_i64 (!use_mips32r6_instructions) +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_negsetcond_i64 0 +#endif + +/* optional instructions detected at runtime */ +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_ext8s_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_clz_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_ctz_i32 0 +#define TCG_TARGET_HAS_ctpop_i32 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_ext8s_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_ext16s_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_rot_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_clz_i64 use_mips32r2_instructions +#define TCG_TARGET_HAS_ctz_i64 0 +#define TCG_TARGET_HAS_ctpop_i64 0 +#endif + +/* optional instructions automatically implemented */ +#define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */ +#define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */ + +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_ext8u_i64 0 /* andi rt, rs, 0xff */ +#define TCG_TARGET_HAS_ext16u_i64 0 /* andi rt, rs, 0xffff */ +#endif + +#define TCG_TARGET_HAS_qemu_ldst_i128 0 +#define TCG_TARGET_HAS_tst 0 + +#define TCG_TARGET_extract_valid(type, ofs, len) use_mips32r2_instructions +#define TCG_TARGET_deposit_valid(type, ofs, len) use_mips32r2_instructions + +static inline bool +tcg_target_sextract_valid(TCGType type, unsigned ofs, unsigned len) +{ + if (ofs == 0) { + switch (len) { + case 8: + case 16: + return use_mips32r2_instructions; + case 32: + return type == TCG_TYPE_I64; + } + } + return false; +} +#define TCG_TARGET_sextract_valid tcg_target_sextract_valid + +#endif diff --git a/tcg/mips/tcg-target-mo.h b/tcg/mips/tcg-target-mo.h new file mode 100644 index 0000000000..50cefc222d --- /dev/null +++ b/tcg/mips/tcg-target-mo.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org> + * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net> + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +#define TCG_TARGET_DEFAULT_MO 0 + +#endif diff --git a/tcg/mips/tcg-target-opc.h.inc b/tcg/mips/tcg-target-opc.h.inc new file mode 100644 index 0000000000..84e777bfe5 --- /dev/null +++ b/tcg/mips/tcg-target-opc.h.inc @@ -0,0 +1 @@ +/* No target specific opcodes. */ diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc index 3b5b5c6d5b..99f6ef6c76 100644 --- a/tcg/mips/tcg-target.c.inc +++ b/tcg/mips/tcg-target.c.inc @@ -24,8 +24,19 @@ * THE SOFTWARE. */ -#include "../tcg-ldst.c.inc" -#include "../tcg-pool.c.inc" +/* used for function call generation */ +#define TCG_TARGET_STACK_ALIGN 16 +#if _MIPS_SIM == _ABIO32 +# define TCG_TARGET_CALL_STACK_OFFSET 16 +# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN +# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF +#else +# define TCG_TARGET_CALL_STACK_OFFSET 0 +# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL +# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL +#endif +#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN #if TCG_TARGET_REG_BITS == 32 # define LO_OFF (HOST_BIG_ENDIAN * 4) @@ -1667,7 +1678,7 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, /* Always indirect, nothing to do */ } -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) { @@ -2030,12 +2041,37 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2, args[3] + args[4] - 1, args[3]); break; + case INDEX_op_extract_i32: - tcg_out_opc_bf(s, OPC_EXT, a0, a1, args[3] - 1, a2); + if (a2 == 0 && args[3] <= 16) { + tcg_out_opc_imm(s, OPC_ANDI, a0, a1, (1 << args[3]) - 1); + } else { + tcg_out_opc_bf(s, OPC_EXT, a0, a1, args[3] - 1, a2); + } break; case INDEX_op_extract_i64: - tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1, - args[3] - 1, a2); + if (a2 == 0 && args[3] <= 16) { + tcg_out_opc_imm(s, OPC_ANDI, a0, a1, (1 << args[3]) - 1); + } else { + tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, + a0, a1, args[3] - 1, a2); + } + break; + + case INDEX_op_sextract_i64: + if (a2 == 0 && args[3] == 32) { + tcg_out_ext32s(s, a0, a1); + break; + } + /* FALLTHRU */ + case INDEX_op_sextract_i32: + if (a2 == 0 && args[3] == 8) { + tcg_out_ext8s(s, TCG_TYPE_REG, a0, a1); + } else if (a2 == 0 && args[3] == 16) { + tcg_out_ext16s(s, TCG_TYPE_REG, a0, a1); + } else { + g_assert_not_reached(); + } break; case INDEX_op_brcond_i32: @@ -2140,7 +2176,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, } } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -2158,6 +2195,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_ext8s_i32: case INDEX_op_ext16s_i32: case INDEX_op_extract_i32: + case INDEX_op_sextract_i32: case INDEX_op_ld8u_i64: case INDEX_op_ld8s_i64: case INDEX_op_ld16u_i64: @@ -2179,6 +2217,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_extrl_i64_i32: case INDEX_op_extrh_i64_i32: case INDEX_op_extract_i64: + case INDEX_op_sextract_i64: return C_O1_I1(r, r); case INDEX_op_st8_i32: @@ -2281,7 +2320,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) : C_O0_I4(rZ, rZ, r, r)); default: - g_assert_not_reached(); + return C_NotImplemented; } } diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index a996aa171d..3090acc4f5 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -70,134 +70,4 @@ typedef enum { TCG_AREG0 = TCG_REG_S8, } TCGReg; -/* used for function call generation */ -#define TCG_TARGET_STACK_ALIGN 16 -#if _MIPS_SIM == _ABIO32 -# define TCG_TARGET_CALL_STACK_OFFSET 16 -# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN -# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF -#else -# define TCG_TARGET_CALL_STACK_OFFSET 0 -# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL -# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL -#endif -#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN - -/* MOVN/MOVZ instructions detection */ -#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \ - defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \ - defined(_MIPS_ARCH_MIPS4) -#define use_movnz_instructions 1 -#else -extern bool use_movnz_instructions; -#endif - -/* MIPS32 instruction set detection */ -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 1) -#define use_mips32_instructions 1 -#else -extern bool use_mips32_instructions; -#endif - -/* MIPS32R2 instruction set detection */ -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) -#define use_mips32r2_instructions 1 -#else -extern bool use_mips32r2_instructions; -#endif - -/* MIPS32R6 instruction set detection */ -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 6) -#define use_mips32r6_instructions 1 -#else -#define use_mips32r6_instructions 0 -#endif - -/* optional instructions */ -#define TCG_TARGET_HAS_div_i32 1 -#define TCG_TARGET_HAS_rem_i32 1 -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_nor_i32 1 -#define TCG_TARGET_HAS_andc_i32 0 -#define TCG_TARGET_HAS_orc_i32 0 -#define TCG_TARGET_HAS_eqv_i32 0 -#define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_mulu2_i32 (!use_mips32r6_instructions) -#define TCG_TARGET_HAS_muls2_i32 (!use_mips32r6_instructions) -#define TCG_TARGET_HAS_muluh_i32 1 -#define TCG_TARGET_HAS_mulsh_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_negsetcond_i32 0 - -#if TCG_TARGET_REG_BITS == 64 -#define TCG_TARGET_HAS_add2_i32 0 -#define TCG_TARGET_HAS_sub2_i32 0 -#define TCG_TARGET_HAS_extr_i64_i32 1 -#define TCG_TARGET_HAS_div_i64 1 -#define TCG_TARGET_HAS_rem_i64 1 -#define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_nor_i64 1 -#define TCG_TARGET_HAS_andc_i64 0 -#define TCG_TARGET_HAS_orc_i64 0 -#define TCG_TARGET_HAS_eqv_i64 0 -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_add2_i64 0 -#define TCG_TARGET_HAS_sub2_i64 0 -#define TCG_TARGET_HAS_mulu2_i64 (!use_mips32r6_instructions) -#define TCG_TARGET_HAS_muls2_i64 (!use_mips32r6_instructions) -#define TCG_TARGET_HAS_muluh_i64 1 -#define TCG_TARGET_HAS_mulsh_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_negsetcond_i64 0 -#endif - -/* optional instructions detected at runtime */ -#define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_deposit_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_extract_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_sextract_i32 0 -#define TCG_TARGET_HAS_extract2_i32 0 -#define TCG_TARGET_HAS_ext8s_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_clz_i32 use_mips32r2_instructions -#define TCG_TARGET_HAS_ctz_i32 0 -#define TCG_TARGET_HAS_ctpop_i32 0 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -#if TCG_TARGET_REG_BITS == 64 -#define TCG_TARGET_HAS_bswap16_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_bswap32_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_bswap64_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_deposit_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_extract_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_ext8s_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_ext16s_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_rot_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_clz_i64 use_mips32r2_instructions -#define TCG_TARGET_HAS_ctz_i64 0 -#define TCG_TARGET_HAS_ctpop_i64 0 -#endif - -/* optional instructions automatically implemented */ -#define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */ -#define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */ - -#if TCG_TARGET_REG_BITS == 64 -#define TCG_TARGET_HAS_ext8u_i64 0 /* andi rt, rs, 0xff */ -#define TCG_TARGET_HAS_ext16u_i64 0 /* andi rt, rs, 0xffff */ -#endif - -#define TCG_TARGET_HAS_qemu_ldst_i128 0 - -#define TCG_TARGET_HAS_tst 0 - -#define TCG_TARGET_DEFAULT_MO 0 -#define TCG_TARGET_NEED_LDST_LABELS -#define TCG_TARGET_NEED_POOL_LABELS - #endif diff --git a/tcg/optimize.c b/tcg/optimize.c index c23f0d1392..8c6303e3af 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -28,6 +28,7 @@ #include "qemu/interval-tree.h" #include "tcg/tcg-op-common.h" #include "tcg-internal.h" +#include "tcg-has.h" #define CASE_OP_32_64(x) \ glue(glue(case INDEX_op_, x), _i32): \ @@ -370,7 +371,7 @@ static bool tcg_opt_gen_mov(OptContext *ctx, TCGOp *op, TCGArg dst, TCGArg src) case TCG_TYPE_V64: case TCG_TYPE_V128: case TCG_TYPE_V256: - /* TCGOP_VECL and TCGOP_VECE remain unchanged. */ + /* TCGOP_TYPE and TCGOP_VECE remain unchanged. */ new_op = INDEX_op_mov_vec; break; default: @@ -2361,9 +2362,11 @@ static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg) xor_opc = INDEX_op_xor_i32; shr_opc = INDEX_op_shr_i32; neg_opc = INDEX_op_neg_i32; - if (TCG_TARGET_extract_i32_valid(sh, 1)) { - uext_opc = TCG_TARGET_HAS_extract_i32 ? INDEX_op_extract_i32 : 0; - sext_opc = TCG_TARGET_HAS_sextract_i32 ? INDEX_op_sextract_i32 : 0; + if (TCG_TARGET_extract_valid(TCG_TYPE_I32, sh, 1)) { + uext_opc = INDEX_op_extract_i32; + } + if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, sh, 1)) { + sext_opc = INDEX_op_sextract_i32; } break; case TCG_TYPE_I64: @@ -2372,9 +2375,11 @@ static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg) xor_opc = INDEX_op_xor_i64; shr_opc = INDEX_op_shr_i64; neg_opc = INDEX_op_neg_i64; - if (TCG_TARGET_extract_i64_valid(sh, 1)) { - uext_opc = TCG_TARGET_HAS_extract_i64 ? INDEX_op_extract_i64 : 0; - sext_opc = TCG_TARGET_HAS_sextract_i64 ? INDEX_op_sextract_i64 : 0; + if (TCG_TARGET_extract_valid(TCG_TYPE_I64, sh, 1)) { + uext_opc = INDEX_op_extract_i64; + } + if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, sh, 1)) { + sext_opc = INDEX_op_sextract_i64; } break; default: @@ -2866,13 +2871,7 @@ void tcg_optimize(TCGContext *s) copy_propagate(&ctx, op, def->nb_oargs, def->nb_iargs); /* Pre-compute the type of the operation. */ - if (def->flags & TCG_OPF_VECTOR) { - ctx.type = TCG_TYPE_V64 + TCGOP_VECL(op); - } else if (def->flags & TCG_OPF_64BIT) { - ctx.type = TCG_TYPE_I64; - } else { - ctx.type = TCG_TYPE_I32; - } + ctx.type = TCGOP_TYPE(op); /* * Process each opcode. diff --git a/tcg/ppc/tcg-target-has.h b/tcg/ppc/tcg-target-has.h new file mode 100644 index 0000000000..6db91f78ce --- /dev/null +++ b/tcg/ppc/tcg-target-has.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2008 Fabrice Bellard + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +#include "host/cpuinfo.h" + +#define have_isa_2_06 (cpuinfo & CPUINFO_V2_06) +#define have_isa_2_07 (cpuinfo & CPUINFO_V2_07) +#define have_isa_3_00 (cpuinfo & CPUINFO_V3_0) +#define have_isa_3_10 (cpuinfo & CPUINFO_V3_1) +#define have_altivec (cpuinfo & CPUINFO_ALTIVEC) +#define have_vsx (cpuinfo & CPUINFO_VSX) + +/* optional instructions automatically implemented */ +#define TCG_TARGET_HAS_ext8u_i32 0 /* andi */ +#define TCG_TARGET_HAS_ext16u_i32 0 + +/* optional instructions */ +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 have_isa_3_00 +#define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_andc_i32 1 +#define TCG_TARGET_HAS_orc_i32 1 +#define TCG_TARGET_HAS_eqv_i32 1 +#define TCG_TARGET_HAS_nand_i32 1 +#define TCG_TARGET_HAS_nor_i32 1 +#define TCG_TARGET_HAS_clz_i32 1 +#define TCG_TARGET_HAS_ctz_i32 have_isa_3_00 +#define TCG_TARGET_HAS_ctpop_i32 have_isa_2_06 +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_negsetcond_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 0 +#define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 1 +#define TCG_TARGET_HAS_mulsh_i32 1 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_extr_i64_i32 0 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 have_isa_3_00 +#define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 0 +#define TCG_TARGET_HAS_ext16u_i64 0 +#define TCG_TARGET_HAS_ext32u_i64 0 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_andc_i64 1 +#define TCG_TARGET_HAS_orc_i64 1 +#define TCG_TARGET_HAS_eqv_i64 1 +#define TCG_TARGET_HAS_nand_i64 1 +#define TCG_TARGET_HAS_nor_i64 1 +#define TCG_TARGET_HAS_clz_i64 1 +#define TCG_TARGET_HAS_ctz_i64 have_isa_3_00 +#define TCG_TARGET_HAS_ctpop_i64 have_isa_2_06 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_negsetcond_i64 1 +#define TCG_TARGET_HAS_add2_i64 1 +#define TCG_TARGET_HAS_sub2_i64 1 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 +#endif + +#define TCG_TARGET_HAS_qemu_ldst_i128 \ + (TCG_TARGET_REG_BITS == 64 && have_isa_2_07) + +#define TCG_TARGET_HAS_tst 1 + +/* + * While technically Altivec could support V64, it has no 64-bit store + * instruction and substituting two 32-bit stores makes the generated + * code quite large. + */ +#define TCG_TARGET_HAS_v64 have_vsx +#define TCG_TARGET_HAS_v128 have_altivec +#define TCG_TARGET_HAS_v256 0 + +#define TCG_TARGET_HAS_andc_vec 1 +#define TCG_TARGET_HAS_orc_vec have_isa_2_07 +#define TCG_TARGET_HAS_nand_vec have_isa_2_07 +#define TCG_TARGET_HAS_nor_vec 1 +#define TCG_TARGET_HAS_eqv_vec have_isa_2_07 +#define TCG_TARGET_HAS_not_vec 1 +#define TCG_TARGET_HAS_neg_vec have_isa_3_00 +#define TCG_TARGET_HAS_abs_vec 0 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 1 +#define TCG_TARGET_HAS_shi_vec 0 +#define TCG_TARGET_HAS_shs_vec 0 +#define TCG_TARGET_HAS_shv_vec 1 +#define TCG_TARGET_HAS_mul_vec 1 +#define TCG_TARGET_HAS_sat_vec 1 +#define TCG_TARGET_HAS_minmax_vec 1 +#define TCG_TARGET_HAS_bitsel_vec have_vsx +#define TCG_TARGET_HAS_cmpsel_vec 1 +#define TCG_TARGET_HAS_tst_vec 0 + +#define TCG_TARGET_extract_valid(type, ofs, len) 1 +#define TCG_TARGET_deposit_valid(type, ofs, len) 1 + +static inline bool +tcg_target_sextract_valid(TCGType type, unsigned ofs, unsigned len) +{ + if (type == TCG_TYPE_I64 && ofs + len == 32) { + return true; + } + return ofs == 0 && (len == 8 || len == 16); +} +#define TCG_TARGET_sextract_valid tcg_target_sextract_valid + +#endif diff --git a/tcg/ppc/tcg-target-mo.h b/tcg/ppc/tcg-target-mo.h new file mode 100644 index 0000000000..98bfe03b7a --- /dev/null +++ b/tcg/ppc/tcg-target-mo.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2008 Fabrice Bellard + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +#define TCG_TARGET_DEFAULT_MO 0 + +#endif diff --git a/tcg/ppc/tcg-target.opc.h b/tcg/ppc/tcg-target-opc.h.inc index db514403c3..c3635831b5 100644 --- a/tcg/ppc/tcg-target.opc.h +++ b/tcg/ppc/tcg-target-opc.h.inc @@ -24,9 +24,9 @@ * consider these to be UNSPEC with names. */ -DEF(ppc_mrgh_vec, 1, 2, 0, IMPLVEC) -DEF(ppc_mrgl_vec, 1, 2, 0, IMPLVEC) -DEF(ppc_msum_vec, 1, 3, 0, IMPLVEC) -DEF(ppc_muleu_vec, 1, 2, 0, IMPLVEC) -DEF(ppc_mulou_vec, 1, 2, 0, IMPLVEC) -DEF(ppc_pkum_vec, 1, 2, 0, IMPLVEC) +DEF(ppc_mrgh_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(ppc_mrgl_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(ppc_msum_vec, 1, 3, 0, TCG_OPF_VECTOR) +DEF(ppc_muleu_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(ppc_mulou_vec, 1, 2, 0, TCG_OPF_VECTOR) +DEF(ppc_pkum_vec, 1, 2, 0, TCG_OPF_VECTOR) diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc index 9a11c26fd3..6e711cd53f 100644 --- a/tcg/ppc/tcg-target.c.inc +++ b/tcg/ppc/tcg-target.c.inc @@ -23,8 +23,6 @@ */ #include "elf.h" -#include "../tcg-pool.c.inc" -#include "../tcg-ldst.c.inc" /* * Standardize on the _CALL_FOO symbols used by GCC: @@ -2942,7 +2940,7 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, flush_idcache_range(jmp_rx, jmp_rw, 4); } -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) { @@ -3432,13 +3430,41 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_extract_i32: + if (args[2] == 0 && args[3] <= 16) { + tcg_out32(s, ANDI | SAI(args[1], args[0], (1 << args[3]) - 1)); + break; + } tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], 32 - args[3], 31); break; case INDEX_op_extract_i64: + if (args[2] == 0 && args[3] <= 16) { + tcg_out32(s, ANDI | SAI(args[1], args[0], (1 << args[3]) - 1)); + break; + } tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 64 - args[3]); break; + case INDEX_op_sextract_i64: + if (args[2] + args[3] == 32) { + if (args[2] == 0) { + tcg_out_ext32s(s, args[0], args[1]); + } else { + tcg_out_sari32(s, args[0], args[1], args[2]); + } + break; + } + /* FALLTHRU */ + case INDEX_op_sextract_i32: + if (args[2] == 0 && args[3] == 8) { + tcg_out_ext8s(s, TCG_TYPE_I32, args[0], args[1]); + } else if (args[2] == 0 && args[3] == 16) { + tcg_out_ext16s(s, TCG_TYPE_I32, args[0], args[1]); + } else { + g_assert_not_reached(); + } + break; + case INDEX_op_movcond_i32: tcg_out_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1], args[2], args[3], args[4], const_args[2]); @@ -4142,7 +4168,8 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, va_end(va); } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -4161,6 +4188,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_bswap16_i32: case INDEX_op_bswap32_i32: case INDEX_op_extract_i32: + case INDEX_op_sextract_i32: case INDEX_op_ld8u_i64: case INDEX_op_ld8s_i64: case INDEX_op_ld16u_i64: @@ -4180,6 +4208,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_bswap32_i64: case INDEX_op_bswap64_i64: case INDEX_op_extract_i64: + case INDEX_op_sextract_i64: return C_O1_I1(r, r); case INDEX_op_st8_i32: @@ -4356,7 +4385,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) return C_O1_I4(v, v, v, vZM, v); default: - g_assert_not_reached(); + return C_NotImplemented; } } diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 0b2171d38c..5607634e99 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -25,8 +25,6 @@ #ifndef PPC_TCG_TARGET_H #define PPC_TCG_TARGET_H -#include "host/cpuinfo.h" - #define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) #define TCG_TARGET_NB_REGS 64 @@ -55,128 +53,4 @@ typedef enum { TCG_AREG0 = TCG_REG_R27 } TCGReg; -typedef enum { - tcg_isa_base, - tcg_isa_2_06, - tcg_isa_2_07, - tcg_isa_3_00, - tcg_isa_3_10, -} TCGPowerISA; - -#define have_isa_2_06 (cpuinfo & CPUINFO_V2_06) -#define have_isa_2_07 (cpuinfo & CPUINFO_V2_07) -#define have_isa_3_00 (cpuinfo & CPUINFO_V3_0) -#define have_isa_3_10 (cpuinfo & CPUINFO_V3_1) -#define have_altivec (cpuinfo & CPUINFO_ALTIVEC) -#define have_vsx (cpuinfo & CPUINFO_VSX) - -/* optional instructions automatically implemented */ -#define TCG_TARGET_HAS_ext8u_i32 0 /* andi */ -#define TCG_TARGET_HAS_ext16u_i32 0 - -/* optional instructions */ -#define TCG_TARGET_HAS_div_i32 1 -#define TCG_TARGET_HAS_rem_i32 have_isa_3_00 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_andc_i32 1 -#define TCG_TARGET_HAS_orc_i32 1 -#define TCG_TARGET_HAS_eqv_i32 1 -#define TCG_TARGET_HAS_nand_i32 1 -#define TCG_TARGET_HAS_nor_i32 1 -#define TCG_TARGET_HAS_clz_i32 1 -#define TCG_TARGET_HAS_ctz_i32 have_isa_3_00 -#define TCG_TARGET_HAS_ctpop_i32 have_isa_2_06 -#define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 1 -#define TCG_TARGET_HAS_sextract_i32 0 -#define TCG_TARGET_HAS_extract2_i32 0 -#define TCG_TARGET_HAS_negsetcond_i32 1 -#define TCG_TARGET_HAS_mulu2_i32 0 -#define TCG_TARGET_HAS_muls2_i32 0 -#define TCG_TARGET_HAS_muluh_i32 1 -#define TCG_TARGET_HAS_mulsh_i32 1 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -#if TCG_TARGET_REG_BITS == 64 -#define TCG_TARGET_HAS_add2_i32 0 -#define TCG_TARGET_HAS_sub2_i32 0 -#define TCG_TARGET_HAS_extr_i64_i32 0 -#define TCG_TARGET_HAS_div_i64 1 -#define TCG_TARGET_HAS_rem_i64 have_isa_3_00 -#define TCG_TARGET_HAS_rot_i64 1 -#define TCG_TARGET_HAS_ext8s_i64 1 -#define TCG_TARGET_HAS_ext16s_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i64 0 -#define TCG_TARGET_HAS_ext16u_i64 0 -#define TCG_TARGET_HAS_ext32u_i64 0 -#define TCG_TARGET_HAS_bswap16_i64 1 -#define TCG_TARGET_HAS_bswap32_i64 1 -#define TCG_TARGET_HAS_bswap64_i64 1 -#define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_andc_i64 1 -#define TCG_TARGET_HAS_orc_i64 1 -#define TCG_TARGET_HAS_eqv_i64 1 -#define TCG_TARGET_HAS_nand_i64 1 -#define TCG_TARGET_HAS_nor_i64 1 -#define TCG_TARGET_HAS_clz_i64 1 -#define TCG_TARGET_HAS_ctz_i64 have_isa_3_00 -#define TCG_TARGET_HAS_ctpop_i64 have_isa_2_06 -#define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 1 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_negsetcond_i64 1 -#define TCG_TARGET_HAS_add2_i64 1 -#define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i64 0 -#define TCG_TARGET_HAS_muls2_i64 0 -#define TCG_TARGET_HAS_muluh_i64 1 -#define TCG_TARGET_HAS_mulsh_i64 1 -#endif - -#define TCG_TARGET_HAS_qemu_ldst_i128 \ - (TCG_TARGET_REG_BITS == 64 && have_isa_2_07) - -#define TCG_TARGET_HAS_tst 1 - -/* - * While technically Altivec could support V64, it has no 64-bit store - * instruction and substituting two 32-bit stores makes the generated - * code quite large. - */ -#define TCG_TARGET_HAS_v64 have_vsx -#define TCG_TARGET_HAS_v128 have_altivec -#define TCG_TARGET_HAS_v256 0 - -#define TCG_TARGET_HAS_andc_vec 1 -#define TCG_TARGET_HAS_orc_vec have_isa_2_07 -#define TCG_TARGET_HAS_nand_vec have_isa_2_07 -#define TCG_TARGET_HAS_nor_vec 1 -#define TCG_TARGET_HAS_eqv_vec have_isa_2_07 -#define TCG_TARGET_HAS_not_vec 1 -#define TCG_TARGET_HAS_neg_vec have_isa_3_00 -#define TCG_TARGET_HAS_abs_vec 0 -#define TCG_TARGET_HAS_roti_vec 0 -#define TCG_TARGET_HAS_rots_vec 0 -#define TCG_TARGET_HAS_rotv_vec 1 -#define TCG_TARGET_HAS_shi_vec 0 -#define TCG_TARGET_HAS_shs_vec 0 -#define TCG_TARGET_HAS_shv_vec 1 -#define TCG_TARGET_HAS_mul_vec 1 -#define TCG_TARGET_HAS_sat_vec 1 -#define TCG_TARGET_HAS_minmax_vec 1 -#define TCG_TARGET_HAS_bitsel_vec have_vsx -#define TCG_TARGET_HAS_cmpsel_vec 1 -#define TCG_TARGET_HAS_tst_vec 0 - -#define TCG_TARGET_DEFAULT_MO (0) -#define TCG_TARGET_NEED_LDST_LABELS -#define TCG_TARGET_NEED_POOL_LABELS - #endif diff --git a/tcg/riscv/tcg-target-has.h b/tcg/riscv/tcg-target-has.h new file mode 100644 index 0000000000..f35f9b31f5 --- /dev/null +++ b/tcg/riscv/tcg-target-has.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2018 SiFive, Inc + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +#include "host/cpuinfo.h" + +/* optional instructions */ +#define TCG_TARGET_HAS_negsetcond_i32 1 +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 +#define TCG_TARGET_HAS_div2_i32 0 +#define TCG_TARGET_HAS_rot_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 0 +#define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_bswap32_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_andc_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_orc_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_eqv_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_ctz_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_ctpop_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_brcond2 1 +#define TCG_TARGET_HAS_setcond2 1 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +#define TCG_TARGET_HAS_negsetcond_i64 1 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_div2_i64 0 +#define TCG_TARGET_HAS_rot_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_extr_i64_i32 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 1 +#define TCG_TARGET_HAS_ext16u_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_bswap16_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_bswap32_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_bswap64_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_andc_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_orc_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_eqv_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_ctz_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_ctpop_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_add2_i64 1 +#define TCG_TARGET_HAS_sub2_i64 1 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 + +#define TCG_TARGET_HAS_qemu_ldst_i128 0 + +#define TCG_TARGET_HAS_tst 0 + +/* vector instructions */ +#define TCG_TARGET_HAS_v64 (cpuinfo & CPUINFO_ZVE64X) +#define TCG_TARGET_HAS_v128 (cpuinfo & CPUINFO_ZVE64X) +#define TCG_TARGET_HAS_v256 (cpuinfo & CPUINFO_ZVE64X) +#define TCG_TARGET_HAS_andc_vec 0 +#define TCG_TARGET_HAS_orc_vec 0 +#define TCG_TARGET_HAS_nand_vec 0 +#define TCG_TARGET_HAS_nor_vec 0 +#define TCG_TARGET_HAS_eqv_vec 0 +#define TCG_TARGET_HAS_not_vec 1 +#define TCG_TARGET_HAS_neg_vec 1 +#define TCG_TARGET_HAS_abs_vec 0 +#define TCG_TARGET_HAS_roti_vec 1 +#define TCG_TARGET_HAS_rots_vec 1 +#define TCG_TARGET_HAS_rotv_vec 1 +#define TCG_TARGET_HAS_shi_vec 1 +#define TCG_TARGET_HAS_shs_vec 1 +#define TCG_TARGET_HAS_shv_vec 1 +#define TCG_TARGET_HAS_mul_vec 1 +#define TCG_TARGET_HAS_sat_vec 1 +#define TCG_TARGET_HAS_minmax_vec 1 +#define TCG_TARGET_HAS_bitsel_vec 0 +#define TCG_TARGET_HAS_cmpsel_vec 1 + +#define TCG_TARGET_HAS_tst_vec 0 + +static inline bool +tcg_target_extract_valid(TCGType type, unsigned ofs, unsigned len) +{ + if (type == TCG_TYPE_I64 && ofs + len == 32) { + /* ofs > 0 uses SRLIW; ofs == 0 uses add.uw. */ + return ofs || (cpuinfo & CPUINFO_ZBA); + } + switch (len) { + case 1: + return (cpuinfo & CPUINFO_ZBS) && ofs != 0; + case 16: + return (cpuinfo & CPUINFO_ZBB) && ofs == 0; + } + return false; +} +#define TCG_TARGET_extract_valid tcg_target_extract_valid + +static inline bool +tcg_target_sextract_valid(TCGType type, unsigned ofs, unsigned len) +{ + if (type == TCG_TYPE_I64 && ofs + len == 32) { + return true; + } + return (cpuinfo & CPUINFO_ZBB) && ofs == 0 && (len == 8 || len == 16); +} +#define TCG_TARGET_sextract_valid tcg_target_sextract_valid + +#define TCG_TARGET_deposit_valid(type, ofs, len) 0 + +#endif diff --git a/tcg/riscv/tcg-target-mo.h b/tcg/riscv/tcg-target-mo.h new file mode 100644 index 0000000000..691b5d0da8 --- /dev/null +++ b/tcg/riscv/tcg-target-mo.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2018 SiFive, Inc + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +#define TCG_TARGET_DEFAULT_MO 0 + +#endif diff --git a/tcg/riscv/tcg-target.opc.h b/tcg/riscv/tcg-target-opc.h.inc index b80b39e1e5..b80b39e1e5 100644 --- a/tcg/riscv/tcg-target.opc.h +++ b/tcg/riscv/tcg-target-opc.h.inc diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc index 96f9a7e348..61dc310c1a 100644 --- a/tcg/riscv/tcg-target.c.inc +++ b/tcg/riscv/tcg-target.c.inc @@ -27,8 +27,14 @@ * THE SOFTWARE. */ -#include "../tcg-ldst.c.inc" -#include "../tcg-pool.c.inc" +/* Used for function call generation. */ +#define TCG_REG_CALL_STACK TCG_REG_SP +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_STACK_OFFSET 0 +#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -157,6 +163,7 @@ typedef enum { OPC_ANDI = 0x7013, OPC_AUIPC = 0x17, OPC_BEQ = 0x63, + OPC_BEXTI = 0x48005013, OPC_BGE = 0x5063, OPC_BGEU = 0x7063, OPC_BLT = 0x4063, @@ -1954,7 +1961,7 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, flush_idcache_range(jmp_rx, jmp_rw, 4); } -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) { @@ -2337,6 +2344,50 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_mb(s, a0); break; + case INDEX_op_extract_i64: + if (a2 + args[3] == 32) { + if (a2 == 0) { + tcg_out_ext32u(s, a0, a1); + } else { + tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2); + } + break; + } + /* FALLTHRU */ + case INDEX_op_extract_i32: + switch (args[3]) { + case 1: + tcg_out_opc_imm(s, OPC_BEXTI, a0, a1, a2); + break; + case 16: + tcg_debug_assert(a2 == 0); + tcg_out_ext16u(s, a0, a1); + break; + default: + g_assert_not_reached(); + } + break; + + case INDEX_op_sextract_i64: + if (a2 + args[3] == 32) { + if (a2 == 0) { + tcg_out_ext32s(s, a0, a1); + } else { + tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2); + } + break; + } + /* FALLTHRU */ + case INDEX_op_sextract_i32: + if (a2 == 0 && args[3] == 8) { + tcg_out_ext8s(s, TCG_TYPE_REG, a0, a1); + } else if (a2 == 0 && args[3] == 16) { + tcg_out_ext16s(s, TCG_TYPE_REG, a0, a1); + } else { + g_assert_not_reached(); + } + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: case INDEX_op_call: /* Always emitted via tcg_out_call. */ @@ -2577,7 +2628,8 @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) } } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -2613,6 +2665,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_extrl_i64_i32: case INDEX_op_extrh_i64_i32: case INDEX_op_ext_i32_i64: + case INDEX_op_extract_i32: + case INDEX_op_extract_i64: + case INDEX_op_sextract_i32: + case INDEX_op_sextract_i64: case INDEX_op_bswap16_i32: case INDEX_op_bswap32_i32: case INDEX_op_bswap16_i64: @@ -2761,7 +2817,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_cmpsel_vec: return C_O1_I4(v, v, vL, vK, vK); default: - g_assert_not_reached(); + return C_NotImplemented; } } diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h index 334c37cbe6..db5f3d8b72 100644 --- a/tcg/riscv/tcg-target.h +++ b/tcg/riscv/tcg-target.h @@ -25,8 +25,6 @@ #ifndef RISCV_TCG_TARGET_H #define RISCV_TCG_TARGET_H -#include "host/cpuinfo.h" - #define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_NB_REGS 64 #define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) @@ -59,118 +57,4 @@ typedef enum { TCG_REG_TMP2 = TCG_REG_T4, } TCGReg; -/* used for function call generation */ -#define TCG_REG_CALL_STACK TCG_REG_SP -#define TCG_TARGET_STACK_ALIGN 16 -#define TCG_TARGET_CALL_STACK_OFFSET 0 -#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL - -/* optional instructions */ -#define TCG_TARGET_HAS_negsetcond_i32 1 -#define TCG_TARGET_HAS_div_i32 1 -#define TCG_TARGET_HAS_rem_i32 1 -#define TCG_TARGET_HAS_div2_i32 0 -#define TCG_TARGET_HAS_rot_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_deposit_i32 0 -#define TCG_TARGET_HAS_extract_i32 0 -#define TCG_TARGET_HAS_sextract_i32 0 -#define TCG_TARGET_HAS_extract2_i32 0 -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#define TCG_TARGET_HAS_mulu2_i32 0 -#define TCG_TARGET_HAS_muls2_i32 0 -#define TCG_TARGET_HAS_muluh_i32 0 -#define TCG_TARGET_HAS_mulsh_i32 0 -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_ext8u_i32 1 -#define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_bswap32_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_andc_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_orc_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_eqv_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_clz_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_ctz_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_ctpop_i32 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_brcond2 1 -#define TCG_TARGET_HAS_setcond2 1 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -#define TCG_TARGET_HAS_negsetcond_i64 1 -#define TCG_TARGET_HAS_div_i64 1 -#define TCG_TARGET_HAS_rem_i64 1 -#define TCG_TARGET_HAS_div2_i64 0 -#define TCG_TARGET_HAS_rot_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_deposit_i64 0 -#define TCG_TARGET_HAS_extract_i64 0 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_extr_i64_i32 1 -#define TCG_TARGET_HAS_ext8s_i64 1 -#define TCG_TARGET_HAS_ext16s_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i64 1 -#define TCG_TARGET_HAS_ext16u_i64 1 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_bswap32_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_bswap64_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_andc_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_orc_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_eqv_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 0 -#define TCG_TARGET_HAS_clz_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_ctz_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_ctpop_i64 (cpuinfo & CPUINFO_ZBB) -#define TCG_TARGET_HAS_add2_i64 1 -#define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i64 0 -#define TCG_TARGET_HAS_muls2_i64 0 -#define TCG_TARGET_HAS_muluh_i64 1 -#define TCG_TARGET_HAS_mulsh_i64 1 - -#define TCG_TARGET_HAS_qemu_ldst_i128 0 - -#define TCG_TARGET_HAS_tst 0 - -/* vector instructions */ -#define TCG_TARGET_HAS_v64 (cpuinfo & CPUINFO_ZVE64X) -#define TCG_TARGET_HAS_v128 (cpuinfo & CPUINFO_ZVE64X) -#define TCG_TARGET_HAS_v256 (cpuinfo & CPUINFO_ZVE64X) -#define TCG_TARGET_HAS_andc_vec 0 -#define TCG_TARGET_HAS_orc_vec 0 -#define TCG_TARGET_HAS_nand_vec 0 -#define TCG_TARGET_HAS_nor_vec 0 -#define TCG_TARGET_HAS_eqv_vec 0 -#define TCG_TARGET_HAS_not_vec 1 -#define TCG_TARGET_HAS_neg_vec 1 -#define TCG_TARGET_HAS_abs_vec 0 -#define TCG_TARGET_HAS_roti_vec 1 -#define TCG_TARGET_HAS_rots_vec 1 -#define TCG_TARGET_HAS_rotv_vec 1 -#define TCG_TARGET_HAS_shi_vec 1 -#define TCG_TARGET_HAS_shs_vec 1 -#define TCG_TARGET_HAS_shv_vec 1 -#define TCG_TARGET_HAS_mul_vec 1 -#define TCG_TARGET_HAS_sat_vec 1 -#define TCG_TARGET_HAS_minmax_vec 1 -#define TCG_TARGET_HAS_bitsel_vec 0 -#define TCG_TARGET_HAS_cmpsel_vec 1 - -#define TCG_TARGET_HAS_tst_vec 0 - -#define TCG_TARGET_DEFAULT_MO (0) - -#define TCG_TARGET_NEED_LDST_LABELS -#define TCG_TARGET_NEED_POOL_LABELS - #endif diff --git a/tcg/s390x/tcg-target-has.h b/tcg/s390x/tcg-target-has.h new file mode 100644 index 0000000000..e99e671642 --- /dev/null +++ b/tcg/s390x/tcg-target-has.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2009 Ulrich Hecht <uli@suse.de> + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +/* Facilities required for proper operation; checked at startup. */ + +#define FACILITY_ZARCH_ACTIVE 2 +#define FACILITY_LONG_DISP 18 +#define FACILITY_EXT_IMM 21 +#define FACILITY_GEN_INST_EXT 34 +#define FACILITY_45 45 + +/* Facilities that are checked at runtime. */ + +#define FACILITY_LOAD_ON_COND2 53 +#define FACILITY_MISC_INSN_EXT2 58 +#define FACILITY_MISC_INSN_EXT3 61 +#define FACILITY_VECTOR 129 +#define FACILITY_VECTOR_ENH1 135 + +extern uint64_t s390_facilities[3]; + +#define HAVE_FACILITY(X) \ + ((s390_facilities[FACILITY_##X / 64] >> (63 - FACILITY_##X % 64)) & 1) + +/* optional instructions */ +#define TCG_TARGET_HAS_div2_i32 1 +#define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_not_i32 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_andc_i32 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_orc_i32 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_eqv_i32 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_nand_i32 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_nor_i32 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_clz_i32 0 +#define TCG_TARGET_HAS_ctz_i32 0 +#define TCG_TARGET_HAS_ctpop_i32 1 +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_negsetcond_i32 1 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 0 +#define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_extr_i64_i32 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +#define TCG_TARGET_HAS_div2_i64 1 +#define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 1 +#define TCG_TARGET_HAS_ext16u_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 +#define TCG_TARGET_HAS_not_i64 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_andc_i64 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_orc_i64 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_eqv_i64 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_nand_i64 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_nor_i64 HAVE_FACILITY(MISC_INSN_EXT3) +#define TCG_TARGET_HAS_clz_i64 1 +#define TCG_TARGET_HAS_ctz_i64 0 +#define TCG_TARGET_HAS_ctpop_i64 1 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_negsetcond_i64 1 +#define TCG_TARGET_HAS_add2_i64 1 +#define TCG_TARGET_HAS_sub2_i64 1 +#define TCG_TARGET_HAS_mulu2_i64 1 +#define TCG_TARGET_HAS_muls2_i64 HAVE_FACILITY(MISC_INSN_EXT2) +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 + +#define TCG_TARGET_HAS_qemu_ldst_i128 1 + +#define TCG_TARGET_HAS_tst 1 + +#define TCG_TARGET_HAS_v64 HAVE_FACILITY(VECTOR) +#define TCG_TARGET_HAS_v128 HAVE_FACILITY(VECTOR) +#define TCG_TARGET_HAS_v256 0 + +#define TCG_TARGET_HAS_andc_vec 1 +#define TCG_TARGET_HAS_orc_vec HAVE_FACILITY(VECTOR_ENH1) +#define TCG_TARGET_HAS_nand_vec HAVE_FACILITY(VECTOR_ENH1) +#define TCG_TARGET_HAS_nor_vec 1 +#define TCG_TARGET_HAS_eqv_vec HAVE_FACILITY(VECTOR_ENH1) +#define TCG_TARGET_HAS_not_vec 1 +#define TCG_TARGET_HAS_neg_vec 1 +#define TCG_TARGET_HAS_abs_vec 1 +#define TCG_TARGET_HAS_roti_vec 1 +#define TCG_TARGET_HAS_rots_vec 1 +#define TCG_TARGET_HAS_rotv_vec 1 +#define TCG_TARGET_HAS_shi_vec 1 +#define TCG_TARGET_HAS_shs_vec 1 +#define TCG_TARGET_HAS_shv_vec 1 +#define TCG_TARGET_HAS_mul_vec 1 +#define TCG_TARGET_HAS_sat_vec 0 +#define TCG_TARGET_HAS_minmax_vec 1 +#define TCG_TARGET_HAS_bitsel_vec 1 +#define TCG_TARGET_HAS_cmpsel_vec 1 +#define TCG_TARGET_HAS_tst_vec 0 + +#define TCG_TARGET_extract_valid(type, ofs, len) 1 +#define TCG_TARGET_deposit_valid(type, ofs, len) 1 + +static inline bool +tcg_target_sextract_valid(TCGType type, unsigned ofs, unsigned len) +{ + if (ofs == 0) { + switch (len) { + case 8: + case 16: + return true; + case 32: + return type == TCG_TYPE_I64; + } + } + return false; +} +#define TCG_TARGET_sextract_valid tcg_target_sextract_valid + +#endif diff --git a/tcg/s390x/tcg-target-mo.h b/tcg/s390x/tcg-target-mo.h new file mode 100644 index 0000000000..962295ed51 --- /dev/null +++ b/tcg/s390x/tcg-target-mo.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2009 Ulrich Hecht <uli@suse.de> + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) + +#endif diff --git a/tcg/s390x/tcg-target.opc.h b/tcg/s390x/tcg-target-opc.h.inc index 0eb2350fb3..61237b39cd 100644 --- a/tcg/s390x/tcg-target.opc.h +++ b/tcg/s390x/tcg-target-opc.h.inc @@ -10,6 +10,6 @@ * emitted by tcg_expand_vec_op. For those familiar with GCC internals, * consider these to be UNSPEC with names. */ -DEF(s390_vuph_vec, 1, 1, 0, IMPLVEC) -DEF(s390_vupl_vec, 1, 1, 0, IMPLVEC) -DEF(s390_vpks_vec, 1, 2, 0, IMPLVEC) +DEF(s390_vuph_vec, 1, 1, 0, TCG_OPF_VECTOR) +DEF(s390_vupl_vec, 1, 1, 0, TCG_OPF_VECTOR) +DEF(s390_vpks_vec, 1, 2, 0, TCG_OPF_VECTOR) diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc index 27bccc14e5..dc7722dc31 100644 --- a/tcg/s390x/tcg-target.c.inc +++ b/tcg/s390x/tcg-target.c.inc @@ -24,10 +24,16 @@ * THE SOFTWARE. */ -#include "../tcg-ldst.c.inc" -#include "../tcg-pool.c.inc" #include "elf.h" +/* Used for function call generation. */ +#define TCG_TARGET_STACK_ALIGN 8 +#define TCG_TARGET_CALL_STACK_OFFSET 160 +#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EXTEND +#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_BY_REF +#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF + #define TCG_CT_CONST_S16 (1 << 8) #define TCG_CT_CONST_S32 (1 << 9) #define TCG_CT_CONST_U32 (1 << 10) @@ -1566,9 +1572,41 @@ static void tgen_deposit(TCGContext *s, TCGReg dest, TCGReg src, static void tgen_extract(TCGContext *s, TCGReg dest, TCGReg src, int ofs, int len) { + if (ofs == 0) { + switch (len) { + case 8: + tcg_out_ext8u(s, dest, src); + return; + case 16: + tcg_out_ext16u(s, dest, src); + return; + case 32: + tcg_out_ext32u(s, dest, src); + return; + } + } tcg_out_risbg(s, dest, src, 64 - len, 63, 64 - ofs, 1); } +static void tgen_sextract(TCGContext *s, TCGReg dest, TCGReg src, + int ofs, int len) +{ + if (ofs == 0) { + switch (len) { + case 8: + tcg_out_ext8s(s, TCG_TYPE_REG, dest, src); + return; + case 16: + tcg_out_ext16s(s, TCG_TYPE_REG, dest, src); + return; + case 32: + tcg_out_ext32s(s, dest, src); + return; + } + } + g_assert_not_reached(); +} + static void tgen_gotoi(TCGContext *s, int cc, const tcg_insn_unit *dest) { ptrdiff_t off = tcg_pcrel_diff(s, dest) >> 1; @@ -2111,9 +2149,9 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, case glue(glue(INDEX_op_,x),_i32): \ case glue(glue(INDEX_op_,x),_i64) -static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, - const TCGArg args[TCG_MAX_OP_ARGS], - const int const_args[TCG_MAX_OP_ARGS]) +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, + const TCGArg args[TCG_MAX_OP_ARGS], + const int const_args[TCG_MAX_OP_ARGS]) { S390Opcode op, op2; TCGArg a0, a1, a2; @@ -2707,7 +2745,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, /* Since we can't support "0Z" as a constraint, we allow a1 in any register. Fix things up as if a matching constraint. */ if (a0 != a1) { - TCGType type = (opc == INDEX_op_deposit_i64); if (a0 == a2) { tcg_out_mov(s, type, TCG_TMP0, a2); a2 = TCG_TMP0; @@ -2721,6 +2758,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, OP_32_64(extract): tgen_extract(s, args[0], args[1], args[2], args[3]); break; + OP_32_64(sextract): + tgen_sextract(s, args[0], args[1], args[2], args[3]); + break; case INDEX_op_clz_i64: tgen_clz(s, args[0], args[1], args[2], const_args[2]); @@ -3201,7 +3241,8 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, va_end(va); } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -3319,6 +3360,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_extu_i32_i64: case INDEX_op_extract_i32: case INDEX_op_extract_i64: + case INDEX_op_sextract_i32: + case INDEX_op_sextract_i64: case INDEX_op_ctpop_i32: case INDEX_op_ctpop_i64: return C_O1_I1(r, r); @@ -3421,7 +3464,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) : C_O1_I4(v, v, v, vZ, v)); default: - g_assert_not_reached(); + return C_NotImplemented; } } diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h index 86aeca166f..0ef5a6d3dd 100644 --- a/tcg/s390x/tcg-target.h +++ b/tcg/s390x/tcg-target.h @@ -51,130 +51,4 @@ typedef enum TCGReg { #define TCG_TARGET_NB_REGS 64 -/* Facilities required for proper operation; checked at startup. */ - -#define FACILITY_ZARCH_ACTIVE 2 -#define FACILITY_LONG_DISP 18 -#define FACILITY_EXT_IMM 21 -#define FACILITY_GEN_INST_EXT 34 -#define FACILITY_45 45 - -/* Facilities that are checked at runtime. */ - -#define FACILITY_LOAD_ON_COND2 53 -#define FACILITY_MISC_INSN_EXT2 58 -#define FACILITY_MISC_INSN_EXT3 61 -#define FACILITY_VECTOR 129 -#define FACILITY_VECTOR_ENH1 135 - -extern uint64_t s390_facilities[3]; - -#define HAVE_FACILITY(X) \ - ((s390_facilities[FACILITY_##X / 64] >> (63 - FACILITY_##X % 64)) & 1) - -/* optional instructions */ -#define TCG_TARGET_HAS_div2_i32 1 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_ext8u_i32 1 -#define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_not_i32 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_andc_i32 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_orc_i32 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_eqv_i32 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_nand_i32 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_nor_i32 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_clz_i32 0 -#define TCG_TARGET_HAS_ctz_i32 0 -#define TCG_TARGET_HAS_ctpop_i32 1 -#define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 1 -#define TCG_TARGET_HAS_sextract_i32 0 -#define TCG_TARGET_HAS_extract2_i32 0 -#define TCG_TARGET_HAS_negsetcond_i32 1 -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#define TCG_TARGET_HAS_mulu2_i32 0 -#define TCG_TARGET_HAS_muls2_i32 0 -#define TCG_TARGET_HAS_muluh_i32 0 -#define TCG_TARGET_HAS_mulsh_i32 0 -#define TCG_TARGET_HAS_extr_i64_i32 0 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -#define TCG_TARGET_HAS_div2_i64 1 -#define TCG_TARGET_HAS_rot_i64 1 -#define TCG_TARGET_HAS_ext8s_i64 1 -#define TCG_TARGET_HAS_ext16s_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i64 1 -#define TCG_TARGET_HAS_ext16u_i64 1 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 1 -#define TCG_TARGET_HAS_bswap32_i64 1 -#define TCG_TARGET_HAS_bswap64_i64 1 -#define TCG_TARGET_HAS_not_i64 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_andc_i64 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_orc_i64 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_eqv_i64 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_nand_i64 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_nor_i64 HAVE_FACILITY(MISC_INSN_EXT3) -#define TCG_TARGET_HAS_clz_i64 1 -#define TCG_TARGET_HAS_ctz_i64 0 -#define TCG_TARGET_HAS_ctpop_i64 1 -#define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 1 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_negsetcond_i64 1 -#define TCG_TARGET_HAS_add2_i64 1 -#define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i64 1 -#define TCG_TARGET_HAS_muls2_i64 HAVE_FACILITY(MISC_INSN_EXT2) -#define TCG_TARGET_HAS_muluh_i64 0 -#define TCG_TARGET_HAS_mulsh_i64 0 - -#define TCG_TARGET_HAS_qemu_ldst_i128 1 - -#define TCG_TARGET_HAS_tst 1 - -#define TCG_TARGET_HAS_v64 HAVE_FACILITY(VECTOR) -#define TCG_TARGET_HAS_v128 HAVE_FACILITY(VECTOR) -#define TCG_TARGET_HAS_v256 0 - -#define TCG_TARGET_HAS_andc_vec 1 -#define TCG_TARGET_HAS_orc_vec HAVE_FACILITY(VECTOR_ENH1) -#define TCG_TARGET_HAS_nand_vec HAVE_FACILITY(VECTOR_ENH1) -#define TCG_TARGET_HAS_nor_vec 1 -#define TCG_TARGET_HAS_eqv_vec HAVE_FACILITY(VECTOR_ENH1) -#define TCG_TARGET_HAS_not_vec 1 -#define TCG_TARGET_HAS_neg_vec 1 -#define TCG_TARGET_HAS_abs_vec 1 -#define TCG_TARGET_HAS_roti_vec 1 -#define TCG_TARGET_HAS_rots_vec 1 -#define TCG_TARGET_HAS_rotv_vec 1 -#define TCG_TARGET_HAS_shi_vec 1 -#define TCG_TARGET_HAS_shs_vec 1 -#define TCG_TARGET_HAS_shv_vec 1 -#define TCG_TARGET_HAS_mul_vec 1 -#define TCG_TARGET_HAS_sat_vec 0 -#define TCG_TARGET_HAS_minmax_vec 1 -#define TCG_TARGET_HAS_bitsel_vec 1 -#define TCG_TARGET_HAS_cmpsel_vec 1 -#define TCG_TARGET_HAS_tst_vec 0 - -/* used for function call generation */ -#define TCG_TARGET_STACK_ALIGN 8 -#define TCG_TARGET_CALL_STACK_OFFSET 160 -#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EXTEND -#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_BY_REF -#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF - -#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) -#define TCG_TARGET_NEED_LDST_LABELS -#define TCG_TARGET_NEED_POOL_LABELS - #endif diff --git a/tcg/sparc64/tcg-target-has.h b/tcg/sparc64/tcg-target-has.h new file mode 100644 index 0000000000..2f46df8c61 --- /dev/null +++ b/tcg/sparc64/tcg-target-has.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2008 Fabrice Bellard + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +#if defined(__VIS__) && __VIS__ >= 0x300 +#define use_vis3_instructions 1 +#else +extern bool use_vis3_instructions; +#endif + +/* optional instructions */ +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 0 +#define TCG_TARGET_HAS_rot_i32 0 +#define TCG_TARGET_HAS_ext8s_i32 0 +#define TCG_TARGET_HAS_ext16s_i32 0 +#define TCG_TARGET_HAS_ext8u_i32 0 +#define TCG_TARGET_HAS_ext16u_i32 0 +#define TCG_TARGET_HAS_bswap16_i32 0 +#define TCG_TARGET_HAS_bswap32_i32 0 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_andc_i32 1 +#define TCG_TARGET_HAS_orc_i32 1 +#define TCG_TARGET_HAS_eqv_i32 0 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 0 +#define TCG_TARGET_HAS_ctz_i32 0 +#define TCG_TARGET_HAS_ctpop_i32 0 +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_negsetcond_i32 1 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 1 +#define TCG_TARGET_HAS_muls2_i32 1 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +#define TCG_TARGET_HAS_extr_i64_i32 0 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 0 +#define TCG_TARGET_HAS_rot_i64 0 +#define TCG_TARGET_HAS_ext8s_i64 0 +#define TCG_TARGET_HAS_ext16s_i64 0 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 0 +#define TCG_TARGET_HAS_ext16u_i64 0 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_bswap16_i64 0 +#define TCG_TARGET_HAS_bswap32_i64 0 +#define TCG_TARGET_HAS_bswap64_i64 0 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_andc_i64 1 +#define TCG_TARGET_HAS_orc_i64 1 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 0 +#define TCG_TARGET_HAS_ctz_i64 0 +#define TCG_TARGET_HAS_ctpop_i64 0 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_negsetcond_i64 1 +#define TCG_TARGET_HAS_add2_i64 1 +#define TCG_TARGET_HAS_sub2_i64 1 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 use_vis3_instructions +#define TCG_TARGET_HAS_mulsh_i64 0 + +#define TCG_TARGET_HAS_qemu_ldst_i128 0 + +#define TCG_TARGET_HAS_tst 1 + +#define TCG_TARGET_extract_valid(type, ofs, len) \ + ((type) == TCG_TYPE_I64 && (ofs) + (len) == 32) + +#define TCG_TARGET_sextract_valid TCG_TARGET_extract_valid + +#define TCG_TARGET_deposit_valid(type, ofs, len) 0 + +#endif diff --git a/tcg/sparc64/tcg-target-mo.h b/tcg/sparc64/tcg-target-mo.h new file mode 100644 index 0000000000..98bfe03b7a --- /dev/null +++ b/tcg/sparc64/tcg-target-mo.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2008 Fabrice Bellard + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +#define TCG_TARGET_DEFAULT_MO 0 + +#endif diff --git a/tcg/sparc64/tcg-target-opc.h.inc b/tcg/sparc64/tcg-target-opc.h.inc new file mode 100644 index 0000000000..84e777bfe5 --- /dev/null +++ b/tcg/sparc64/tcg-target-opc.h.inc @@ -0,0 +1 @@ +/* No target specific opcodes. */ diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc index 32f9ec24b5..733cb51651 100644 --- a/tcg/sparc64/tcg-target.c.inc +++ b/tcg/sparc64/tcg-target.c.inc @@ -27,8 +27,15 @@ #error "unsupported code generation mode" #endif -#include "../tcg-ldst.c.inc" -#include "../tcg-pool.c.inc" +/* Used for function call generation. */ +#define TCG_REG_CALL_STACK TCG_REG_O6 +#define TCG_TARGET_STACK_BIAS 2047 +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_STACK_OFFSET (128 + 6 * 8 + TCG_TARGET_STACK_BIAS) +#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EXTEND +#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL +#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -1281,7 +1288,7 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, { } -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) { @@ -1503,6 +1510,15 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_mb(s, a0); break; + case INDEX_op_extract_i64: + tcg_debug_assert(a2 + args[3] == 32); + tcg_out_arithi(s, a0, a1, a2, SHIFT_SRL); + break; + case INDEX_op_sextract_i64: + tcg_debug_assert(a2 + args[3] == 32); + tcg_out_arithi(s, a0, a1, a2, SHIFT_SRA); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: case INDEX_op_call: /* Always emitted via tcg_out_call. */ @@ -1525,7 +1541,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, } } -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -1551,6 +1568,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_ext32u_i64: case INDEX_op_ext_i32_i64: case INDEX_op_extu_i32_i64: + case INDEX_op_extract_i64: + case INDEX_op_sextract_i64: case INDEX_op_qemu_ld_a32_i32: case INDEX_op_qemu_ld_a64_i32: case INDEX_op_qemu_ld_a32_i64: @@ -1620,7 +1639,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) return C_O1_I2(r, r, r); default: - g_assert_not_reached(); + return C_NotImplemented; } } diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h index a18906a14e..f7d75d5806 100644 --- a/tcg/sparc64/tcg-target.h +++ b/tcg/sparc64/tcg-target.h @@ -64,97 +64,6 @@ typedef enum { TCG_REG_I7, } TCGReg; -/* used for function call generation */ -#define TCG_REG_CALL_STACK TCG_REG_O6 - -#define TCG_TARGET_STACK_BIAS 2047 -#define TCG_TARGET_STACK_ALIGN 16 -#define TCG_TARGET_CALL_STACK_OFFSET (128 + 6*8 + TCG_TARGET_STACK_BIAS) -#define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EXTEND -#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL -#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL - -#if defined(__VIS__) && __VIS__ >= 0x300 -#define use_vis3_instructions 1 -#else -extern bool use_vis3_instructions; -#endif - -/* optional instructions */ -#define TCG_TARGET_HAS_div_i32 1 -#define TCG_TARGET_HAS_rem_i32 0 -#define TCG_TARGET_HAS_rot_i32 0 -#define TCG_TARGET_HAS_ext8s_i32 0 -#define TCG_TARGET_HAS_ext16s_i32 0 -#define TCG_TARGET_HAS_ext8u_i32 0 -#define TCG_TARGET_HAS_ext16u_i32 0 -#define TCG_TARGET_HAS_bswap16_i32 0 -#define TCG_TARGET_HAS_bswap32_i32 0 -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_andc_i32 1 -#define TCG_TARGET_HAS_orc_i32 1 -#define TCG_TARGET_HAS_eqv_i32 0 -#define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_clz_i32 0 -#define TCG_TARGET_HAS_ctz_i32 0 -#define TCG_TARGET_HAS_ctpop_i32 0 -#define TCG_TARGET_HAS_deposit_i32 0 -#define TCG_TARGET_HAS_extract_i32 0 -#define TCG_TARGET_HAS_sextract_i32 0 -#define TCG_TARGET_HAS_extract2_i32 0 -#define TCG_TARGET_HAS_negsetcond_i32 1 -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#define TCG_TARGET_HAS_mulu2_i32 1 -#define TCG_TARGET_HAS_muls2_i32 1 -#define TCG_TARGET_HAS_muluh_i32 0 -#define TCG_TARGET_HAS_mulsh_i32 0 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -#define TCG_TARGET_HAS_extr_i64_i32 0 -#define TCG_TARGET_HAS_div_i64 1 -#define TCG_TARGET_HAS_rem_i64 0 -#define TCG_TARGET_HAS_rot_i64 0 -#define TCG_TARGET_HAS_ext8s_i64 0 -#define TCG_TARGET_HAS_ext16s_i64 0 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i64 0 -#define TCG_TARGET_HAS_ext16u_i64 0 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 0 -#define TCG_TARGET_HAS_bswap32_i64 0 -#define TCG_TARGET_HAS_bswap64_i64 0 -#define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_andc_i64 1 -#define TCG_TARGET_HAS_orc_i64 1 -#define TCG_TARGET_HAS_eqv_i64 0 -#define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 0 -#define TCG_TARGET_HAS_clz_i64 0 -#define TCG_TARGET_HAS_ctz_i64 0 -#define TCG_TARGET_HAS_ctpop_i64 0 -#define TCG_TARGET_HAS_deposit_i64 0 -#define TCG_TARGET_HAS_extract_i64 0 -#define TCG_TARGET_HAS_sextract_i64 0 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_negsetcond_i64 1 -#define TCG_TARGET_HAS_add2_i64 1 -#define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i64 0 -#define TCG_TARGET_HAS_muls2_i64 0 -#define TCG_TARGET_HAS_muluh_i64 use_vis3_instructions -#define TCG_TARGET_HAS_mulsh_i64 0 - -#define TCG_TARGET_HAS_qemu_ldst_i128 0 - -#define TCG_TARGET_HAS_tst 1 - #define TCG_AREG0 TCG_REG_I0 -#define TCG_TARGET_DEFAULT_MO (0) -#define TCG_TARGET_NEED_LDST_LABELS -#define TCG_TARGET_NEED_POOL_LABELS - #endif diff --git a/tcg/tcg-common.c b/tcg/tcg-common.c index 35e7616ae9..e98b3e5fdd 100644 --- a/tcg/tcg-common.c +++ b/tcg/tcg-common.c @@ -24,10 +24,11 @@ #include "qemu/osdep.h" #include "tcg/tcg.h" +#include "tcg-has.h" -TCGOpDef tcg_op_defs[] = { +const TCGOpDef tcg_op_defs[] = { #define DEF(s, oargs, iargs, cargs, flags) \ - { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, NULL }, + { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags }, #include "tcg/tcg-opc.h" #undef DEF }; diff --git a/tcg/tcg-has.h b/tcg/tcg-has.h new file mode 100644 index 0000000000..418e4673eb --- /dev/null +++ b/tcg/tcg-has.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2024 Linaro, Ltd. + */ + +#ifndef TCG_HAS_H +#define TCG_HAS_H + +#include "tcg-target-has.h" + +#if TCG_TARGET_REG_BITS == 32 +/* Turn some undef macros into false macros. */ +#define TCG_TARGET_HAS_extr_i64_i32 0 +#define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 +#define TCG_TARGET_HAS_div2_i64 0 +#define TCG_TARGET_HAS_rot_i64 0 +#define TCG_TARGET_HAS_ext8s_i64 0 +#define TCG_TARGET_HAS_ext16s_i64 0 +#define TCG_TARGET_HAS_ext32s_i64 0 +#define TCG_TARGET_HAS_ext8u_i64 0 +#define TCG_TARGET_HAS_ext16u_i64 0 +#define TCG_TARGET_HAS_ext32u_i64 0 +#define TCG_TARGET_HAS_bswap16_i64 0 +#define TCG_TARGET_HAS_bswap32_i64 0 +#define TCG_TARGET_HAS_bswap64_i64 0 +#define TCG_TARGET_HAS_not_i64 0 +#define TCG_TARGET_HAS_andc_i64 0 +#define TCG_TARGET_HAS_orc_i64 0 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 0 +#define TCG_TARGET_HAS_ctz_i64 0 +#define TCG_TARGET_HAS_ctpop_i64 0 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_negsetcond_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 +/* Turn some undef macros into true macros. */ +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#endif + +/* Only one of DIV or DIV2 should be defined. */ +#if defined(TCG_TARGET_HAS_div_i32) +#define TCG_TARGET_HAS_div2_i32 0 +#elif defined(TCG_TARGET_HAS_div2_i32) +#define TCG_TARGET_HAS_div_i32 0 +#define TCG_TARGET_HAS_rem_i32 0 +#endif +#if defined(TCG_TARGET_HAS_div_i64) +#define TCG_TARGET_HAS_div2_i64 0 +#elif defined(TCG_TARGET_HAS_div2_i64) +#define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 +#endif + +#if !defined(TCG_TARGET_HAS_v64) \ + && !defined(TCG_TARGET_HAS_v128) \ + && !defined(TCG_TARGET_HAS_v256) +#define TCG_TARGET_MAYBE_vec 0 +#define TCG_TARGET_HAS_abs_vec 0 +#define TCG_TARGET_HAS_neg_vec 0 +#define TCG_TARGET_HAS_not_vec 0 +#define TCG_TARGET_HAS_andc_vec 0 +#define TCG_TARGET_HAS_orc_vec 0 +#define TCG_TARGET_HAS_nand_vec 0 +#define TCG_TARGET_HAS_nor_vec 0 +#define TCG_TARGET_HAS_eqv_vec 0 +#define TCG_TARGET_HAS_roti_vec 0 +#define TCG_TARGET_HAS_rots_vec 0 +#define TCG_TARGET_HAS_rotv_vec 0 +#define TCG_TARGET_HAS_shi_vec 0 +#define TCG_TARGET_HAS_shs_vec 0 +#define TCG_TARGET_HAS_shv_vec 0 +#define TCG_TARGET_HAS_mul_vec 0 +#define TCG_TARGET_HAS_sat_vec 0 +#define TCG_TARGET_HAS_minmax_vec 0 +#define TCG_TARGET_HAS_bitsel_vec 0 +#define TCG_TARGET_HAS_cmpsel_vec 0 +#define TCG_TARGET_HAS_tst_vec 0 +#else +#define TCG_TARGET_MAYBE_vec 1 +#endif +#ifndef TCG_TARGET_HAS_v64 +#define TCG_TARGET_HAS_v64 0 +#endif +#ifndef TCG_TARGET_HAS_v128 +#define TCG_TARGET_HAS_v128 0 +#endif +#ifndef TCG_TARGET_HAS_v256 +#define TCG_TARGET_HAS_v256 0 +#endif + +#endif diff --git a/tcg/tcg-internal.h b/tcg/tcg-internal.h index 8099248076..a648ee7a0e 100644 --- a/tcg/tcg-internal.h +++ b/tcg/tcg-internal.h @@ -92,12 +92,13 @@ TCGTemp *tcg_temp_new_internal(TCGType type, TCGTempKind kind); */ TCGTemp *tcg_constant_internal(TCGType type, int64_t val); -TCGOp *tcg_gen_op1(TCGOpcode, TCGArg); -TCGOp *tcg_gen_op2(TCGOpcode, TCGArg, TCGArg); -TCGOp *tcg_gen_op3(TCGOpcode, TCGArg, TCGArg, TCGArg); -TCGOp *tcg_gen_op4(TCGOpcode, TCGArg, TCGArg, TCGArg, TCGArg); -TCGOp *tcg_gen_op5(TCGOpcode, TCGArg, TCGArg, TCGArg, TCGArg, TCGArg); -TCGOp *tcg_gen_op6(TCGOpcode, TCGArg, TCGArg, TCGArg, TCGArg, TCGArg, TCGArg); +TCGOp *tcg_gen_op1(TCGOpcode, TCGType, TCGArg); +TCGOp *tcg_gen_op2(TCGOpcode, TCGType, TCGArg, TCGArg); +TCGOp *tcg_gen_op3(TCGOpcode, TCGType, TCGArg, TCGArg, TCGArg); +TCGOp *tcg_gen_op4(TCGOpcode, TCGType, TCGArg, TCGArg, TCGArg, TCGArg); +TCGOp *tcg_gen_op5(TCGOpcode, TCGType, TCGArg, TCGArg, TCGArg, TCGArg, TCGArg); +TCGOp *tcg_gen_op6(TCGOpcode, TCGType, TCGArg, TCGArg, + TCGArg, TCGArg, TCGArg, TCGArg); void vec_gen_2(TCGOpcode, TCGType, unsigned, TCGArg, TCGArg); void vec_gen_3(TCGOpcode, TCGType, unsigned, TCGArg, TCGArg, TCGArg); @@ -105,4 +106,9 @@ void vec_gen_4(TCGOpcode, TCGType, unsigned, TCGArg, TCGArg, TCGArg, TCGArg); void vec_gen_6(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a, TCGArg b, TCGArg c, TCGArg d, TCGArg e); +TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *op, + TCGOpcode opc, unsigned nargs); +TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, + TCGOpcode opc, unsigned nargs); + #endif /* TCG_INTERNAL_H */ diff --git a/tcg/tcg-ldst.c.inc b/tcg/tcg-ldst.c.inc deleted file mode 100644 index ffada04af0..0000000000 --- a/tcg/tcg-ldst.c.inc +++ /dev/null @@ -1,65 +0,0 @@ -/* - * TCG Backend Data: load-store optimization only. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * Generate TB finalization at the end of block - */ - -static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l); -static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l); - -static int tcg_out_ldst_finalize(TCGContext *s) -{ - TCGLabelQemuLdst *lb; - - /* qemu_ld/st slow paths */ - QSIMPLEQ_FOREACH(lb, &s->ldst_labels, next) { - if (lb->is_ld - ? !tcg_out_qemu_ld_slow_path(s, lb) - : !tcg_out_qemu_st_slow_path(s, lb)) { - return -2; - } - - /* Test for (pending) buffer overflow. The assumption is that any - one operation beginning below the high water mark cannot overrun - the buffer completely. Thus we can test for overflow after - generating code without having to check during generation. */ - if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) { - return -1; - } - } - return 0; -} - -/* - * Allocate a new TCGLabelQemuLdst entry. - */ - -static inline TCGLabelQemuLdst *new_ldst_label(TCGContext *s) -{ - TCGLabelQemuLdst *l = tcg_malloc(sizeof(*l)); - - memset(l, 0, sizeof(*l)); - QSIMPLEQ_INSERT_TAIL(&s->ldst_labels, l, next); - - return l; -} diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c index 97e4df221a..d32a4f146d 100644 --- a/tcg/tcg-op-gvec.c +++ b/tcg/tcg-op-gvec.c @@ -23,6 +23,7 @@ #include "tcg/tcg-op-common.h" #include "tcg/tcg-op-gvec-common.h" #include "tcg/tcg-gvec-desc.h" +#include "tcg-has.h" #define MAX_UNROLL 4 diff --git a/tcg/tcg-op-ldst.c b/tcg/tcg-op-ldst.c index a318011229..77271e0193 100644 --- a/tcg/tcg-op-ldst.c +++ b/tcg/tcg-op-ldst.c @@ -30,7 +30,8 @@ #include "exec/translation-block.h" #include "exec/plugin-gen.h" #include "tcg-internal.h" - +#include "tcg-has.h" +#include "tcg-target-mo.h" static void check_max_alignment(unsigned a_bits) { @@ -87,14 +88,15 @@ static MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st) return op; } -static void gen_ldst(TCGOpcode opc, TCGTemp *vl, TCGTemp *vh, +static void gen_ldst(TCGOpcode opc, TCGType type, TCGTemp *vl, TCGTemp *vh, TCGTemp *addr, MemOpIdx oi) { if (TCG_TARGET_REG_BITS == 64 || tcg_ctx->addr_type == TCG_TYPE_I32) { if (vh) { - tcg_gen_op4(opc, temp_arg(vl), temp_arg(vh), temp_arg(addr), oi); + tcg_gen_op4(opc, type, temp_arg(vl), temp_arg(vh), + temp_arg(addr), oi); } else { - tcg_gen_op3(opc, temp_arg(vl), temp_arg(addr), oi); + tcg_gen_op3(opc, type, temp_arg(vl), temp_arg(addr), oi); } } else { /* See TCGV_LOW/HIGH. */ @@ -102,10 +104,11 @@ static void gen_ldst(TCGOpcode opc, TCGTemp *vl, TCGTemp *vh, TCGTemp *ah = addr + !HOST_BIG_ENDIAN; if (vh) { - tcg_gen_op5(opc, temp_arg(vl), temp_arg(vh), + tcg_gen_op5(opc, type, temp_arg(vl), temp_arg(vh), temp_arg(al), temp_arg(ah), oi); } else { - tcg_gen_op4(opc, temp_arg(vl), temp_arg(al), temp_arg(ah), oi); + tcg_gen_op4(opc, type, temp_arg(vl), + temp_arg(al), temp_arg(ah), oi); } } } @@ -115,9 +118,9 @@ static void gen_ldst_i64(TCGOpcode opc, TCGv_i64 v, TCGTemp *addr, MemOpIdx oi) if (TCG_TARGET_REG_BITS == 32) { TCGTemp *vl = tcgv_i32_temp(TCGV_LOW(v)); TCGTemp *vh = tcgv_i32_temp(TCGV_HIGH(v)); - gen_ldst(opc, vl, vh, addr, oi); + gen_ldst(opc, TCG_TYPE_I64, vl, vh, addr, oi); } else { - gen_ldst(opc, tcgv_i64_temp(v), NULL, addr, oi); + gen_ldst(opc, TCG_TYPE_I64, tcgv_i64_temp(v), NULL, addr, oi); } } @@ -250,7 +253,7 @@ static void tcg_gen_qemu_ld_i32_int(TCGv_i32 val, TCGTemp *addr, } else { opc = INDEX_op_qemu_ld_a64_i32; } - gen_ldst(opc, tcgv_i32_temp(val), NULL, addr, oi); + gen_ldst(opc, TCG_TYPE_I32, tcgv_i32_temp(val), NULL, addr, oi); plugin_gen_mem_callbacks_i32(val, copy_addr, addr, orig_oi, QEMU_PLUGIN_MEM_R); @@ -319,7 +322,7 @@ static void tcg_gen_qemu_st_i32_int(TCGv_i32 val, TCGTemp *addr, opc = INDEX_op_qemu_st_a64_i32; } } - gen_ldst(opc, tcgv_i32_temp(val), NULL, addr, oi); + gen_ldst(opc, TCG_TYPE_I32, tcgv_i32_temp(val), NULL, addr, oi); plugin_gen_mem_callbacks_i32(val, NULL, addr, orig_oi, QEMU_PLUGIN_MEM_W); if (swap) { @@ -590,7 +593,8 @@ static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr, } else { opc = INDEX_op_qemu_ld_a64_i128; } - gen_ldst(opc, tcgv_i64_temp(lo), tcgv_i64_temp(hi), addr, oi); + gen_ldst(opc, TCG_TYPE_I128, tcgv_i64_temp(lo), + tcgv_i64_temp(hi), addr, oi); if (need_bswap) { tcg_gen_bswap64_i64(lo, lo); @@ -710,7 +714,8 @@ static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr, } else { opc = INDEX_op_qemu_st_a64_i128; } - gen_ldst(opc, tcgv_i64_temp(lo), tcgv_i64_temp(hi), addr, oi); + gen_ldst(opc, TCG_TYPE_I128, tcgv_i64_temp(lo), + tcgv_i64_temp(hi), addr, oi); if (need_bswap) { tcg_temp_free_i64(lo); diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c index d4bb4aee74..893d68e7d8 100644 --- a/tcg/tcg-op-vec.c +++ b/tcg/tcg-op-vec.c @@ -23,6 +23,7 @@ #include "tcg/tcg-op-common.h" #include "tcg/tcg-mo.h" #include "tcg-internal.h" +#include "tcg-has.h" /* * Vector optional opcode tracking. @@ -143,7 +144,7 @@ bool tcg_can_emit_vecop_list(const TCGOpcode *list, void vec_gen_2(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a) { TCGOp *op = tcg_emit_op(opc, 2); - TCGOP_VECL(op) = type - TCG_TYPE_V64; + TCGOP_TYPE(op) = type; TCGOP_VECE(op) = vece; op->args[0] = r; op->args[1] = a; @@ -153,7 +154,7 @@ void vec_gen_3(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a, TCGArg b) { TCGOp *op = tcg_emit_op(opc, 3); - TCGOP_VECL(op) = type - TCG_TYPE_V64; + TCGOP_TYPE(op) = type; TCGOP_VECE(op) = vece; op->args[0] = r; op->args[1] = a; @@ -164,7 +165,7 @@ void vec_gen_4(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a, TCGArg b, TCGArg c) { TCGOp *op = tcg_emit_op(opc, 4); - TCGOP_VECL(op) = type - TCG_TYPE_V64; + TCGOP_TYPE(op) = type; TCGOP_VECE(op) = vece; op->args[0] = r; op->args[1] = a; @@ -176,7 +177,7 @@ void vec_gen_6(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a, TCGArg b, TCGArg c, TCGArg d, TCGArg e) { TCGOp *op = tcg_emit_op(opc, 6); - TCGOP_VECL(op) = type - TCG_TYPE_V64; + TCGOP_TYPE(op) = type; TCGOP_VECE(op) = vece; op->args[0] = r; op->args[1] = a; diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index 4a7e705367..fec6d678a2 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -29,7 +29,7 @@ #include "exec/translation-block.h" #include "exec/plugin-gen.h" #include "tcg-internal.h" - +#include "tcg-has.h" /* * Encourage the compiler to tail-call to a function, rather than inlining. @@ -37,34 +37,39 @@ */ #define NI __attribute__((noinline)) -TCGOp * NI tcg_gen_op1(TCGOpcode opc, TCGArg a1) +TCGOp * NI tcg_gen_op1(TCGOpcode opc, TCGType type, TCGArg a1) { TCGOp *op = tcg_emit_op(opc, 1); + TCGOP_TYPE(op) = type; op->args[0] = a1; return op; } -TCGOp * NI tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2) +TCGOp * NI tcg_gen_op2(TCGOpcode opc, TCGType type, TCGArg a1, TCGArg a2) { TCGOp *op = tcg_emit_op(opc, 2); + TCGOP_TYPE(op) = type; op->args[0] = a1; op->args[1] = a2; return op; } -TCGOp * NI tcg_gen_op3(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3) +TCGOp * NI tcg_gen_op3(TCGOpcode opc, TCGType type, TCGArg a1, + TCGArg a2, TCGArg a3) { TCGOp *op = tcg_emit_op(opc, 3); + TCGOP_TYPE(op) = type; op->args[0] = a1; op->args[1] = a2; op->args[2] = a3; return op; } -TCGOp * NI tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, +TCGOp * NI tcg_gen_op4(TCGOpcode opc, TCGType type, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4) { TCGOp *op = tcg_emit_op(opc, 4); + TCGOP_TYPE(op) = type; op->args[0] = a1; op->args[1] = a2; op->args[2] = a3; @@ -72,10 +77,11 @@ TCGOp * NI tcg_gen_op4(TCGOpcode opc, TCGArg a1, TCGArg a2, return op; } -TCGOp * NI tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, +TCGOp * NI tcg_gen_op5(TCGOpcode opc, TCGType type, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4, TCGArg a5) { TCGOp *op = tcg_emit_op(opc, 5); + TCGOP_TYPE(op) = type; op->args[0] = a1; op->args[1] = a2; op->args[2] = a3; @@ -84,10 +90,11 @@ TCGOp * NI tcg_gen_op5(TCGOpcode opc, TCGArg a1, TCGArg a2, return op; } -TCGOp * NI tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, - TCGArg a4, TCGArg a5, TCGArg a6) +TCGOp * NI tcg_gen_op6(TCGOpcode opc, TCGType type, TCGArg a1, TCGArg a2, + TCGArg a3, TCGArg a4, TCGArg a5, TCGArg a6) { TCGOp *op = tcg_emit_op(opc, 6); + TCGOP_TYPE(op) = type; op->args[0] = a1; op->args[1] = a2; op->args[2] = a3; @@ -107,132 +114,138 @@ TCGOp * NI tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, # define DNI #endif -static void DNI tcg_gen_op1_i32(TCGOpcode opc, TCGv_i32 a1) +static void DNI tcg_gen_op1_i32(TCGOpcode opc, TCGType type, TCGv_i32 a1) { - tcg_gen_op1(opc, tcgv_i32_arg(a1)); + tcg_gen_op1(opc, type, tcgv_i32_arg(a1)); } -static void DNI tcg_gen_op1_i64(TCGOpcode opc, TCGv_i64 a1) +static void DNI tcg_gen_op1_i64(TCGOpcode opc, TCGType type, TCGv_i64 a1) { - tcg_gen_op1(opc, tcgv_i64_arg(a1)); + tcg_gen_op1(opc, type, tcgv_i64_arg(a1)); } -static TCGOp * DNI tcg_gen_op1i(TCGOpcode opc, TCGArg a1) +static TCGOp * DNI tcg_gen_op1i(TCGOpcode opc, TCGType type, TCGArg a1) { - return tcg_gen_op1(opc, a1); + return tcg_gen_op1(opc, type, a1); } static void DNI tcg_gen_op2_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2) { - tcg_gen_op2(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2)); + tcg_gen_op2(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2)); } static void DNI tcg_gen_op2_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2) { - tcg_gen_op2(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2)); + tcg_gen_op2(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), tcgv_i64_arg(a2)); } static void DNI tcg_gen_op3_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGv_i32 a3) { - tcg_gen_op3(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3)); + tcg_gen_op3(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), + tcgv_i32_arg(a2), tcgv_i32_arg(a3)); } static void DNI tcg_gen_op3_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGv_i64 a3) { - tcg_gen_op3(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3)); + tcg_gen_op3(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), + tcgv_i64_arg(a2), tcgv_i64_arg(a3)); } static void DNI tcg_gen_op3i_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGArg a3) { - tcg_gen_op3(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), a3); + tcg_gen_op3(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2), a3); } static void DNI tcg_gen_op3i_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGArg a3) { - tcg_gen_op3(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), a3); + tcg_gen_op3(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), tcgv_i64_arg(a2), a3); } static void DNI tcg_gen_ldst_op_i32(TCGOpcode opc, TCGv_i32 val, TCGv_ptr base, TCGArg offset) { - tcg_gen_op3(opc, tcgv_i32_arg(val), tcgv_ptr_arg(base), offset); + tcg_gen_op3(opc, TCG_TYPE_I32, tcgv_i32_arg(val), + tcgv_ptr_arg(base), offset); } static void DNI tcg_gen_ldst_op_i64(TCGOpcode opc, TCGv_i64 val, TCGv_ptr base, TCGArg offset) { - tcg_gen_op3(opc, tcgv_i64_arg(val), tcgv_ptr_arg(base), offset); + tcg_gen_op3(opc, TCG_TYPE_I64, tcgv_i64_arg(val), + tcgv_ptr_arg(base), offset); } static void DNI tcg_gen_op4_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGv_i32 a3, TCGv_i32 a4) { - tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), + tcg_gen_op4(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3), tcgv_i32_arg(a4)); } static void DNI tcg_gen_op4_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGv_i64 a3, TCGv_i64 a4) { - tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), + tcg_gen_op4(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3), tcgv_i64_arg(a4)); } static void DNI tcg_gen_op4i_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGv_i32 a3, TCGArg a4) { - tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), + tcg_gen_op4(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3), a4); } static void DNI tcg_gen_op4i_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGv_i64 a3, TCGArg a4) { - tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), + tcg_gen_op4(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3), a4); } static TCGOp * DNI tcg_gen_op4ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGArg a3, TCGArg a4) { - return tcg_gen_op4(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), a3, a4); + return tcg_gen_op4(opc, TCG_TYPE_I32, + tcgv_i32_arg(a1), tcgv_i32_arg(a2), a3, a4); } static TCGOp * DNI tcg_gen_op4ii_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGArg a3, TCGArg a4) { - return tcg_gen_op4(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), a3, a4); + return tcg_gen_op4(opc, TCG_TYPE_I64, + tcgv_i64_arg(a1), tcgv_i64_arg(a2), a3, a4); } static void DNI tcg_gen_op5_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGv_i32 a3, TCGv_i32 a4, TCGv_i32 a5) { - tcg_gen_op5(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), + tcg_gen_op5(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5)); } static void DNI tcg_gen_op5_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGv_i64 a3, TCGv_i64 a4, TCGv_i64 a5) { - tcg_gen_op5(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), + tcg_gen_op5(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5)); } static void DNI tcg_gen_op5ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGv_i32 a3, TCGArg a4, TCGArg a5) { - tcg_gen_op5(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), + tcg_gen_op5(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3), a4, a5); } static void DNI tcg_gen_op5ii_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGv_i64 a3, TCGArg a4, TCGArg a5) { - tcg_gen_op5(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), + tcg_gen_op5(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3), a4, a5); } @@ -240,7 +253,7 @@ static void DNI tcg_gen_op6_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGv_i32 a3, TCGv_i32 a4, TCGv_i32 a5, TCGv_i32 a6) { - tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), + tcg_gen_op6(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5), tcgv_i32_arg(a6)); } @@ -249,7 +262,7 @@ static void DNI tcg_gen_op6_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGv_i64 a3, TCGv_i64 a4, TCGv_i64 a5, TCGv_i64 a6) { - tcg_gen_op6(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), + tcg_gen_op6(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5), tcgv_i64_arg(a6)); } @@ -258,7 +271,7 @@ static void DNI tcg_gen_op6i_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGv_i32 a3, TCGv_i32 a4, TCGv_i32 a5, TCGArg a6) { - tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), + tcg_gen_op6(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3), tcgv_i32_arg(a4), tcgv_i32_arg(a5), a6); } @@ -266,7 +279,7 @@ static void DNI tcg_gen_op6i_i64(TCGOpcode opc, TCGv_i64 a1, TCGv_i64 a2, TCGv_i64 a3, TCGv_i64 a4, TCGv_i64 a5, TCGArg a6) { - tcg_gen_op6(opc, tcgv_i64_arg(a1), tcgv_i64_arg(a2), + tcg_gen_op6(opc, TCG_TYPE_I64, tcgv_i64_arg(a1), tcgv_i64_arg(a2), tcgv_i64_arg(a3), tcgv_i64_arg(a4), tcgv_i64_arg(a5), a6); } @@ -274,7 +287,7 @@ static TCGOp * DNI tcg_gen_op6ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, TCGv_i32 a3, TCGv_i32 a4, TCGArg a5, TCGArg a6) { - return tcg_gen_op6(opc, tcgv_i32_arg(a1), tcgv_i32_arg(a2), + return tcg_gen_op6(opc, TCG_TYPE_I32, tcgv_i32_arg(a1), tcgv_i32_arg(a2), tcgv_i32_arg(a3), tcgv_i32_arg(a4), a5, a6); } @@ -283,7 +296,7 @@ static TCGOp * DNI tcg_gen_op6ii_i32(TCGOpcode opc, TCGv_i32 a1, TCGv_i32 a2, void gen_set_label(TCGLabel *l) { l->present = 1; - tcg_gen_op1(INDEX_op_set_label, label_arg(l)); + tcg_gen_op1(INDEX_op_set_label, 0, label_arg(l)); } static void add_as_label_use(TCGLabel *l, TCGOp *op) @@ -296,7 +309,7 @@ static void add_as_label_use(TCGLabel *l, TCGOp *op) void tcg_gen_br(TCGLabel *l) { - add_as_label_use(l, tcg_gen_op1(INDEX_op_br, label_arg(l))); + add_as_label_use(l, tcg_gen_op1(INDEX_op_br, 0, label_arg(l))); } void tcg_gen_mb(TCGBar mb_type) @@ -314,25 +327,25 @@ void tcg_gen_mb(TCGBar mb_type) #endif if (parallel) { - tcg_gen_op1(INDEX_op_mb, mb_type); + tcg_gen_op1(INDEX_op_mb, 0, mb_type); } } void tcg_gen_plugin_cb(unsigned from) { - tcg_gen_op1(INDEX_op_plugin_cb, from); + tcg_gen_op1(INDEX_op_plugin_cb, 0, from); } void tcg_gen_plugin_mem_cb(TCGv_i64 addr, unsigned meminfo) { - tcg_gen_op2(INDEX_op_plugin_mem_cb, tcgv_i64_arg(addr), meminfo); + tcg_gen_op2(INDEX_op_plugin_mem_cb, 0, tcgv_i64_arg(addr), meminfo); } /* 32 bit ops */ void tcg_gen_discard_i32(TCGv_i32 arg) { - tcg_gen_op1_i32(INDEX_op_discard, arg); + tcg_gen_op1_i32(INDEX_op_discard, TCG_TYPE_I32, arg); } void tcg_gen_mov_i32(TCGv_i32 ret, TCGv_i32 arg) @@ -893,7 +906,7 @@ void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2, tcg_gen_mov_i32(ret, arg2); return; } - if (TCG_TARGET_HAS_deposit_i32 && TCG_TARGET_deposit_i32_valid(ofs, len)) { + if (TCG_TARGET_deposit_valid(TCG_TYPE_I32, ofs, len)) { tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len); return; } @@ -938,8 +951,7 @@ void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg, tcg_gen_shli_i32(ret, arg, ofs); } else if (ofs == 0) { tcg_gen_andi_i32(ret, arg, (1u << len) - 1); - } else if (TCG_TARGET_HAS_deposit_i32 - && TCG_TARGET_deposit_i32_valid(ofs, len)) { + } else if (TCG_TARGET_deposit_valid(TCG_TYPE_I32, ofs, len)) { TCGv_i32 zero = tcg_constant_i32(0); tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, zero, arg, ofs, len); } else { @@ -1001,8 +1013,7 @@ void tcg_gen_extract_i32(TCGv_i32 ret, TCGv_i32 arg, return; } - if (TCG_TARGET_HAS_extract_i32 - && TCG_TARGET_extract_i32_valid(ofs, len)) { + if (TCG_TARGET_extract_valid(TCG_TYPE_I32, ofs, len)) { tcg_gen_op4ii_i32(INDEX_op_extract_i32, ret, arg, ofs, len); return; } @@ -1064,8 +1075,7 @@ void tcg_gen_sextract_i32(TCGv_i32 ret, TCGv_i32 arg, } } - if (TCG_TARGET_HAS_sextract_i32 - && TCG_TARGET_extract_i32_valid(ofs, len)) { + if (TCG_TARGET_sextract_valid(TCG_TYPE_I32, ofs, len)) { tcg_gen_op4ii_i32(INDEX_op_sextract_i32, ret, arg, ofs, len); return; } @@ -1467,7 +1477,7 @@ void tcg_gen_st_i32(TCGv_i32 arg1, TCGv_ptr arg2, tcg_target_long offset) void tcg_gen_discard_i64(TCGv_i64 arg) { if (TCG_TARGET_REG_BITS == 64) { - tcg_gen_op1_i64(INDEX_op_discard, arg); + tcg_gen_op1_i64(INDEX_op_discard, TCG_TYPE_I64, arg); } else { tcg_gen_discard_i32(TCGV_LOW(arg)); tcg_gen_discard_i32(TCGV_HIGH(arg)); @@ -2631,12 +2641,13 @@ void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2, tcg_gen_mov_i64(ret, arg2); return; } - if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(ofs, len)) { - tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len); - return; - } - if (TCG_TARGET_REG_BITS == 32) { + if (TCG_TARGET_REG_BITS == 64) { + if (TCG_TARGET_deposit_valid(TCG_TYPE_I64, ofs, len)) { + tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len); + return; + } + } else { if (ofs >= 32) { tcg_gen_deposit_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_LOW(arg2), ofs - 32, len); @@ -2691,8 +2702,8 @@ void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg, tcg_gen_shli_i64(ret, arg, ofs); } else if (ofs == 0) { tcg_gen_andi_i64(ret, arg, (1ull << len) - 1); - } else if (TCG_TARGET_HAS_deposit_i64 - && TCG_TARGET_deposit_i64_valid(ofs, len)) { + } else if (TCG_TARGET_REG_BITS == 64 && + TCG_TARGET_deposit_valid(TCG_TYPE_I64, ofs, len)) { TCGv_i64 zero = tcg_constant_i64(0); tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, zero, arg, ofs, len); } else { @@ -2798,8 +2809,7 @@ void tcg_gen_extract_i64(TCGv_i64 ret, TCGv_i64 arg, goto do_shift_and; } - if (TCG_TARGET_HAS_extract_i64 - && TCG_TARGET_extract_i64_valid(ofs, len)) { + if (TCG_TARGET_extract_valid(TCG_TYPE_I64, ofs, len)) { tcg_gen_op4ii_i64(INDEX_op_extract_i64, ret, arg, ofs, len); return; } @@ -2904,8 +2914,7 @@ void tcg_gen_sextract_i64(TCGv_i64 ret, TCGv_i64 arg, return; } - if (TCG_TARGET_HAS_sextract_i64 - && TCG_TARGET_extract_i64_valid(ofs, len)) { + if (TCG_TARGET_sextract_valid(TCG_TYPE_I64, ofs, len)) { tcg_gen_op4ii_i64(INDEX_op_sextract_i64, ret, arg, ofs, len); return; } @@ -3156,7 +3165,7 @@ void tcg_gen_extrl_i64_i32(TCGv_i32 ret, TCGv_i64 arg) if (TCG_TARGET_REG_BITS == 32) { tcg_gen_mov_i32(ret, TCGV_LOW(arg)); } else if (TCG_TARGET_HAS_extr_i64_i32) { - tcg_gen_op2(INDEX_op_extrl_i64_i32, + tcg_gen_op2(INDEX_op_extrl_i64_i32, TCG_TYPE_I32, tcgv_i32_arg(ret), tcgv_i64_arg(arg)); } else { tcg_gen_mov_i32(ret, (TCGv_i32)arg); @@ -3168,7 +3177,7 @@ void tcg_gen_extrh_i64_i32(TCGv_i32 ret, TCGv_i64 arg) if (TCG_TARGET_REG_BITS == 32) { tcg_gen_mov_i32(ret, TCGV_HIGH(arg)); } else if (TCG_TARGET_HAS_extr_i64_i32) { - tcg_gen_op2(INDEX_op_extrh_i64_i32, + tcg_gen_op2(INDEX_op_extrh_i64_i32, TCG_TYPE_I32, tcgv_i32_arg(ret), tcgv_i64_arg(arg)); } else { TCGv_i64 t = tcg_temp_ebb_new_i64(); @@ -3184,7 +3193,7 @@ void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg) tcg_gen_mov_i32(TCGV_LOW(ret), arg); tcg_gen_movi_i32(TCGV_HIGH(ret), 0); } else { - tcg_gen_op2(INDEX_op_extu_i32_i64, + tcg_gen_op2(INDEX_op_extu_i32_i64, TCG_TYPE_I64, tcgv_i64_arg(ret), tcgv_i32_arg(arg)); } } @@ -3195,7 +3204,7 @@ void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg) tcg_gen_mov_i32(TCGV_LOW(ret), arg); tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31); } else { - tcg_gen_op2(INDEX_op_ext_i32_i64, + tcg_gen_op2(INDEX_op_ext_i32_i64, TCG_TYPE_I64, tcgv_i64_arg(ret), tcgv_i32_arg(arg)); } } @@ -3217,7 +3226,7 @@ void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high) tcg_gen_extu_i32_i64(dest, low); /* If deposit is available, use it. Otherwise use the extra knowledge that we have of the zero-extensions above. */ - if (TCG_TARGET_HAS_deposit_i64 && TCG_TARGET_deposit_i64_valid(32, 32)) { + if (TCG_TARGET_deposit_valid(TCG_TYPE_I64, 32, 32)) { tcg_gen_deposit_i64(dest, dest, tmp, 32, 32); } else { tcg_gen_shli_i64(tmp, tmp, 32); @@ -3320,7 +3329,7 @@ void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx) tcg_debug_assert(idx == TB_EXIT_REQUESTED); } - tcg_gen_op1i(INDEX_op_exit_tb, val); + tcg_gen_op1i(INDEX_op_exit_tb, 0, val); } void tcg_gen_goto_tb(unsigned idx) @@ -3335,7 +3344,7 @@ void tcg_gen_goto_tb(unsigned idx) tcg_ctx->goto_tb_issue_mask |= 1 << idx; #endif plugin_gen_disable_mem_helpers(); - tcg_gen_op1i(INDEX_op_goto_tb, idx); + tcg_gen_op1i(INDEX_op_goto_tb, 0, idx); } void tcg_gen_lookup_and_goto_ptr(void) @@ -3350,6 +3359,6 @@ void tcg_gen_lookup_and_goto_ptr(void) plugin_gen_disable_mem_helpers(); ptr = tcg_temp_ebb_new_ptr(); gen_helper_lookup_tb_ptr(ptr, tcg_env); - tcg_gen_op1i(INDEX_op_goto_ptr, tcgv_ptr_arg(ptr)); + tcg_gen_op1i(INDEX_op_goto_ptr, TCG_TYPE_PTR, tcgv_ptr_arg(ptr)); tcg_temp_free_ptr(ptr); } diff --git a/tcg/tcg-pool.c.inc b/tcg/tcg-pool.c.inc deleted file mode 100644 index 90c2e63b7f..0000000000 --- a/tcg/tcg-pool.c.inc +++ /dev/null @@ -1,162 +0,0 @@ -/* - * TCG Backend Data: constant pool. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -typedef struct TCGLabelPoolData { - struct TCGLabelPoolData *next; - tcg_insn_unit *label; - intptr_t addend; - int rtype; - unsigned nlong; - tcg_target_ulong data[]; -} TCGLabelPoolData; - - -static TCGLabelPoolData *new_pool_alloc(TCGContext *s, int nlong, int rtype, - tcg_insn_unit *label, intptr_t addend) -{ - TCGLabelPoolData *n = tcg_malloc(sizeof(TCGLabelPoolData) - + sizeof(tcg_target_ulong) * nlong); - - n->label = label; - n->addend = addend; - n->rtype = rtype; - n->nlong = nlong; - return n; -} - -static void new_pool_insert(TCGContext *s, TCGLabelPoolData *n) -{ - TCGLabelPoolData *i, **pp; - int nlong = n->nlong; - - /* Insertion sort on the pool. */ - for (pp = &s->pool_labels; (i = *pp) != NULL; pp = &i->next) { - if (nlong > i->nlong) { - break; - } - if (nlong < i->nlong) { - continue; - } - if (memcmp(n->data, i->data, sizeof(tcg_target_ulong) * nlong) >= 0) { - break; - } - } - n->next = *pp; - *pp = n; -} - -/* The "usual" for generic integer code. */ -static inline void new_pool_label(TCGContext *s, tcg_target_ulong d, int rtype, - tcg_insn_unit *label, intptr_t addend) -{ - TCGLabelPoolData *n = new_pool_alloc(s, 1, rtype, label, addend); - n->data[0] = d; - new_pool_insert(s, n); -} - -/* For v64 or v128, depending on the host. */ -static inline void new_pool_l2(TCGContext *s, int rtype, tcg_insn_unit *label, - intptr_t addend, tcg_target_ulong d0, - tcg_target_ulong d1) -{ - TCGLabelPoolData *n = new_pool_alloc(s, 2, rtype, label, addend); - n->data[0] = d0; - n->data[1] = d1; - new_pool_insert(s, n); -} - -/* For v128 or v256, depending on the host. */ -static inline void new_pool_l4(TCGContext *s, int rtype, tcg_insn_unit *label, - intptr_t addend, tcg_target_ulong d0, - tcg_target_ulong d1, tcg_target_ulong d2, - tcg_target_ulong d3) -{ - TCGLabelPoolData *n = new_pool_alloc(s, 4, rtype, label, addend); - n->data[0] = d0; - n->data[1] = d1; - n->data[2] = d2; - n->data[3] = d3; - new_pool_insert(s, n); -} - -/* For v256, for 32-bit host. */ -static inline void new_pool_l8(TCGContext *s, int rtype, tcg_insn_unit *label, - intptr_t addend, tcg_target_ulong d0, - tcg_target_ulong d1, tcg_target_ulong d2, - tcg_target_ulong d3, tcg_target_ulong d4, - tcg_target_ulong d5, tcg_target_ulong d6, - tcg_target_ulong d7) -{ - TCGLabelPoolData *n = new_pool_alloc(s, 8, rtype, label, addend); - n->data[0] = d0; - n->data[1] = d1; - n->data[2] = d2; - n->data[3] = d3; - n->data[4] = d4; - n->data[5] = d5; - n->data[6] = d6; - n->data[7] = d7; - new_pool_insert(s, n); -} - -/* To be provided by cpu/tcg-target.c.inc. */ -static void tcg_out_nop_fill(tcg_insn_unit *p, int count); - -static int tcg_out_pool_finalize(TCGContext *s) -{ - TCGLabelPoolData *p = s->pool_labels; - TCGLabelPoolData *l = NULL; - void *a; - - if (p == NULL) { - return 0; - } - - /* ??? Round up to qemu_icache_linesize, but then do not round - again when allocating the next TranslationBlock structure. */ - a = (void *)ROUND_UP((uintptr_t)s->code_ptr, - sizeof(tcg_target_ulong) * p->nlong); - tcg_out_nop_fill(s->code_ptr, (tcg_insn_unit *)a - s->code_ptr); - s->data_gen_ptr = a; - - for (; p != NULL; p = p->next) { - size_t size = sizeof(tcg_target_ulong) * p->nlong; - uintptr_t value; - - if (!l || l->nlong != p->nlong || memcmp(l->data, p->data, size)) { - if (unlikely(a > s->code_gen_highwater)) { - return -1; - } - memcpy(a, p->data, size); - a += size; - l = p; - } - - value = (uintptr_t)tcg_splitwx_to_rx(a) - size; - if (!patch_reloc(p->label, p->rtype, value, p->addend)) { - return -2; - } - } - - s->code_ptr = a; - return 0; -} diff --git a/tcg/tcg.c b/tcg/tcg.c index 4578b185be..43b6712286 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -56,6 +56,7 @@ #include "tcg/tcg-temp-internal.h" #include "tcg-internal.h" #include "tcg/perf.h" +#include "tcg-has.h" #ifdef CONFIG_USER_ONLY #include "user/guest-base.h" #endif @@ -66,6 +67,11 @@ static void tcg_target_init(TCGContext *s); static void tcg_target_qemu_prologue(TCGContext *s); static bool patch_reloc(tcg_insn_unit *code_ptr, int type, intptr_t value, intptr_t addend); +static void tcg_out_nop_fill(tcg_insn_unit *p, int count); + +typedef struct TCGLabelQemuLdst TCGLabelQemuLdst; +static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l); +static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l); /* The CIE and FDE header definitions will be common to all hosts. */ typedef struct { @@ -90,7 +96,7 @@ typedef struct QEMU_PACKED { DebugFrameFDEHeader fde; } DebugFrameHeader; -typedef struct TCGLabelQemuLdst { +struct TCGLabelQemuLdst { bool is_ld; /* qemu_ld: true, qemu_st: false */ MemOpIdx oi; TCGType type; /* result type of a load */ @@ -101,7 +107,7 @@ typedef struct TCGLabelQemuLdst { const tcg_insn_unit *raddr; /* addr of the next IR of qemu_ld/st IR */ tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */ QSIMPLEQ_ENTRY(TCGLabelQemuLdst) next; -} TCGLabelQemuLdst; +}; static void tcg_register_jit_int(const void *buf, size_t size, const void *debug_frame, @@ -128,7 +134,7 @@ static void tcg_out_addi_ptr(TCGContext *s, TCGReg, TCGReg, tcg_target_long); static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2); static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg); static void tcg_out_goto_tb(TCGContext *s, int which); -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]); #if TCG_TARGET_MAYBE_vec @@ -165,6 +171,10 @@ static inline void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, { g_assert_not_reached(); } +int tcg_can_emit_vec_op(TCGOpcode o, TCGType t, unsigned ve) +{ + return 0; +} #endif static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, intptr_t arg2); @@ -175,9 +185,6 @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target, static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot); static bool tcg_target_const_match(int64_t val, int ct, TCGType type, TCGCond cond, int vece); -#ifdef TCG_TARGET_NEED_LDST_LABELS -static int tcg_out_ldst_finalize(TCGContext *s); -#endif #ifndef CONFIG_USER_ONLY #define guest_base ({ qemu_build_not_reached(); (uintptr_t)0; }) @@ -634,6 +641,197 @@ static void tcg_out_movext3(TCGContext *s, const TCGMovExtend *i1, } } +/* + * Allocate a new TCGLabelQemuLdst entry. + */ + +__attribute__((unused)) +static TCGLabelQemuLdst *new_ldst_label(TCGContext *s) +{ + TCGLabelQemuLdst *l = tcg_malloc(sizeof(*l)); + + memset(l, 0, sizeof(*l)); + QSIMPLEQ_INSERT_TAIL(&s->ldst_labels, l, next); + + return l; +} + +/* + * Allocate new constant pool entries. + */ + +typedef struct TCGLabelPoolData { + struct TCGLabelPoolData *next; + tcg_insn_unit *label; + intptr_t addend; + int rtype; + unsigned nlong; + tcg_target_ulong data[]; +} TCGLabelPoolData; + +static TCGLabelPoolData *new_pool_alloc(TCGContext *s, int nlong, int rtype, + tcg_insn_unit *label, intptr_t addend) +{ + TCGLabelPoolData *n = tcg_malloc(sizeof(TCGLabelPoolData) + + sizeof(tcg_target_ulong) * nlong); + + n->label = label; + n->addend = addend; + n->rtype = rtype; + n->nlong = nlong; + return n; +} + +static void new_pool_insert(TCGContext *s, TCGLabelPoolData *n) +{ + TCGLabelPoolData *i, **pp; + int nlong = n->nlong; + + /* Insertion sort on the pool. */ + for (pp = &s->pool_labels; (i = *pp) != NULL; pp = &i->next) { + if (nlong > i->nlong) { + break; + } + if (nlong < i->nlong) { + continue; + } + if (memcmp(n->data, i->data, sizeof(tcg_target_ulong) * nlong) >= 0) { + break; + } + } + n->next = *pp; + *pp = n; +} + +/* The "usual" for generic integer code. */ +__attribute__((unused)) +static void new_pool_label(TCGContext *s, tcg_target_ulong d, int rtype, + tcg_insn_unit *label, intptr_t addend) +{ + TCGLabelPoolData *n = new_pool_alloc(s, 1, rtype, label, addend); + n->data[0] = d; + new_pool_insert(s, n); +} + +/* For v64 or v128, depending on the host. */ +__attribute__((unused)) +static void new_pool_l2(TCGContext *s, int rtype, tcg_insn_unit *label, + intptr_t addend, tcg_target_ulong d0, + tcg_target_ulong d1) +{ + TCGLabelPoolData *n = new_pool_alloc(s, 2, rtype, label, addend); + n->data[0] = d0; + n->data[1] = d1; + new_pool_insert(s, n); +} + +/* For v128 or v256, depending on the host. */ +__attribute__((unused)) +static void new_pool_l4(TCGContext *s, int rtype, tcg_insn_unit *label, + intptr_t addend, tcg_target_ulong d0, + tcg_target_ulong d1, tcg_target_ulong d2, + tcg_target_ulong d3) +{ + TCGLabelPoolData *n = new_pool_alloc(s, 4, rtype, label, addend); + n->data[0] = d0; + n->data[1] = d1; + n->data[2] = d2; + n->data[3] = d3; + new_pool_insert(s, n); +} + +/* For v256, for 32-bit host. */ +__attribute__((unused)) +static void new_pool_l8(TCGContext *s, int rtype, tcg_insn_unit *label, + intptr_t addend, tcg_target_ulong d0, + tcg_target_ulong d1, tcg_target_ulong d2, + tcg_target_ulong d3, tcg_target_ulong d4, + tcg_target_ulong d5, tcg_target_ulong d6, + tcg_target_ulong d7) +{ + TCGLabelPoolData *n = new_pool_alloc(s, 8, rtype, label, addend); + n->data[0] = d0; + n->data[1] = d1; + n->data[2] = d2; + n->data[3] = d3; + n->data[4] = d4; + n->data[5] = d5; + n->data[6] = d6; + n->data[7] = d7; + new_pool_insert(s, n); +} + +/* + * Generate TB finalization at the end of block + */ + +static int tcg_out_ldst_finalize(TCGContext *s) +{ + TCGLabelQemuLdst *lb; + + /* qemu_ld/st slow paths */ + QSIMPLEQ_FOREACH(lb, &s->ldst_labels, next) { + if (lb->is_ld + ? !tcg_out_qemu_ld_slow_path(s, lb) + : !tcg_out_qemu_st_slow_path(s, lb)) { + return -2; + } + + /* + * Test for (pending) buffer overflow. The assumption is that any + * one operation beginning below the high water mark cannot overrun + * the buffer completely. Thus we can test for overflow after + * generating code without having to check during generation. + */ + if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) { + return -1; + } + } + return 0; +} + +static int tcg_out_pool_finalize(TCGContext *s) +{ + TCGLabelPoolData *p = s->pool_labels; + TCGLabelPoolData *l = NULL; + void *a; + + if (p == NULL) { + return 0; + } + + /* + * ??? Round up to qemu_icache_linesize, but then do not round + * again when allocating the next TranslationBlock structure. + */ + a = (void *)ROUND_UP((uintptr_t)s->code_ptr, + sizeof(tcg_target_ulong) * p->nlong); + tcg_out_nop_fill(s->code_ptr, (tcg_insn_unit *)a - s->code_ptr); + s->data_gen_ptr = a; + + for (; p != NULL; p = p->next) { + size_t size = sizeof(tcg_target_ulong) * p->nlong; + uintptr_t value; + + if (!l || l->nlong != p->nlong || memcmp(l->data, p->data, size)) { + if (unlikely(a > s->code_gen_highwater)) { + return -1; + } + memcpy(a, p->data, size); + a += size; + l = p; + } + + value = (uintptr_t)tcg_splitwx_to_rx(a) - size; + if (!patch_reloc(p->label, p->rtype, value, p->addend)) { + return -2; + } + } + + s->code_ptr = a; + return 0; +} + #define C_PFX1(P, A) P##A #define C_PFX2(P, A, B) P##A##_##B #define C_PFX3(P, A, B, C) P##A##_##B##_##C @@ -664,10 +862,11 @@ static void tcg_out_movext3(TCGContext *s, const TCGMovExtend *i1, #define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_n1_o1_i4_, O1, O2, I1, I2, I3, I4), typedef enum { + C_NotImplemented = -1, #include "tcg-target-con-set.h" } TCGConstraintSetIndex; -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode); +static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode, TCGType, unsigned); #undef C_O0_I1 #undef C_O0_I2 @@ -688,31 +887,35 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode); /* Put all of the constraint sets into an array, indexed by the enum. */ -#define C_O0_I1(I1) { .args_ct_str = { #I1 } }, -#define C_O0_I2(I1, I2) { .args_ct_str = { #I1, #I2 } }, -#define C_O0_I3(I1, I2, I3) { .args_ct_str = { #I1, #I2, #I3 } }, -#define C_O0_I4(I1, I2, I3, I4) { .args_ct_str = { #I1, #I2, #I3, #I4 } }, +typedef struct TCGConstraintSet { + uint8_t nb_oargs, nb_iargs; + const char *args_ct_str[TCG_MAX_OP_ARGS]; +} TCGConstraintSet; -#define C_O1_I1(O1, I1) { .args_ct_str = { #O1, #I1 } }, -#define C_O1_I2(O1, I1, I2) { .args_ct_str = { #O1, #I1, #I2 } }, -#define C_O1_I3(O1, I1, I2, I3) { .args_ct_str = { #O1, #I1, #I2, #I3 } }, -#define C_O1_I4(O1, I1, I2, I3, I4) { .args_ct_str = { #O1, #I1, #I2, #I3, #I4 } }, +#define C_O0_I1(I1) { 0, 1, { #I1 } }, +#define C_O0_I2(I1, I2) { 0, 2, { #I1, #I2 } }, +#define C_O0_I3(I1, I2, I3) { 0, 3, { #I1, #I2, #I3 } }, +#define C_O0_I4(I1, I2, I3, I4) { 0, 4, { #I1, #I2, #I3, #I4 } }, -#define C_N1_I2(O1, I1, I2) { .args_ct_str = { "&" #O1, #I1, #I2 } }, -#define C_N1O1_I1(O1, O2, I1) { .args_ct_str = { "&" #O1, #O2, #I1 } }, -#define C_N2_I1(O1, O2, I1) { .args_ct_str = { "&" #O1, "&" #O2, #I1 } }, +#define C_O1_I1(O1, I1) { 1, 1, { #O1, #I1 } }, +#define C_O1_I2(O1, I1, I2) { 1, 2, { #O1, #I1, #I2 } }, +#define C_O1_I3(O1, I1, I2, I3) { 1, 3, { #O1, #I1, #I2, #I3 } }, +#define C_O1_I4(O1, I1, I2, I3, I4) { 1, 4, { #O1, #I1, #I2, #I3, #I4 } }, -#define C_O2_I1(O1, O2, I1) { .args_ct_str = { #O1, #O2, #I1 } }, -#define C_O2_I2(O1, O2, I1, I2) { .args_ct_str = { #O1, #O2, #I1, #I2 } }, -#define C_O2_I3(O1, O2, I1, I2, I3) { .args_ct_str = { #O1, #O2, #I1, #I2, #I3 } }, -#define C_O2_I4(O1, O2, I1, I2, I3, I4) { .args_ct_str = { #O1, #O2, #I1, #I2, #I3, #I4 } }, -#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) { .args_ct_str = { "&" #O1, #O2, #I1, #I2, #I3, #I4 } }, +#define C_N1_I2(O1, I1, I2) { 1, 2, { "&" #O1, #I1, #I2 } }, +#define C_N1O1_I1(O1, O2, I1) { 2, 1, { "&" #O1, #O2, #I1 } }, +#define C_N2_I1(O1, O2, I1) { 2, 1, { "&" #O1, "&" #O2, #I1 } }, -static const TCGTargetOpDef constraint_sets[] = { +#define C_O2_I1(O1, O2, I1) { 2, 1, { #O1, #O2, #I1 } }, +#define C_O2_I2(O1, O2, I1, I2) { 2, 2, { #O1, #O2, #I1, #I2 } }, +#define C_O2_I3(O1, O2, I1, I2, I3) { 2, 3, { #O1, #O2, #I1, #I2, #I3 } }, +#define C_O2_I4(O1, O2, I1, I2, I3, I4) { 2, 4, { #O1, #O2, #I1, #I2, #I3, #I4 } }, +#define C_N1_O1_I4(O1, O2, I1, I2, I3, I4) { 2, 4, { "&" #O1, #O2, #I1, #I2, #I3, #I4 } }, + +static const TCGConstraintSet constraint_sets[] = { #include "tcg-target-con-set.h" }; - #undef C_O0_I1 #undef C_O0_I2 #undef C_O0_I3 @@ -1293,39 +1496,19 @@ static void init_call_layout(TCGHelperInfo *info) } static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)]; -static void process_op_defs(TCGContext *s); +static void process_constraint_sets(void); static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type, TCGReg reg, const char *name); static void tcg_context_init(unsigned max_cpus) { TCGContext *s = &tcg_init_ctx; - int op, total_args, n, i; - TCGOpDef *def; - TCGArgConstraint *args_ct; + int n, i; TCGTemp *ts; memset(s, 0, sizeof(*s)); s->nb_globals = 0; - /* Count total number of arguments and allocate the corresponding - space */ - total_args = 0; - for(op = 0; op < NB_OPS; op++) { - def = &tcg_op_defs[op]; - n = def->nb_iargs + def->nb_oargs; - total_args += n; - } - - args_ct = g_new0(TCGArgConstraint, total_args); - - for(op = 0; op < NB_OPS; op++) { - def = &tcg_op_defs[op]; - def->args_ct = args_ct; - n = def->nb_iargs + def->nb_oargs; - args_ct += n; - } - init_call_layout(&info_helper_ld32_mmu); init_call_layout(&info_helper_ld64_mmu); init_call_layout(&info_helper_ld128_mmu); @@ -1334,7 +1517,7 @@ static void tcg_context_init(unsigned max_cpus) init_call_layout(&info_helper_st128_mmu); tcg_target_init(s); - process_op_defs(s); + process_constraint_sets(); /* Reverse the order of the saved registers, assuming they're all at the start of tcg_target_reg_alloc_order. */ @@ -1931,12 +2114,34 @@ TCGTemp *tcgv_i32_temp(TCGv_i32 v) } #endif /* CONFIG_DEBUG_TCG */ -/* Return true if OP may appear in the opcode stream. - Test the runtime variable that controls each opcode. */ -bool tcg_op_supported(TCGOpcode op) +/* + * Return true if OP may appear in the opcode stream with TYPE. + * Test the runtime variable that controls each opcode. + */ +bool tcg_op_supported(TCGOpcode op, TCGType type, unsigned flags) { - const bool have_vec - = TCG_TARGET_HAS_v64 | TCG_TARGET_HAS_v128 | TCG_TARGET_HAS_v256; + bool has_type; + + switch (type) { + case TCG_TYPE_I32: + has_type = true; + break; + case TCG_TYPE_I64: + has_type = TCG_TARGET_REG_BITS == 64; + break; + case TCG_TYPE_V64: + has_type = TCG_TARGET_HAS_v64; + break; + case TCG_TYPE_V128: + has_type = TCG_TARGET_HAS_v128; + break; + case TCG_TYPE_V256: + has_type = TCG_TARGET_HAS_v256; + break; + default: + has_type = false; + break; + } switch (op) { case INDEX_op_discard: @@ -1990,6 +2195,9 @@ bool tcg_op_supported(TCGOpcode op) case INDEX_op_shl_i32: case INDEX_op_shr_i32: case INDEX_op_sar_i32: + case INDEX_op_extract_i32: + case INDEX_op_sextract_i32: + case INDEX_op_deposit_i32: return true; case INDEX_op_negsetcond_i32: @@ -2006,12 +2214,6 @@ bool tcg_op_supported(TCGOpcode op) case INDEX_op_rotl_i32: case INDEX_op_rotr_i32: return TCG_TARGET_HAS_rot_i32; - case INDEX_op_deposit_i32: - return TCG_TARGET_HAS_deposit_i32; - case INDEX_op_extract_i32: - return TCG_TARGET_HAS_extract_i32; - case INDEX_op_sextract_i32: - return TCG_TARGET_HAS_sextract_i32; case INDEX_op_extract2_i32: return TCG_TARGET_HAS_extract2_i32; case INDEX_op_add2_i32: @@ -2088,6 +2290,9 @@ bool tcg_op_supported(TCGOpcode op) case INDEX_op_sar_i64: case INDEX_op_ext_i32_i64: case INDEX_op_extu_i32_i64: + case INDEX_op_extract_i64: + case INDEX_op_sextract_i64: + case INDEX_op_deposit_i64: return TCG_TARGET_REG_BITS == 64; case INDEX_op_negsetcond_i64: @@ -2104,12 +2309,6 @@ bool tcg_op_supported(TCGOpcode op) case INDEX_op_rotl_i64: case INDEX_op_rotr_i64: return TCG_TARGET_HAS_rot_i64; - case INDEX_op_deposit_i64: - return TCG_TARGET_HAS_deposit_i64; - case INDEX_op_extract_i64: - return TCG_TARGET_HAS_extract_i64; - case INDEX_op_sextract_i64: - return TCG_TARGET_HAS_sextract_i64; case INDEX_op_extract2_i64: return TCG_TARGET_HAS_extract2_i64; case INDEX_op_extrl_i64_i32: @@ -2175,60 +2374,60 @@ bool tcg_op_supported(TCGOpcode op) case INDEX_op_or_vec: case INDEX_op_xor_vec: case INDEX_op_cmp_vec: - return have_vec; + return has_type; case INDEX_op_dup2_vec: - return have_vec && TCG_TARGET_REG_BITS == 32; + return has_type && TCG_TARGET_REG_BITS == 32; case INDEX_op_not_vec: - return have_vec && TCG_TARGET_HAS_not_vec; + return has_type && TCG_TARGET_HAS_not_vec; case INDEX_op_neg_vec: - return have_vec && TCG_TARGET_HAS_neg_vec; + return has_type && TCG_TARGET_HAS_neg_vec; case INDEX_op_abs_vec: - return have_vec && TCG_TARGET_HAS_abs_vec; + return has_type && TCG_TARGET_HAS_abs_vec; case INDEX_op_andc_vec: - return have_vec && TCG_TARGET_HAS_andc_vec; + return has_type && TCG_TARGET_HAS_andc_vec; case INDEX_op_orc_vec: - return have_vec && TCG_TARGET_HAS_orc_vec; + return has_type && TCG_TARGET_HAS_orc_vec; case INDEX_op_nand_vec: - return have_vec && TCG_TARGET_HAS_nand_vec; + return has_type && TCG_TARGET_HAS_nand_vec; case INDEX_op_nor_vec: - return have_vec && TCG_TARGET_HAS_nor_vec; + return has_type && TCG_TARGET_HAS_nor_vec; case INDEX_op_eqv_vec: - return have_vec && TCG_TARGET_HAS_eqv_vec; + return has_type && TCG_TARGET_HAS_eqv_vec; case INDEX_op_mul_vec: - return have_vec && TCG_TARGET_HAS_mul_vec; + return has_type && TCG_TARGET_HAS_mul_vec; case INDEX_op_shli_vec: case INDEX_op_shri_vec: case INDEX_op_sari_vec: - return have_vec && TCG_TARGET_HAS_shi_vec; + return has_type && TCG_TARGET_HAS_shi_vec; case INDEX_op_shls_vec: case INDEX_op_shrs_vec: case INDEX_op_sars_vec: - return have_vec && TCG_TARGET_HAS_shs_vec; + return has_type && TCG_TARGET_HAS_shs_vec; case INDEX_op_shlv_vec: case INDEX_op_shrv_vec: case INDEX_op_sarv_vec: - return have_vec && TCG_TARGET_HAS_shv_vec; + return has_type && TCG_TARGET_HAS_shv_vec; case INDEX_op_rotli_vec: - return have_vec && TCG_TARGET_HAS_roti_vec; + return has_type && TCG_TARGET_HAS_roti_vec; case INDEX_op_rotls_vec: - return have_vec && TCG_TARGET_HAS_rots_vec; + return has_type && TCG_TARGET_HAS_rots_vec; case INDEX_op_rotlv_vec: case INDEX_op_rotrv_vec: - return have_vec && TCG_TARGET_HAS_rotv_vec; + return has_type && TCG_TARGET_HAS_rotv_vec; case INDEX_op_ssadd_vec: case INDEX_op_usadd_vec: case INDEX_op_sssub_vec: case INDEX_op_ussub_vec: - return have_vec && TCG_TARGET_HAS_sat_vec; + return has_type && TCG_TARGET_HAS_sat_vec; case INDEX_op_smin_vec: case INDEX_op_umin_vec: case INDEX_op_smax_vec: case INDEX_op_umax_vec: - return have_vec && TCG_TARGET_HAS_minmax_vec; + return has_type && TCG_TARGET_HAS_minmax_vec; case INDEX_op_bitsel_vec: - return have_vec && TCG_TARGET_HAS_bitsel_vec; + return has_type && TCG_TARGET_HAS_bitsel_vec; case INDEX_op_cmpsel_vec: - return have_vec && TCG_TARGET_HAS_cmpsel_vec; + return has_type && TCG_TARGET_HAS_cmpsel_vec; default: tcg_debug_assert(op > INDEX_op_last_generic && op < NB_OPS); @@ -2236,6 +2435,20 @@ bool tcg_op_supported(TCGOpcode op) } } +bool tcg_op_deposit_valid(TCGType type, unsigned ofs, unsigned len) +{ + unsigned width; + + tcg_debug_assert(type == TCG_TYPE_I32 || type == TCG_TYPE_I64); + width = (type == TCG_TYPE_I32 ? 32 : 64); + + tcg_debug_assert(ofs < width); + tcg_debug_assert(len > 0); + tcg_debug_assert(len <= width - ofs); + + return TCG_TARGET_deposit_valid(type, ofs, len); +} + static TCGOp *tcg_op_alloc(TCGOpcode opc, unsigned nargs); static void tcg_gen_callN(void *func, TCGHelperInfo *info, @@ -2616,7 +2829,8 @@ void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs) nb_cargs = def->nb_cargs; if (def->flags & TCG_OPF_VECTOR) { - col += ne_fprintf(f, "v%d,e%d,", 64 << TCGOP_VECL(op), + col += ne_fprintf(f, "v%d,e%d,", + 8 * tcg_type_size(TCGOP_TYPE(op)), 8 << TCGOP_VECE(op)); } @@ -2889,10 +3103,12 @@ void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs) } /* we give more priority to constraints with less registers */ -static int get_constraint_priority(const TCGOpDef *def, int k) +static int get_constraint_priority(const TCGArgConstraint *arg_ct, int k) { - const TCGArgConstraint *arg_ct = &def->args_ct[k]; - int n = ctpop64(arg_ct->regs); + int n; + + arg_ct += k; + n = ctpop64(arg_ct->regs); /* * Sort constraints of a single register first, which includes output @@ -2921,10 +3137,9 @@ static int get_constraint_priority(const TCGOpDef *def, int k) } /* sort from highest priority to lowest */ -static void sort_constraints(TCGOpDef *def, int start, int n) +static void sort_constraints(TCGArgConstraint *a, int start, int n) { int i, j; - TCGArgConstraint *a = def->args_ct; for (i = 0; i < n; i++) { a[start + i].sort_index = start + i; @@ -2934,8 +3149,8 @@ static void sort_constraints(TCGOpDef *def, int start, int n) } for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { - int p1 = get_constraint_priority(def, a[start + i].sort_index); - int p2 = get_constraint_priority(def, a[start + j].sort_index); + int p1 = get_constraint_priority(a, a[start + i].sort_index); + int p2 = get_constraint_priority(a, a[start + j].sort_index); if (p1 < p2) { int tmp = a[start + i].sort_index; a[start + i].sort_index = a[start + j].sort_index; @@ -2945,56 +3160,39 @@ static void sort_constraints(TCGOpDef *def, int start, int n) } } -static void process_op_defs(TCGContext *s) -{ - TCGOpcode op; +static const TCGArgConstraint empty_cts[TCG_MAX_OP_ARGS]; +static TCGArgConstraint all_cts[ARRAY_SIZE(constraint_sets)][TCG_MAX_OP_ARGS]; - for (op = 0; op < NB_OPS; op++) { - TCGOpDef *def = &tcg_op_defs[op]; - const TCGTargetOpDef *tdefs; +static void process_constraint_sets(void) +{ + for (size_t c = 0; c < ARRAY_SIZE(constraint_sets); ++c) { + const TCGConstraintSet *tdefs = &constraint_sets[c]; + TCGArgConstraint *args_ct = all_cts[c]; + int nb_oargs = tdefs->nb_oargs; + int nb_iargs = tdefs->nb_iargs; + int nb_args = nb_oargs + nb_iargs; bool saw_alias_pair = false; - int i, o, i2, o2, nb_args; - if (def->flags & TCG_OPF_NOT_PRESENT) { - continue; - } - - nb_args = def->nb_iargs + def->nb_oargs; - if (nb_args == 0) { - continue; - } - - /* - * Macro magic should make it impossible, but double-check that - * the array index is in range. Since the signness of an enum - * is implementation defined, force the result to unsigned. - */ - unsigned con_set = tcg_target_op_def(op); - tcg_debug_assert(con_set < ARRAY_SIZE(constraint_sets)); - tdefs = &constraint_sets[con_set]; - - for (i = 0; i < nb_args; i++) { + for (int i = 0; i < nb_args; i++) { const char *ct_str = tdefs->args_ct_str[i]; - bool input_p = i >= def->nb_oargs; - - /* Incomplete TCGTargetOpDef entry. */ - tcg_debug_assert(ct_str != NULL); + bool input_p = i >= nb_oargs; + int o; switch (*ct_str) { case '0' ... '9': o = *ct_str - '0'; tcg_debug_assert(input_p); - tcg_debug_assert(o < def->nb_oargs); - tcg_debug_assert(def->args_ct[o].regs != 0); - tcg_debug_assert(!def->args_ct[o].oalias); - def->args_ct[i] = def->args_ct[o]; + tcg_debug_assert(o < nb_oargs); + tcg_debug_assert(args_ct[o].regs != 0); + tcg_debug_assert(!args_ct[o].oalias); + args_ct[i] = args_ct[o]; /* The output sets oalias. */ - def->args_ct[o].oalias = 1; - def->args_ct[o].alias_index = i; + args_ct[o].oalias = 1; + args_ct[o].alias_index = i; /* The input sets ialias. */ - def->args_ct[i].ialias = 1; - def->args_ct[i].alias_index = o; - if (def->args_ct[i].pair) { + args_ct[i].ialias = 1; + args_ct[i].alias_index = o; + if (args_ct[i].pair) { saw_alias_pair = true; } tcg_debug_assert(ct_str[1] == '\0'); @@ -3002,41 +3200,41 @@ static void process_op_defs(TCGContext *s) case '&': tcg_debug_assert(!input_p); - def->args_ct[i].newreg = true; + args_ct[i].newreg = true; ct_str++; break; case 'p': /* plus */ /* Allocate to the register after the previous. */ - tcg_debug_assert(i > (input_p ? def->nb_oargs : 0)); + tcg_debug_assert(i > (input_p ? nb_oargs : 0)); o = i - 1; - tcg_debug_assert(!def->args_ct[o].pair); - tcg_debug_assert(!def->args_ct[o].ct); - def->args_ct[i] = (TCGArgConstraint){ + tcg_debug_assert(!args_ct[o].pair); + tcg_debug_assert(!args_ct[o].ct); + args_ct[i] = (TCGArgConstraint){ .pair = 2, .pair_index = o, - .regs = def->args_ct[o].regs << 1, - .newreg = def->args_ct[o].newreg, + .regs = args_ct[o].regs << 1, + .newreg = args_ct[o].newreg, }; - def->args_ct[o].pair = 1; - def->args_ct[o].pair_index = i; + args_ct[o].pair = 1; + args_ct[o].pair_index = i; tcg_debug_assert(ct_str[1] == '\0'); continue; case 'm': /* minus */ /* Allocate to the register before the previous. */ - tcg_debug_assert(i > (input_p ? def->nb_oargs : 0)); + tcg_debug_assert(i > (input_p ? nb_oargs : 0)); o = i - 1; - tcg_debug_assert(!def->args_ct[o].pair); - tcg_debug_assert(!def->args_ct[o].ct); - def->args_ct[i] = (TCGArgConstraint){ + tcg_debug_assert(!args_ct[o].pair); + tcg_debug_assert(!args_ct[o].ct); + args_ct[i] = (TCGArgConstraint){ .pair = 1, .pair_index = o, - .regs = def->args_ct[o].regs >> 1, - .newreg = def->args_ct[o].newreg, + .regs = args_ct[o].regs >> 1, + .newreg = args_ct[o].newreg, }; - def->args_ct[o].pair = 2; - def->args_ct[o].pair_index = i; + args_ct[o].pair = 2; + args_ct[o].pair_index = i; tcg_debug_assert(ct_str[1] == '\0'); continue; } @@ -3044,16 +3242,16 @@ static void process_op_defs(TCGContext *s) do { switch (*ct_str) { case 'i': - def->args_ct[i].ct |= TCG_CT_CONST; + args_ct[i].ct |= TCG_CT_CONST; break; /* Include all of the target-specific constraints. */ #undef CONST #define CONST(CASE, MASK) \ - case CASE: def->args_ct[i].ct |= MASK; break; + case CASE: args_ct[i].ct |= MASK; break; #define REGS(CASE, MASK) \ - case CASE: def->args_ct[i].regs |= MASK; break; + case CASE: args_ct[i].regs |= MASK; break; #include "tcg-target-con-str.h" @@ -3064,15 +3262,12 @@ static void process_op_defs(TCGContext *s) case '&': case 'p': case 'm': - /* Typo in TCGTargetOpDef constraint. */ + /* Typo in TCGConstraintSet constraint. */ g_assert_not_reached(); } } while (*++ct_str != '\0'); } - /* TCGTargetOpDef entry with too much information? */ - tcg_debug_assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL); - /* * Fix up output pairs that are aliased with inputs. * When we created the alias, we copied pair from the output. @@ -3093,51 +3288,53 @@ static void process_op_defs(TCGContext *s) * first output to pair=3, and the pair_index'es to match. */ if (saw_alias_pair) { - for (i = def->nb_oargs; i < nb_args; i++) { + for (int i = nb_oargs; i < nb_args; i++) { + int o, o2, i2; + /* * Since [0-9pm] must be alone in the constraint string, * the only way they can both be set is if the pair comes * from the output alias. */ - if (!def->args_ct[i].ialias) { + if (!args_ct[i].ialias) { continue; } - switch (def->args_ct[i].pair) { + switch (args_ct[i].pair) { case 0: break; case 1: - o = def->args_ct[i].alias_index; - o2 = def->args_ct[o].pair_index; - tcg_debug_assert(def->args_ct[o].pair == 1); - tcg_debug_assert(def->args_ct[o2].pair == 2); - if (def->args_ct[o2].oalias) { + o = args_ct[i].alias_index; + o2 = args_ct[o].pair_index; + tcg_debug_assert(args_ct[o].pair == 1); + tcg_debug_assert(args_ct[o2].pair == 2); + if (args_ct[o2].oalias) { /* Case 1a */ - i2 = def->args_ct[o2].alias_index; - tcg_debug_assert(def->args_ct[i2].pair == 2); - def->args_ct[i2].pair_index = i; - def->args_ct[i].pair_index = i2; + i2 = args_ct[o2].alias_index; + tcg_debug_assert(args_ct[i2].pair == 2); + args_ct[i2].pair_index = i; + args_ct[i].pair_index = i2; } else { /* Case 1b */ - def->args_ct[i].pair_index = i; + args_ct[i].pair_index = i; } break; case 2: - o = def->args_ct[i].alias_index; - o2 = def->args_ct[o].pair_index; - tcg_debug_assert(def->args_ct[o].pair == 2); - tcg_debug_assert(def->args_ct[o2].pair == 1); - if (def->args_ct[o2].oalias) { + o = args_ct[i].alias_index; + o2 = args_ct[o].pair_index; + tcg_debug_assert(args_ct[o].pair == 2); + tcg_debug_assert(args_ct[o2].pair == 1); + if (args_ct[o2].oalias) { /* Case 1a */ - i2 = def->args_ct[o2].alias_index; - tcg_debug_assert(def->args_ct[i2].pair == 1); - def->args_ct[i2].pair_index = i; - def->args_ct[i].pair_index = i2; + i2 = args_ct[o2].alias_index; + tcg_debug_assert(args_ct[i2].pair == 1); + args_ct[i2].pair_index = i; + args_ct[i].pair_index = i2; } else { /* Case 2 */ - def->args_ct[i].pair = 3; - def->args_ct[o2].pair = 3; - def->args_ct[i].pair_index = o2; - def->args_ct[o2].pair_index = i; + args_ct[i].pair = 3; + args_ct[o2].pair = 3; + args_ct[i].pair_index = o2; + args_ct[o2].pair_index = i; } break; default: @@ -3147,9 +3344,32 @@ static void process_op_defs(TCGContext *s) } /* sort the constraints (XXX: this is just an heuristic) */ - sort_constraints(def, 0, def->nb_oargs); - sort_constraints(def, def->nb_oargs, def->nb_iargs); + sort_constraints(args_ct, 0, nb_oargs); + sort_constraints(args_ct, nb_oargs, nb_iargs); + } +} + +static const TCGArgConstraint *opcode_args_ct(const TCGOp *op) +{ + const TCGOpDef *def = &tcg_op_defs[op->opc]; + TCGConstraintSetIndex con_set; + +#ifdef CONFIG_DEBUG_TCG + assert(tcg_op_supported(op->opc, TCGOP_TYPE(op), TCGOP_FLAGS(op))); +#endif + + if (def->flags & TCG_OPF_NOT_PRESENT) { + return empty_cts; } + + con_set = tcg_target_op_def(op->opc, TCGOP_TYPE(op), TCGOP_FLAGS(op)); + tcg_debug_assert(con_set >= 0 && con_set < ARRAY_SIZE(constraint_sets)); + + /* The constraint arguments must match TCGOpcode arguments. */ + tcg_debug_assert(constraint_sets[con_set].nb_oargs == def->nb_oargs); + tcg_debug_assert(constraint_sets[con_set].nb_iargs == def->nb_iargs); + + return all_cts[con_set]; } static void remove_label_use(TCGOp *op, int idx) @@ -3248,6 +3468,8 @@ TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *old_op, TCGOpcode opc, unsigned nargs) { TCGOp *new_op = tcg_op_alloc(opc, nargs); + + TCGOP_TYPE(new_op) = TCGOP_TYPE(old_op); QTAILQ_INSERT_BEFORE(old_op, new_op, link); return new_op; } @@ -3256,6 +3478,8 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op, TCGOpcode opc, unsigned nargs) { TCGOp *new_op = tcg_op_alloc(opc, nargs); + + TCGOP_TYPE(new_op) = TCGOP_TYPE(old_op); QTAILQ_INSERT_AFTER(&s->ops, old_op, new_op, link); return new_op; } @@ -3618,6 +3842,7 @@ liveness_pass_1(TCGContext *s) TCGTemp *ts; TCGOpcode opc = op->opc; const TCGOpDef *def = &tcg_op_defs[opc]; + const TCGArgConstraint *args_ct; switch (opc) { case INDEX_op_call: @@ -3907,8 +4132,9 @@ liveness_pass_1(TCGContext *s) break; default: + args_ct = opcode_args_ct(op); for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) { - const TCGArgConstraint *ct = &def->args_ct[i]; + const TCGArgConstraint *ct = &args_ct[i]; TCGRegSet set, *pset; ts = arg_temp(op->args[i]); @@ -4695,6 +4921,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op) { const TCGLifeData arg_life = op->life; TCGRegSet dup_out_regs, dup_in_regs; + const TCGArgConstraint *dup_args_ct; TCGTemp *its, *ots; TCGType itype, vtype; unsigned vece; @@ -4709,7 +4936,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op) itype = its->type; vece = TCGOP_VECE(op); - vtype = TCGOP_VECL(op) + TCG_TYPE_V64; + vtype = TCGOP_TYPE(op); if (its->val_type == TEMP_VAL_CONST) { /* Propagate constant via movi -> dupi. */ @@ -4721,8 +4948,9 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op) return; } - dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].regs; - dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].regs; + dup_args_ct = opcode_args_ct(op); + dup_out_regs = dup_args_ct[0].regs; + dup_in_regs = dup_args_ct[1].regs; /* Allocate the output register now. */ if (ots->val_type != TEMP_VAL_REG) { @@ -4808,6 +5036,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) int i, k, nb_iargs, nb_oargs; TCGReg reg; TCGArg arg; + const TCGArgConstraint *args_ct; const TCGArgConstraint *arg_ct; TCGTemp *ts; TCGArg new_args[TCG_MAX_OP_ARGS]; @@ -4852,6 +5081,8 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) break; } + args_ct = opcode_args_ct(op); + /* satisfy input constraints */ for (k = 0; k < nb_iargs; k++) { TCGRegSet i_preferred_regs, i_required_regs; @@ -4859,9 +5090,9 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) TCGTemp *ts2; int i1, i2; - i = def->args_ct[nb_oargs + k].sort_index; + i = args_ct[nb_oargs + k].sort_index; arg = op->args[i]; - arg_ct = &def->args_ct[i]; + arg_ct = &args_ct[i]; ts = arg_temp(arg); if (ts->val_type == TEMP_VAL_CONST @@ -4891,7 +5122,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) * register and move it. */ if (temp_readonly(ts) || !IS_DEAD_ARG(i) - || def->args_ct[arg_ct->alias_index].newreg) { + || args_ct[arg_ct->alias_index].newreg) { allocate_new_reg = true; } else if (ts->val_type == TEMP_VAL_REG) { /* @@ -5076,10 +5307,10 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) } /* satisfy the output constraints */ - for(k = 0; k < nb_oargs; k++) { - i = def->args_ct[k].sort_index; + for (k = 0; k < nb_oargs; k++) { + i = args_ct[k].sort_index; arg = op->args[i]; - arg_ct = &def->args_ct[i]; + arg_ct = &args_ct[i]; ts = arg_temp(arg); /* ENV should not be modified. */ @@ -5176,10 +5407,10 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) break; default: if (def->flags & TCG_OPF_VECTOR) { - tcg_out_vec_op(s, op->opc, TCGOP_VECL(op), TCGOP_VECE(op), - new_args, const_args); + tcg_out_vec_op(s, op->opc, TCGOP_TYPE(op) - TCG_TYPE_V64, + TCGOP_VECE(op), new_args, const_args); } else { - tcg_out_op(s, op->opc, new_args, const_args); + tcg_out_op(s, op->opc, TCGOP_TYPE(op), new_args, const_args); } break; } @@ -5203,7 +5434,7 @@ static bool tcg_reg_alloc_dup2(TCGContext *s, const TCGOp *op) { const TCGLifeData arg_life = op->life; TCGTemp *ots, *itsl, *itsh; - TCGType vtype = TCGOP_VECL(op) + TCG_TYPE_V64; + TCGType vtype = TCGOP_TYPE(op); /* This opcode is only valid for 32-bit hosts, for 64-bit elements. */ tcg_debug_assert(TCG_TARGET_REG_BITS == 32); @@ -5219,8 +5450,7 @@ static bool tcg_reg_alloc_dup2(TCGContext *s, const TCGOp *op) /* Allocate the output register now. */ if (ots->val_type != TEMP_VAL_REG) { TCGRegSet allocated_regs = s->reserved_regs; - TCGRegSet dup_out_regs = - tcg_op_defs[INDEX_op_dup_vec].args_ct[0].regs; + TCGRegSet dup_out_regs = opcode_args_ct(op)[0].regs; TCGReg oreg; /* Make sure to not spill the input registers. */ @@ -6176,12 +6406,8 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) s->code_ptr = s->code_buf; s->data_gen_ptr = NULL; -#ifdef TCG_TARGET_NEED_LDST_LABELS QSIMPLEQ_INIT(&s->ldst_labels); -#endif -#ifdef TCG_TARGET_NEED_POOL_LABELS s->pool_labels = NULL; -#endif start_words = s->insn_start_words; s->gen_insn_data = @@ -6238,7 +6464,8 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) /* fall through */ default: /* Sanity check that we've not introduced any unhandled opcodes. */ - tcg_debug_assert(tcg_op_supported(opc)); + tcg_debug_assert(tcg_op_supported(opc, TCGOP_TYPE(op), + TCGOP_FLAGS(op))); /* Note: in order to speed up the code, it would be much faster to have specialized register allocator functions for some common argument patterns */ @@ -6261,18 +6488,14 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start) s->gen_insn_end_off[num_insns] = tcg_current_code_size(s); /* Generate TB finalization at the end of block */ -#ifdef TCG_TARGET_NEED_LDST_LABELS i = tcg_out_ldst_finalize(s); if (i < 0) { return i; } -#endif -#ifdef TCG_TARGET_NEED_POOL_LABELS i = tcg_out_pool_finalize(s); if (i < 0) { return i; } -#endif if (!tcg_resolve_relocs(s)) { return -2; } diff --git a/tcg/tci.c b/tcg/tci.c index 3eb95e20b6..8c1c53424d 100644 --- a/tcg/tci.c +++ b/tcg/tci.c @@ -22,6 +22,7 @@ #include "tcg/helper-info.h" #include "tcg/tcg-ldst.h" #include "disas/dis-asm.h" +#include "tcg-has.h" #include <ffi.h> @@ -650,24 +651,18 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, regs[r0] = ror32(regs[r1], regs[r2] & 31); break; #endif -#if TCG_TARGET_HAS_deposit_i32 case INDEX_op_deposit_i32: tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len); regs[r0] = deposit32(regs[r1], pos, len, regs[r2]); break; -#endif -#if TCG_TARGET_HAS_extract_i32 case INDEX_op_extract_i32: tci_args_rrbb(insn, &r0, &r1, &pos, &len); regs[r0] = extract32(regs[r1], pos, len); break; -#endif -#if TCG_TARGET_HAS_sextract_i32 case INDEX_op_sextract_i32: tci_args_rrbb(insn, &r0, &r1, &pos, &len); regs[r0] = sextract32(regs[r1], pos, len); break; -#endif case INDEX_op_brcond_i32: tci_args_rl(insn, tb_ptr, &r0, &ptr); if ((uint32_t)regs[r0]) { @@ -861,24 +856,18 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env, regs[r0] = ror64(regs[r1], regs[r2] & 63); break; #endif -#if TCG_TARGET_HAS_deposit_i64 case INDEX_op_deposit_i64: tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len); regs[r0] = deposit64(regs[r1], pos, len, regs[r2]); break; -#endif -#if TCG_TARGET_HAS_extract_i64 case INDEX_op_extract_i64: tci_args_rrbb(insn, &r0, &r1, &pos, &len); regs[r0] = extract64(regs[r1], pos, len); break; -#endif -#if TCG_TARGET_HAS_sextract_i64 case INDEX_op_sextract_i64: tci_args_rrbb(insn, &r0, &r1, &pos, &len); regs[r0] = sextract64(regs[r1], pos, len); break; -#endif case INDEX_op_brcond_i64: tci_args_rl(insn, tb_ptr, &r0, &ptr); if (regs[r0]) { diff --git a/tcg/tci/tcg-target-has.h b/tcg/tci/tcg-target-has.h new file mode 100644 index 0000000000..c8785ca8dc --- /dev/null +++ b/tcg/tci/tcg-target-has.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific opcode support + * Copyright (c) 2009, 2011 Stefan Weil + */ + +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 +#define TCG_TARGET_HAS_andc_i32 1 +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_eqv_i32 1 +#define TCG_TARGET_HAS_nand_i32 1 +#define TCG_TARGET_HAS_nor_i32 1 +#define TCG_TARGET_HAS_clz_i32 1 +#define TCG_TARGET_HAS_ctz_i32 1 +#define TCG_TARGET_HAS_ctpop_i32 1 +#define TCG_TARGET_HAS_not_i32 1 +#define TCG_TARGET_HAS_orc_i32 1 +#define TCG_TARGET_HAS_rot_i32 1 +#define TCG_TARGET_HAS_negsetcond_i32 0 +#define TCG_TARGET_HAS_muls2_i32 1 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +#if TCG_TARGET_REG_BITS == 64 +#define TCG_TARGET_HAS_extr_i64_i32 0 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 1 +#define TCG_TARGET_HAS_ext16u_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 +#define TCG_TARGET_HAS_andc_i64 1 +#define TCG_TARGET_HAS_eqv_i64 1 +#define TCG_TARGET_HAS_nand_i64 1 +#define TCG_TARGET_HAS_nor_i64 1 +#define TCG_TARGET_HAS_clz_i64 1 +#define TCG_TARGET_HAS_ctz_i64 1 +#define TCG_TARGET_HAS_ctpop_i64 1 +#define TCG_TARGET_HAS_not_i64 1 +#define TCG_TARGET_HAS_orc_i64 1 +#define TCG_TARGET_HAS_rot_i64 1 +#define TCG_TARGET_HAS_negsetcond_i64 0 +#define TCG_TARGET_HAS_muls2_i64 1 +#define TCG_TARGET_HAS_add2_i32 1 +#define TCG_TARGET_HAS_sub2_i32 1 +#define TCG_TARGET_HAS_mulu2_i32 1 +#define TCG_TARGET_HAS_add2_i64 1 +#define TCG_TARGET_HAS_sub2_i64 1 +#define TCG_TARGET_HAS_mulu2_i64 1 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 +#else +#define TCG_TARGET_HAS_mulu2_i32 1 +#endif /* TCG_TARGET_REG_BITS == 64 */ + +#define TCG_TARGET_HAS_qemu_ldst_i128 0 + +#define TCG_TARGET_HAS_tst 1 + +#define TCG_TARGET_extract_valid(type, ofs, len) 1 +#define TCG_TARGET_sextract_valid(type, ofs, len) 1 +#define TCG_TARGET_deposit_valid(type, ofs, len) 1 + +#endif diff --git a/tcg/tci/tcg-target-mo.h b/tcg/tci/tcg-target-mo.h new file mode 100644 index 0000000000..779872e39a --- /dev/null +++ b/tcg/tci/tcg-target-mo.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define target-specific memory model + * Copyright (c) 2009, 2011 Stefan Weil + */ + +#ifndef TCG_TARGET_MO_H +#define TCG_TARGET_MO_H + +/* + * We could notice __i386__ or __s390x__ and reduce the barriers depending + * on the host. But if you want performance, you use the normal backend. + * We prefer consistency across hosts on this. + */ +#define TCG_TARGET_DEFAULT_MO 0 + +#endif diff --git a/tcg/tci/tcg-target-opc.h.inc b/tcg/tci/tcg-target-opc.h.inc new file mode 100644 index 0000000000..ecc8c4e55e --- /dev/null +++ b/tcg/tci/tcg-target-opc.h.inc @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: MIT */ +/* These opcodes for use between the tci generator and interpreter. */ +DEF(tci_movi, 1, 0, 1, TCG_OPF_NOT_PRESENT) +DEF(tci_movl, 1, 0, 1, TCG_OPF_NOT_PRESENT) diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc index c740864b96..d6c77325a3 100644 --- a/tcg/tci/tcg-target.c.inc +++ b/tcg/tci/tcg-target.c.inc @@ -22,9 +22,22 @@ * THE SOFTWARE. */ -#include "../tcg-pool.c.inc" +/* Used for function call generation. */ +#define TCG_TARGET_CALL_STACK_OFFSET 0 +#define TCG_TARGET_STACK_ALIGN 8 +#if TCG_TARGET_REG_BITS == 32 +# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EVEN +# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN +# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN +#else +# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL +# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL +# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL +#endif +#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL -static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +static TCGConstraintSetIndex +tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags) { switch (op) { case INDEX_op_goto_ptr: @@ -174,7 +187,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) return TCG_TARGET_REG_BITS == 64 ? C_O0_I2(r, r) : C_O0_I4(r, r, r, r); default: - g_assert_not_reached(); + return C_NotImplemented; } } @@ -695,7 +708,7 @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, /* Always indirect, nothing to do */ } -static void tcg_out_op(TCGContext *s, TCGOpcode opc, +static void tcg_out_op(TCGContext *s, TCGOpcode opc, TCGType type, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) { @@ -761,29 +774,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_op_rrr(s, opc, args[0], args[1], args[2]); break; - CASE_32_64(deposit) /* Optional (TCG_TARGET_HAS_deposit_*). */ - { - TCGArg pos = args[3], len = args[4]; - TCGArg max = opc == INDEX_op_deposit_i32 ? 32 : 64; - - tcg_debug_assert(pos < max); - tcg_debug_assert(pos + len <= max); - - tcg_out_op_rrrbb(s, opc, args[0], args[1], args[2], pos, len); - } + CASE_32_64(deposit) + tcg_out_op_rrrbb(s, opc, args[0], args[1], args[2], args[3], args[4]); break; CASE_32_64(extract) /* Optional (TCG_TARGET_HAS_extract_*). */ CASE_32_64(sextract) /* Optional (TCG_TARGET_HAS_sextract_*). */ - { - TCGArg pos = args[2], len = args[3]; - TCGArg max = tcg_op_defs[opc].flags & TCG_OPF_64BIT ? 64 : 32; - - tcg_debug_assert(pos < max); - tcg_debug_assert(pos + len <= max); - - tcg_out_op_rrbb(s, opc, args[0], args[1], pos, len); - } + tcg_out_op_rrbb(s, opc, args[0], args[1], args[2], args[3]); break; CASE_32_64(brcond) @@ -965,3 +962,13 @@ bool tcg_target_has_memory_bswap(MemOp memop) { return true; } + +static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) +{ + g_assert_not_reached(); +} + +static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) +{ + g_assert_not_reached(); +} diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index a076f401d2..a9ca493d20 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -44,81 +44,6 @@ #define TCG_TARGET_INSN_UNIT_SIZE 4 #define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) -/* Optional instructions. */ - -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_div_i32 1 -#define TCG_TARGET_HAS_rem_i32 1 -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 -#define TCG_TARGET_HAS_ext8u_i32 1 -#define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_andc_i32 1 -#define TCG_TARGET_HAS_deposit_i32 1 -#define TCG_TARGET_HAS_extract_i32 1 -#define TCG_TARGET_HAS_sextract_i32 1 -#define TCG_TARGET_HAS_extract2_i32 0 -#define TCG_TARGET_HAS_eqv_i32 1 -#define TCG_TARGET_HAS_nand_i32 1 -#define TCG_TARGET_HAS_nor_i32 1 -#define TCG_TARGET_HAS_clz_i32 1 -#define TCG_TARGET_HAS_ctz_i32 1 -#define TCG_TARGET_HAS_ctpop_i32 1 -#define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_orc_i32 1 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_negsetcond_i32 0 -#define TCG_TARGET_HAS_muls2_i32 1 -#define TCG_TARGET_HAS_muluh_i32 0 -#define TCG_TARGET_HAS_mulsh_i32 0 -#define TCG_TARGET_HAS_qemu_st8_i32 0 - -#if TCG_TARGET_REG_BITS == 64 -#define TCG_TARGET_HAS_extr_i64_i32 0 -#define TCG_TARGET_HAS_bswap16_i64 1 -#define TCG_TARGET_HAS_bswap32_i64 1 -#define TCG_TARGET_HAS_bswap64_i64 1 -#define TCG_TARGET_HAS_deposit_i64 1 -#define TCG_TARGET_HAS_extract_i64 1 -#define TCG_TARGET_HAS_sextract_i64 1 -#define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_div_i64 1 -#define TCG_TARGET_HAS_rem_i64 1 -#define TCG_TARGET_HAS_ext8s_i64 1 -#define TCG_TARGET_HAS_ext16s_i64 1 -#define TCG_TARGET_HAS_ext32s_i64 1 -#define TCG_TARGET_HAS_ext8u_i64 1 -#define TCG_TARGET_HAS_ext16u_i64 1 -#define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_andc_i64 1 -#define TCG_TARGET_HAS_eqv_i64 1 -#define TCG_TARGET_HAS_nand_i64 1 -#define TCG_TARGET_HAS_nor_i64 1 -#define TCG_TARGET_HAS_clz_i64 1 -#define TCG_TARGET_HAS_ctz_i64 1 -#define TCG_TARGET_HAS_ctpop_i64 1 -#define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_orc_i64 1 -#define TCG_TARGET_HAS_rot_i64 1 -#define TCG_TARGET_HAS_negsetcond_i64 0 -#define TCG_TARGET_HAS_muls2_i64 1 -#define TCG_TARGET_HAS_add2_i32 1 -#define TCG_TARGET_HAS_sub2_i32 1 -#define TCG_TARGET_HAS_mulu2_i32 1 -#define TCG_TARGET_HAS_add2_i64 1 -#define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i64 1 -#define TCG_TARGET_HAS_muluh_i64 0 -#define TCG_TARGET_HAS_mulsh_i64 0 -#else -#define TCG_TARGET_HAS_mulu2_i32 1 -#endif /* TCG_TARGET_REG_BITS == 64 */ - -#define TCG_TARGET_HAS_qemu_ldst_i128 0 - -#define TCG_TARGET_HAS_tst 1 - /* Number of registers available. */ #define TCG_TARGET_NB_REGS 16 @@ -146,26 +71,7 @@ typedef enum { TCG_REG_CALL_STACK = TCG_REG_R15, } TCGReg; -/* Used for function call generation. */ -#define TCG_TARGET_CALL_STACK_OFFSET 0 -#define TCG_TARGET_STACK_ALIGN 8 -#if TCG_TARGET_REG_BITS == 32 -# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EVEN -# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN -# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN -#else -# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL -# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL -# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL -#endif -#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL - #define HAVE_TCG_QEMU_TB_EXEC #define TCG_TARGET_NEED_POOL_LABELS -/* We could notice __i386__ or __s390x__ and reduce the barriers depending - on the host. But if you want performance, you use the normal backend. - We prefer consistency across hosts on this. */ -#define TCG_TARGET_DEFAULT_MO (0) - #endif /* TCG_TARGET_H */ diff --git a/tests/functional/aspeed.py b/tests/functional/aspeed.py index 62f50bab7a..b52358bb8c 100644 --- a/tests/functional/aspeed.py +++ b/tests/functional/aspeed.py @@ -42,7 +42,7 @@ class AspeedTest(LinuxKernelTest): def do_test_arm_aspeed_buildroot_poweroff(self): exec_command_and_wait_for_pattern(self, 'poweroff', - 'reboot: System halted'); + 'System halted'); def do_test_arm_aspeed_sdk_start(self, image): self.require_netdev('user') diff --git a/tests/functional/meson.build b/tests/functional/meson.build index cf80924ddc..b62f714220 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -44,6 +44,7 @@ test_timeouts = { 'riscv64_tuxrun' : 120, 's390x_ccw_virtio' : 420, 'sh4_tuxrun' : 240, + 'x86_64_kvm_xen' : 180, } tests_generic_system = [ @@ -90,6 +91,7 @@ tests_arm_system_thorough = [ 'arm_cubieboard', 'arm_emcraft_sf2', 'arm_integratorcp', + 'arm_microbit', 'arm_orangepi', 'arm_quanta_gsj', 'arm_raspi2', @@ -244,6 +246,7 @@ tests_x86_64_system_thorough = [ 'netdev_ethtool', 'virtio_gpu', 'x86_64_hotplug_cpu', + 'x86_64_kvm_xen', 'x86_64_tuxrun', ] diff --git a/tests/functional/test_aarch64_aspeed.py b/tests/functional/test_aarch64_aspeed.py index 141d863859..9595498ace 100755 --- a/tests/functional/test_aarch64_aspeed.py +++ b/tests/functional/test_aarch64_aspeed.py @@ -27,14 +27,14 @@ class AST2x00MachineSDK(QemuSystemTest): wait_for_console_pattern(self, '## Loading kernel from FIT Image') wait_for_console_pattern(self, 'Starting kernel ...') - ASSET_SDK_V902_AST2700 = Asset( - 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.02/ast2700-default-obmc.tar.gz', - 'ac969c2602f4e6bdb69562ff466b89ae3fe1d86e1f6797bb7969d787f82116a7') + ASSET_SDK_V903_AST2700 = Asset( + 'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.03/ast2700-default-obmc.tar.gz', + '91225f50d255e2905ba8d8e0c80b71b9d157c3609770c7a740cd786370d85a77') - def test_aarch64_ast2700_evb_sdk_v09_02(self): + def test_aarch64_ast2700_evb_sdk_v09_03(self): self.set_machine('ast2700-evb') - self.archive_extract(self.ASSET_SDK_V902_AST2700) + self.archive_extract(self.ASSET_SDK_V903_AST2700) num_cpu = 4 uboot_size = os.path.getsize(self.scratch_file('ast2700-default', diff --git a/tests/functional/test_arm_aspeed_ast2500.py b/tests/functional/test_arm_aspeed_ast2500.py index 743fc46eb2..1ffba6c995 100755 --- a/tests/functional/test_arm_aspeed_ast2500.py +++ b/tests/functional/test_arm_aspeed_ast2500.py @@ -11,15 +11,15 @@ from qemu_test import exec_command_and_wait_for_pattern class AST2500Machine(AspeedTest): - ASSET_BR2_202311_AST2500_FLASH = Asset( + ASSET_BR2_202411_AST2500_FLASH = Asset( ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2500-evb/buildroot-2023.11/flash.img'), - 'c23db6160cf77d0258397eb2051162c8473a56c441417c52a91ba217186e715f') + 'images/ast2500-evb/buildroot-2024.11/flash.img'), + '641e6906c18c0f19a2aeb48099d66d4771929c361001d554d0d45c667413e13a') def test_arm_ast2500_evb_buildroot(self): self.set_machine('ast2500-evb') - image_path = self.ASSET_BR2_202311_AST2500_FLASH.fetch() + image_path = self.ASSET_BR2_202411_AST2500_FLASH.fetch() self.vm.add_args('-device', 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); diff --git a/tests/functional/test_arm_aspeed_ast2600.py b/tests/functional/test_arm_aspeed_ast2600.py index 21640123ee..6ae4ed636a 100755 --- a/tests/functional/test_arm_aspeed_ast2600.py +++ b/tests/functional/test_arm_aspeed_ast2600.py @@ -16,15 +16,15 @@ from qemu_test import exec_command_and_wait_for_pattern, skipIfMissingCommands class AST2600Machine(AspeedTest): - ASSET_BR2_202311_AST2600_FLASH = Asset( + ASSET_BR2_202411_AST2600_FLASH = Asset( ('https://github.com/legoater/qemu-aspeed-boot/raw/master/' - 'images/ast2600-evb/buildroot-2023.11/flash.img'), - 'b62808daef48b438d0728ee07662290490ecfa65987bb91294cafb1bb7ad1a68') + 'images/ast2600-evb/buildroot-2024.11/flash.img'), + '4bb2f3dfdea31199b51d66b42f686dc5374c144a7346fdc650194a5578b73609') def test_arm_ast2600_evb_buildroot(self): self.set_machine('ast2600-evb') - image_path = self.ASSET_BR2_202311_AST2600_FLASH.fetch() + image_path = self.ASSET_BR2_202411_AST2600_FLASH.fetch() self.vm.add_args('-device', 'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test'); diff --git a/tests/functional/test_arm_microbit.py b/tests/functional/test_arm_microbit.py new file mode 100755 index 0000000000..68ea4e73d6 --- /dev/null +++ b/tests/functional/test_arm_microbit.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright 2025, The QEMU Project Developers. +# +# A functional test that runs MicroPython on the arm microbit machine. + +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern + + +class MicrobitMachine(QemuSystemTest): + + ASSET_MICRO = Asset('https://ozlabs.org/~joel/microbit-micropython.hex', + '021641f93dfb11767d4978dbb3ca7f475d1b13c69e7f4aec3382f212636bffd6') + + def test_arm_microbit(self): + self.set_machine('microbit') + + micropython = self.ASSET_MICRO.fetch() + self.vm.set_console() + self.vm.add_args('-device', f'loader,file={micropython}') + self.vm.launch() + wait_for_console_pattern(self, 'Type "help()" for more information.') + exec_command_and_wait_for_pattern(self, 'import machine as mch', '>>>') + exec_command_and_wait_for_pattern(self, 'mch.reset()', 'MicroPython') + wait_for_console_pattern(self, '>>>') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/tests/avocado/kvm_xen_guest.py b/tests/functional/test_x86_64_kvm_xen.py index f8cb458d5d..0298c96c2e 100644..100755 --- a/tests/avocado/kvm_xen_guest.py +++ b/tests/functional/test_x86_64_kvm_xen.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 +# # KVM Xen guest functional tests # # Copyright © 2021 Red Hat, Inc. @@ -13,19 +15,12 @@ import os from qemu.machine import machine -from avocado_qemu import LinuxSSHMixIn -from avocado_qemu import QemuSystemTest -from avocado_qemu import wait_for_console_pattern +from qemu_test import QemuSystemTest, Asset, exec_command_and_wait_for_pattern +from qemu_test import wait_for_console_pattern -class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): - """ - :avocado: tags=arch:x86_64 - :avocado: tags=machine:q35 - :avocado: tags=accel:kvm - :avocado: tags=kvm_xen_guest - """ +class KVMXenGuest(QemuSystemTest): - KERNEL_DEFAULT = 'printk.time=0 root=/dev/xvda console=ttyS0' + KERNEL_DEFAULT = 'printk.time=0 root=/dev/xvda console=ttyS0 quiet' kernel_path = None kernel_params = None @@ -33,14 +28,15 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): # Fetch assets from the kvm-xen-guest subdir of my shared test # images directory on fileserver.linaro.org where you can find # build instructions for how they where assembled. - def get_asset(self, name, sha1): - base_url = ('https://fileserver.linaro.org/s/' - 'kE4nCFLdQcoBF9t/download?' - 'path=%2Fkvm-xen-guest&files=' ) - url = base_url + name - # use explicit name rather than failing to neatly parse the - # URL into a unique one - return self.fetch_asset(name=name, locations=(url), asset_hash=sha1) + ASSET_KERNEL = Asset( + ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/download?' + 'path=%2Fkvm-xen-guest&files=bzImage'), + 'ec0ad7bb8c33c5982baee0a75505fe7dbf29d3ff5d44258204d6307c6fe0132a') + + ASSET_ROOTFS = Asset( + ('https://fileserver.linaro.org/s/kE4nCFLdQcoBF9t/download?' + 'path=%2Fkvm-xen-guest&files=rootfs.ext4'), + 'b11045d649006c649c184e93339aaa41a8fe20a1a86620af70323252eb29e40b') def common_vm_setup(self): # We also catch lack of KVM_XEN support if we fail to launch @@ -51,10 +47,8 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): self.vm.add_args("-accel", "kvm,xen-version=0x4000a,kernel-irqchip=split") self.vm.add_args("-smp", "2") - self.kernel_path = self.get_asset("bzImage", - "367962983d0d32109998a70b45dcee4672d0b045") - self.rootfs = self.get_asset("rootfs.ext4", - "f1478401ea4b3fa2ea196396be44315bab2bb5e4") + self.kernel_path = self.ASSET_KERNEL.fetch() + self.rootfs = self.ASSET_ROOTFS.fetch() def run_and_check(self): self.vm.add_args('-kernel', self.kernel_path, @@ -68,10 +62,10 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): self.vm.launch() except machine.VMLaunchFailure as e: if "Xen HVM guest support not present" in e.output: - self.cancel("KVM Xen support is not present " - "(need v5.12+ kernel with CONFIG_KVM_XEN)") + self.skipTest("KVM Xen support is not present " + "(need v5.12+ kernel with CONFIG_KVM_XEN)") elif "Property 'kvm-accel.xen-version' not found" in e.output: - self.cancel("QEMU not built with CONFIG_XEN_EMU support") + self.skipTest("QEMU not built with CONFIG_XEN_EMU support") else: raise e @@ -79,10 +73,11 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): console_pattern = 'Starting dropbear sshd: OK' wait_for_console_pattern(self, console_pattern, 'Oops') self.log.info('sshd ready') - self.ssh_connect('root', '', False) - self.ssh_command('cat /proc/cmdline') - self.ssh_command('dmesg | grep -e "Grant table initialized"') + exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline', 'xen') + exec_command_and_wait_for_pattern(self, 'dmesg | grep "Grant table"', + 'Grant table initialized') + wait_for_console_pattern(self, '#', 'Oops') def test_kvm_xen_guest(self): """ @@ -94,7 +89,9 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): self.kernel_params = (self.KERNEL_DEFAULT + ' xen_emul_unplug=ide-disks') self.run_and_check() - self.ssh_command('grep xen-pirq.*msi /proc/interrupts') + exec_command_and_wait_for_pattern(self, + 'grep xen-pirq.*msi /proc/interrupts', + 'virtio0-output') def test_kvm_xen_guest_nomsi(self): """ @@ -106,7 +103,9 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): self.kernel_params = (self.KERNEL_DEFAULT + ' xen_emul_unplug=ide-disks pci=nomsi') self.run_and_check() - self.ssh_command('grep xen-pirq.* /proc/interrupts') + exec_command_and_wait_for_pattern(self, + 'grep xen-pirq.* /proc/interrupts', + 'virtio0') def test_kvm_xen_guest_noapic_nomsi(self): """ @@ -118,7 +117,9 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): self.kernel_params = (self.KERNEL_DEFAULT + ' xen_emul_unplug=ide-disks noapic pci=nomsi') self.run_and_check() - self.ssh_command('grep xen-pirq /proc/interrupts') + exec_command_and_wait_for_pattern(self, + 'grep xen-pirq /proc/interrupts', + 'virtio0') def test_kvm_xen_guest_vapic(self): """ @@ -130,8 +131,13 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): self.kernel_params = (self.KERNEL_DEFAULT + ' xen_emul_unplug=ide-disks') self.run_and_check() - self.ssh_command('grep xen-pirq /proc/interrupts') - self.ssh_command('grep PCI-MSI /proc/interrupts') + exec_command_and_wait_for_pattern(self, + 'grep xen-pirq /proc/interrupts', + 'acpi') + wait_for_console_pattern(self, '#') + exec_command_and_wait_for_pattern(self, + 'grep PCI-MSI /proc/interrupts', + 'virtio0-output') def test_kvm_xen_guest_novector(self): """ @@ -143,7 +149,9 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): ' xen_emul_unplug=ide-disks' + ' xen_no_vector_callback') self.run_and_check() - self.ssh_command('grep xen-platform-pci /proc/interrupts') + exec_command_and_wait_for_pattern(self, + 'grep xen-platform-pci /proc/interrupts', + 'fasteoi') def test_kvm_xen_guest_novector_nomsi(self): """ @@ -156,7 +164,9 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): ' xen_emul_unplug=ide-disks pci=nomsi' + ' xen_no_vector_callback') self.run_and_check() - self.ssh_command('grep xen-platform-pci /proc/interrupts') + exec_command_and_wait_for_pattern(self, + 'grep xen-platform-pci /proc/interrupts', + 'IO-APIC') def test_kvm_xen_guest_novector_noapic(self): """ @@ -168,4 +178,9 @@ class KVMXenGuest(QemuSystemTest, LinuxSSHMixIn): ' xen_emul_unplug=ide-disks' + ' xen_no_vector_callback noapic') self.run_and_check() - self.ssh_command('grep xen-platform-pci /proc/interrupts') + exec_command_and_wait_for_pattern(self, + 'grep xen-platform-pci /proc/interrupts', + 'XT-PIC') + +if __name__ == '__main__': + QemuSystemTest.main() diff --git a/util/cpuinfo-riscv.c b/util/cpuinfo-riscv.c index 971c924012..0291b7218a 100644 --- a/util/cpuinfo-riscv.c +++ b/util/cpuinfo-riscv.c @@ -36,7 +36,8 @@ static void sigill_handler(int signo, siginfo_t *si, void *data) /* Called both as constructor and (possibly) via other constructors. */ unsigned __attribute__((constructor)) cpuinfo_init(void) { - unsigned left = CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZICOND | CPUINFO_ZVE64X; + unsigned left = CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZBS + | CPUINFO_ZICOND | CPUINFO_ZVE64X; unsigned info = cpuinfo; if (info) { @@ -50,6 +51,9 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) #if defined(__riscv_arch_test) && defined(__riscv_zbb) info |= CPUINFO_ZBB; #endif +#if defined(__riscv_arch_test) && defined(__riscv_zbs) + info |= CPUINFO_ZBS; +#endif #if defined(__riscv_arch_test) && defined(__riscv_zicond) info |= CPUINFO_ZICOND; #endif @@ -71,7 +75,8 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) && pair.key >= 0) { info |= pair.value & RISCV_HWPROBE_EXT_ZBA ? CPUINFO_ZBA : 0; info |= pair.value & RISCV_HWPROBE_EXT_ZBB ? CPUINFO_ZBB : 0; - left &= ~(CPUINFO_ZBA | CPUINFO_ZBB); + info |= pair.value & RISCV_HWPROBE_EXT_ZBS ? CPUINFO_ZBS : 0; + left &= ~(CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZBS); #ifdef RISCV_HWPROBE_EXT_ZICOND info |= pair.value & RISCV_HWPROBE_EXT_ZICOND ? CPUINFO_ZICOND : 0; left &= ~CPUINFO_ZICOND; @@ -117,6 +122,15 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) left &= ~CPUINFO_ZBB; } + if (left & CPUINFO_ZBS) { + /* Probe for Zbs: bext zero,zero,zero. */ + got_sigill = 0; + asm volatile(".insn r 0x33, 5, 0x24, zero, zero, zero" + : : : "memory"); + info |= got_sigill ? 0 : CPUINFO_ZBS; + left &= ~CPUINFO_ZBS; + } + if (left & CPUINFO_ZICOND) { /* Probe for Zicond: czero.eqz zero,zero,zero. */ got_sigill = 0; |