Merge tag 'misc-pull-request' of gitlab.com:marcandre.lureau/qemu into staging
Misc cleanups
Mostly qemu-ga related cleanups.
# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmKT+IccHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5SGgD/97YXkEQHHQNCiKwFub
# c3RpunfM2ww/492fwBqRYt/QZgnl1esR3gNkMLcEtR8dtWoGja98XNcTBSGcbZGj
# ydGlMZ5kfe/+7mJd5xu45egfEbWICXySstohWU6MzpddBQ1tTgq0iTsU738CsPY7
# kreQgnbYjvfPux0/xhLbYmuLZgBeLX3ser4tzaDA5ExvHjdMSkzjV6qQI5j2BZbZ
# 7jCEfOJJ++Rht71A+FN98HGF9WG6LhV0e6AUnc52XhhldnnhJ3hSU6vcrrvHfYFk
# 31awe1R2agWb4RMfhV2Nfn1uwsc3E+2cNPYbTvm3v/wX00Zc0gE4Z2e1/nXYU8OZ
# +kjJeiVBCgt8DNfJDYnqRWnrYSyhMmc/UIysl0SKLVVOymPDotqHjkEanDNwPUsK
# sgGNkZz2KsBkW9+PoIXh9nxowT5gG/v2oBQuLZQ+2iHgrfNVTKUweO8vHDv+A5lj
# 2hEjx7IhUTNlclSHjggj2Uig7cfSgPVw27ephij0pi5pclsS8wLDs3XlVX+GSyW9
# P+2DWcsi7sBx1Gt6VcwWO07McS+NrqwwhR7rT0ioNhmS1TE0mt0YWhkCg5iabVFo
# yzweA0urN8AF0Js5IKZdNk0/z83nr8Qu8dRmGjciaYo7abBetmIdqdzuv1mIkV2H
# Sqi0mv7yPf7uYHk0U1lb2RNtJQ==
# =L0lG
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 29 May 2022 03:49:43 PM PDT
# gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg: issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]
* tag 'misc-pull-request' of gitlab.com:marcandre.lureau/qemu:
test/qga: use g_auto wherever sensible
qga/wixl: replace QEMU_GA_MSI_MINGW_BIN_PATH with glib bindir
qga/wixl: simplify some pre-processing
qga/wixl: require Mingw_bin
qga/wixl: prefer variables over environment
test/qga: use G_TEST_DIR to locate os-release test file
qga: make build_fs_mount_list() return a bool
qga: replace qemu_open_old() with qga_open_cloexec()
qga: throw an Error in ga_channel_open()
qga: use qga_open_cloexec() for safe_open_or_create()
qga: add qga_open_cloexec() helper
qga: flatten safe_open_or_create()
tests: make libqmp buildable for win32
util/win32: simplify qemu_get_local_state_dir()
include: move qemu_*_exec_dir() to cutils
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst
index d9b65ad..3e1bbe6 100644
--- a/docs/system/ppc/pseries.rst
+++ b/docs/system/ppc/pseries.rst
@@ -32,14 +32,43 @@
Firmware
========
+The pSeries platform in QEMU comes with 2 firmwares:
+
`SLOF <https://github.com/aik/SLOF>`_ (Slimline Open Firmware) is an
implementation of the `IEEE 1275-1994, Standard for Boot (Initialization
Configuration) Firmware: Core Requirements and Practices
<https://standards.ieee.org/standard/1275-1994.html>`_.
+SLOF performs bus scanning, PCI resource allocation, provides the client
+interface to boot from block devices and network.
+
QEMU includes a prebuilt image of SLOF which is updated when a more recent
version is required.
+VOF (Virtual Open Firmware) is a minimalistic firmware to work with
+``-machine pseries,x-vof=on``. When enabled, the firmware acts as a slim
+shim and QEMU implements parts of the IEEE 1275 Open Firmware interface.
+
+VOF does not have device drivers, does not do PCI resource allocation and
+relies on ``-kernel`` used with Linux kernels recent enough (v5.4+)
+to PCI resource assignment. It is ideal to use with petitboot.
+
+Booting via ``-kernel`` supports the following:
+
++-------------------+-------------------+------------------+
+| kernel | pseries,x-vof=off | pseries,x-vof=on |
++===================+===================+==================+
+| vmlinux BE | ✓ | ✓ |
++-------------------+-------------------+------------------+
+| vmlinux LE | ✓ | ✓ |
++-------------------+-------------------+------------------+
+| zImage.pseries BE | x | ✓¹ |
++-------------------+-------------------+------------------+
+| zImage.pseries LE | ✓ | ✓ |
++-------------------+-------------------+------------------+
+
+¹ must set kernel-addr=0
+
Build directions
================
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index adfa085..834bed0 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -880,7 +880,7 @@
Show intel SGX information.
ERST
-#if defined(TARGET_M68K) || defined(TARGET_PPC)
+#if defined(CONFIG_MOS6522)
{
.name = "via",
.args_type = "",
diff --git a/hw/hppa/hppa_hardware.h b/hw/hppa/hppa_hardware.h
index 8b6b922..a5ac3dd 100644
--- a/hw/hppa/hppa_hardware.h
+++ b/hw/hppa/hppa_hardware.h
@@ -1,4 +1,5 @@
/* HPPA cores and system support chips. */
+/* Be aware: QEMU and seabios-hppa repositories share this file as-is. */
#ifndef HW_HPPA_HPPA_HARDWARE_H
#define HW_HPPA_HPPA_HARDWARE_H
@@ -30,13 +31,18 @@
#define PCI_HPA DINO_HPA /* PCI bus */
#define IDE_HPA 0xf9000000 /* Boot disc controller */
+/* offsets to DINO HPA: */
+#define DINO_PCI_ADDR 0x064
+#define DINO_CONFIG_DATA 0x068
+#define DINO_IO_DATA 0x06c
+
#define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR)
#define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA)
#define FW_CFG_IO_BASE 0xfffa0000
-#define PORT_SERIAL1 (DINO_UART_HPA + 0x800)
-#define PORT_SERIAL2 (LASI_UART_HPA + 0x800)
+#define PORT_SERIAL1 (LASI_UART_HPA + 0x800)
+#define PORT_SERIAL2 (DINO_UART_HPA + 0x800)
#define HPPA_MAX_CPUS 16 /* max. number of SMP CPUs */
#define CPU_CLOCK_MHZ 250 /* emulate a 250 MHz CPU */
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index d1e174b..63b9dd2 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -32,7 +32,7 @@
#define MAX_IDE_BUS 2
-#define MIN_SEABIOS_HPPA_VERSION 1 /* require at least this fw version */
+#define MIN_SEABIOS_HPPA_VERSION 6 /* require at least this fw version */
#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
@@ -236,20 +236,14 @@
/* Realtime clock, used by firmware for PDC_TOD call. */
mc146818_rtc_init(isa_bus, 2000, NULL);
- /* Serial code setup. */
- if (serial_hd(0)) {
- uint32_t addr = DINO_UART_HPA + 0x800;
- serial_mm_init(addr_space, addr, 0,
- qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT),
- 115200, serial_hd(0), DEVICE_BIG_ENDIAN);
- }
+ /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
+ serial_mm_init(addr_space, LASI_UART_HPA + 0x800, 0,
+ qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
+ serial_hd(0), DEVICE_BIG_ENDIAN);
- if (serial_hd(1)) {
- /* Serial port */
- serial_mm_init(addr_space, LASI_UART_HPA + 0x800, 0,
- qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 8000000 / 16,
- serial_hd(1), DEVICE_BIG_ENDIAN);
- }
+ serial_mm_init(addr_space, DINO_UART_HPA + 0x800, 0,
+ qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
+ serial_hd(1), DEVICE_BIG_ENDIAN);
/* Parallel port */
parallel_mm_init(addr_space, LASI_LPT_HPA + 0x800, 0,
diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c
index 87303b4..a39e070 100644
--- a/hw/intc/pnv_xive2.c
+++ b/hw/intc/pnv_xive2.c
@@ -1295,7 +1295,6 @@
uint64_t val, unsigned size)
{
PnvXive2 *xive = PNV_XIVE2(opaque);
- uint32_t reg = offset >> 3;
switch (offset) {
/*
@@ -1322,8 +1321,6 @@
xive2_error(xive, "TCTXT: invalid write @%"HWADDR_PRIx, offset);
return;
}
-
- xive->pc_regs[reg] = val;
}
static const MemoryRegionOps pnv_xive2_ic_tctxt_ops = {
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 2bc3dce..7f7f5b3 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -47,7 +47,6 @@
#include "hw/irq.h"
#define EPAPR_MAGIC (0x45504150)
-#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
#define DTC_LOAD_PAD 0x1800000
#define DTC_PAD_MASK 0xFFFFF
#define DTB_MAX_SIZE (8 * MiB)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6de8005..fd4942e 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1066,7 +1066,7 @@
_FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device));
}
- if (!spapr->has_graphics && stdout_path) {
+ if (spapr->want_stdout_path && stdout_path) {
/*
* "linux,stdout-path" and "stdout" properties are
* deprecated by linux kernel. New platforms should only
@@ -2712,6 +2712,7 @@
const char *kernel_filename = machine->kernel_filename;
const char *initrd_filename = machine->initrd_filename;
PCIHostState *phb;
+ bool has_vga;
int i;
MemoryRegion *sysmem = get_system_memory();
long load_limit, fw_size;
@@ -2950,9 +2951,12 @@
}
/* Graphics */
- if (spapr_vga_init(phb->bus, &error_fatal)) {
- spapr->has_graphics = true;
+ has_vga = spapr_vga_init(phb->bus, &error_fatal);
+ if (has_vga) {
+ spapr->want_stdout_path = !machine->enable_graphics;
machine->usb |= defaults_enabled() && !machine->usb_disabled;
+ } else {
+ spapr->want_stdout_path = true;
}
if (machine->usb) {
@@ -2962,7 +2966,7 @@
pci_create_simple(phb->bus, -1, "nec-usb-xhci");
}
- if (spapr->has_graphics) {
+ if (has_vga) {
USBBus *usb_bus = usb_bus_find(-1);
usb_create_simple(usb_bus, "usb-kbd");
@@ -2971,14 +2975,16 @@
}
if (kernel_filename) {
+ uint64_t loaded_addr = 0;
+
spapr->kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, spapr,
- NULL, NULL, NULL, NULL, 1,
+ NULL, &loaded_addr, NULL, NULL, 1,
PPC_ELF_MACHINE, 0, 0);
if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
spapr->kernel_size = load_elf(kernel_filename, NULL,
translate_kernel_address, spapr,
- NULL, NULL, NULL, NULL, 0,
+ NULL, &loaded_addr, NULL, NULL, 0,
PPC_ELF_MACHINE, 0, 0);
spapr->kernel_le = spapr->kernel_size > 0;
}
@@ -2988,6 +2994,13 @@
exit(1);
}
+ if (spapr->kernel_addr != loaded_addr) {
+ warn_report("spapr: kernel_addr changed from 0x%"PRIx64
+ " to 0x%"PRIx64,
+ spapr->kernel_addr, loaded_addr);
+ spapr->kernel_addr = loaded_addr;
+ }
+
/* load initrd */
if (initrd_filename) {
/* Try to locate the initrd in the gap between the kernel
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 14b01c3..072dda2 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -194,7 +194,7 @@
Vof *vof;
uint64_t rtc_offset; /* Now used only during incoming migration */
struct PPCTimebase tb;
- bool has_graphics;
+ bool want_stdout_path;
uint32_t vsmt; /* Virtual SMT mode (KVM's "core stride") */
/* Nested HV support (TCG only) */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index acc2174..f7eae35 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -779,6 +779,8 @@
QEMU_PPC_FEATURE2_DARN = 0x00200000, /* darn random number insn */
QEMU_PPC_FEATURE2_SCV = 0x00100000, /* scv syscall */
QEMU_PPC_FEATURE2_HTM_NO_SUSPEND = 0x00080000, /* TM w/o suspended state */
+ QEMU_PPC_FEATURE2_ARCH_3_1 = 0x00040000, /* ISA 3.1 */
+ QEMU_PPC_FEATURE2_MMA = 0x00020000, /* Matrix-Multiply Assist */
};
#define ELF_HWCAP get_elf_hwcap()
@@ -836,6 +838,8 @@
QEMU_PPC_FEATURE2_VEC_CRYPTO);
GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00 |
QEMU_PPC_FEATURE2_DARN | QEMU_PPC_FEATURE2_HAS_IEEE128);
+ GET_FEATURE2(PPC2_ISA310, QEMU_PPC_FEATURE2_ARCH_3_1 |
+ QEMU_PPC_FEATURE2_MMA);
#undef GET_FEATURE
#undef GET_FEATURE2
diff --git a/monitor/misc.c b/monitor/misc.c
index 6c5bb82..3d2312b 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -84,6 +84,9 @@
#include "hw/s390x/storage-attributes.h"
#endif
+/* Make devices configuration available for use in hmp-commands*.hx templates */
+#include CONFIG_DEVICES
+
/* file descriptors passed via SCM_RIGHTS */
typedef struct mon_fd_t mon_fd_t;
struct mon_fd_t {
diff --git a/pc-bios/hppa-firmware.img b/pc-bios/hppa-firmware.img
index 392bce0..b2cbb71 100644
--- a/pc-bios/hppa-firmware.img
+++ b/pc-bios/hppa-firmware.img
Binary files differ
diff --git a/roms/seabios-hppa b/roms/seabios-hppa
index 17ca7a9..458626c 160000
--- a/roms/seabios-hppa
+++ b/roms/seabios-hppa
@@ -1 +1 @@
-Subproject commit 17ca7a9998c1755d42321cfc0afb5f480f5a58ff
+Subproject commit 458626c4c6441045c0612f24313c7cf1f95e71c6
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 48596cf..6d78078 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -227,6 +227,7 @@
int16_t s16[8];
int32_t s32[4];
int64_t s64[2];
+ float16 f16[8];
float32 f32[4];
float64 f64[2];
float128 f128;
@@ -238,6 +239,7 @@
typedef ppc_vsr_t ppc_avr_t;
typedef ppc_vsr_t ppc_fprp_t;
+typedef ppc_vsr_t ppc_acc_t;
#if !defined(CONFIG_USER_ONLY)
/* Software TLB cache */
@@ -735,6 +737,8 @@
(1 << FPSCR_VXSOFT) | (1 << FPSCR_VXSQRT) | \
(1 << FPSCR_VXCVI))
+FIELD(FPSCR, FI, FPSCR_FI, 1)
+
#define FP_DRN2 (1ull << FPSCR_DRN2)
#define FP_DRN1 (1ull << FPSCR_DRN1)
#define FP_DRN0 (1ull << FPSCR_DRN0)
@@ -2271,6 +2275,8 @@
PPC2_ISA300 = 0x0000000000080000ULL,
/* POWER ISA 3.1 */
PPC2_ISA310 = 0x0000000000100000ULL,
+ /* lwsync instruction */
+ PPC2_MEM_LWSYNC = 0x0000000000200000ULL,
#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_VSX | PPC2_PRCNTL | PPC2_DBRX | \
PPC2_ISA205 | PPC2_VSX207 | PPC2_PERM_ISA206 | \
@@ -2279,7 +2285,7 @@
PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | \
PPC2_ALTIVEC_207 | PPC2_ISA207S | PPC2_DFP | \
PPC2_FP_CVT_S64 | PPC2_TM | PPC2_PM_ISA206 | \
- PPC2_ISA300 | PPC2_ISA310)
+ PPC2_ISA300 | PPC2_ISA310 | PPC2_MEM_LWSYNC)
};
/*****************************************************************************/
@@ -2638,6 +2644,9 @@
#define VsrSW(i) s32[i]
#define VsrD(i) u64[i]
#define VsrSD(i) s64[i]
+#define VsrHF(i) f16[i]
+#define VsrSF(i) f32[i]
+#define VsrDF(i) f64[i]
#else
#define VsrB(i) u8[15 - (i)]
#define VsrSB(i) s8[15 - (i)]
@@ -2647,6 +2656,9 @@
#define VsrSW(i) s32[3 - (i)]
#define VsrD(i) u64[1 - (i)]
#define VsrSD(i) s64[1 - (i)]
+#define VsrHF(i) f16[7 - (i)]
+#define VsrSF(i) f32[3 - (i)]
+#define VsrDF(i) f64[1 - (i)]
#endif
static inline int vsr64_offset(int i, bool high)
@@ -2659,6 +2671,11 @@
return offsetof(CPUPPCState, vsr[i].u64[0]);
}
+static inline int acc_full_offset(int i)
+{
+ return vsr_full_offset(i * 4);
+}
+
static inline int fpr_offset(int i)
{
return vsr64_offset(i, true);
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 527ad40..0f891af 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5769,7 +5769,7 @@
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_64B | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI;
- pcc->insns_flags2 = PPC2_FP_CVT_S64;
+ pcc->insns_flags2 = PPC2_FP_CVT_S64 | PPC2_MEM_LWSYNC;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_VR) |
(1ull << MSR_POW) |
@@ -5846,7 +5846,7 @@
PPC_64B |
PPC_POPCNTB |
PPC_SEGMENT_64B | PPC_SLBI;
- pcc->insns_flags2 = PPC2_FP_CVT_S64;
+ pcc->insns_flags2 = PPC2_FP_CVT_S64 | PPC2_MEM_LWSYNC;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_VR) |
(1ull << MSR_POW) |
@@ -5985,7 +5985,7 @@
PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 |
PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206 |
PPC2_FP_TST_ISA206 | PPC2_FP_CVT_S64 |
- PPC2_PM_ISA206;
+ PPC2_PM_ISA206 | PPC2_MEM_LWSYNC;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
@@ -6159,7 +6159,7 @@
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
- PPC2_TM | PPC2_PM_ISA206;
+ PPC2_TM | PPC2_PM_ISA206 | PPC2_MEM_LWSYNC;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_HV) |
(1ull << MSR_TM) |
@@ -6379,7 +6379,7 @@
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
- PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
+ PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_MEM_LWSYNC;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_HV) |
(1ull << MSR_TM) |
@@ -6596,7 +6596,8 @@
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
- PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_ISA310;
+ PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_ISA310 |
+ PPC2_MEM_LWSYNC;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_HV) |
(1ull << MSR_TM) |
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index f6c8318..fed0ce4 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -36,6 +36,15 @@
#define float32_snan_to_qnan(x) ((x) | 0x00400000)
#define float16_snan_to_qnan(x) ((x) | 0x0200)
+static inline float32 bfp32_neg(float32 a)
+{
+ if (unlikely(float32_is_any_nan(a))) {
+ return a;
+ } else {
+ return float32_chs(a);
+ }
+}
+
static inline bool fp_exceptions_enabled(CPUPPCState *env)
{
#ifdef CONFIG_USER_ONLY
@@ -329,24 +338,25 @@
}
}
-static inline void float_overflow_excp(CPUPPCState *env)
+static inline int float_overflow_excp(CPUPPCState *env)
{
CPUState *cs = env_cpu(env);
env->fpscr |= FP_OX;
/* Update the floating-point exception summary */
env->fpscr |= FP_FX;
- if (env->fpscr & FP_OE) {
+
+ bool overflow_enabled = !!(env->fpscr & FP_OE);
+ if (overflow_enabled) {
/* XXX: should adjust the result */
/* Update the floating-point enabled exception summary */
env->fpscr |= FP_FEX;
/* We must update the target FPR before raising the exception */
cs->exception_index = POWERPC_EXCP_PROGRAM;
env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
- } else {
- env->fpscr |= FP_XX;
- env->fpscr |= FP_FI;
}
+
+ return overflow_enabled ? 0 : float_flag_inexact;
}
static inline void float_underflow_excp(CPUPPCState *env)
@@ -370,7 +380,6 @@
{
CPUState *cs = env_cpu(env);
- env->fpscr |= FP_FI;
env->fpscr |= FP_XX;
/* Update the floating-point exception summary */
env->fpscr |= FP_FX;
@@ -414,7 +423,7 @@
ppc_store_fpscr(env, val);
}
-void helper_fpscr_check_status(CPUPPCState *env)
+static void do_fpscr_check_status(CPUPPCState *env, uintptr_t raddr)
{
CPUState *cs = env_cpu(env);
target_ulong fpscr = env->fpscr;
@@ -455,27 +464,36 @@
}
cs->exception_index = POWERPC_EXCP_PROGRAM;
env->error_code = error | POWERPC_EXCP_FP;
+ env->fpscr |= error ? FP_FEX : 0;
/* Deferred floating-point exception after target FPSCR update */
if (fp_exceptions_enabled(env)) {
raise_exception_err_ra(env, cs->exception_index,
- env->error_code, GETPC());
+ env->error_code, raddr);
}
}
-static void do_float_check_status(CPUPPCState *env, uintptr_t raddr)
+void helper_fpscr_check_status(CPUPPCState *env)
+{
+ do_fpscr_check_status(env, GETPC());
+}
+
+static void do_float_check_status(CPUPPCState *env, bool change_fi,
+ uintptr_t raddr)
{
CPUState *cs = env_cpu(env);
int status = get_float_exception_flags(&env->fp_status);
if (status & float_flag_overflow) {
- float_overflow_excp(env);
+ status |= float_overflow_excp(env);
} else if (status & float_flag_underflow) {
float_underflow_excp(env);
}
if (status & float_flag_inexact) {
float_inexact_excp(env);
- } else {
- env->fpscr &= ~FP_FI; /* clear the FPSCR[FI] bit */
+ }
+ if (change_fi) {
+ env->fpscr = FIELD_DP64(env->fpscr, FPSCR, FI,
+ !!(status & float_flag_inexact));
}
if (cs->exception_index == POWERPC_EXCP_PROGRAM &&
@@ -490,7 +508,7 @@
void helper_float_check_status(CPUPPCState *env)
{
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
}
void helper_reset_fpstatus(CPUPPCState *env)
@@ -684,7 +702,7 @@
} else { \
farg.d = cvtr(arg, &env->fp_status); \
} \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, true, GETPC()); \
return farg.ll; \
}
@@ -710,7 +728,7 @@
/* fri* does not set FPSCR[XX] */
set_float_exception_flags(flags & ~float_flag_inexact, &env->fp_status);
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
return arg;
}
@@ -916,18 +934,17 @@
}
/* fsel - fsel. */
-uint64_t helper_fsel(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
- uint64_t arg3)
+uint64_t helper_FSEL(uint64_t a, uint64_t b, uint64_t c)
{
- CPU_DoubleU farg1;
+ CPU_DoubleU fa;
- farg1.ll = arg1;
+ fa.ll = a;
- if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) &&
- !float64_is_any_nan(farg1.d)) {
- return arg2;
+ if ((!float64_is_neg(fa.d) || float64_is_zero(fa.d)) &&
+ !float64_is_any_nan(fa.d)) {
+ return c;
} else {
- return arg3;
+ return b;
}
}
@@ -1690,9 +1707,9 @@
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_ADD_SUB(name, op, nels, tp, fld, sfprf, r2sp) \
+#define VSX_ADD_SUB(name, op, nels, tp, fld, sfifprf, r2sp) \
void helper_##name(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
@@ -1709,19 +1726,19 @@
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
float_invalid_op_addsub(env, tstat.float_exception_flags, \
- sfprf, GETPC()); \
+ sfifprf, GETPC()); \
} \
\
if (r2sp) { \
t.fld = do_frsp(env, t.fld, GETPC()); \
} \
\
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
} \
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_ADD_SUB(xsadddp, add, 1, float64, VsrD(0), 1, 0)
@@ -1757,7 +1774,7 @@
helper_compute_fprf_float128(env, t.f128);
*xt = t;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
}
/*
@@ -1766,9 +1783,9 @@
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_MUL(op, nels, tp, fld, sfprf, r2sp) \
+#define VSX_MUL(op, nels, tp, fld, sfifprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
@@ -1785,20 +1802,20 @@
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
float_invalid_op_mul(env, tstat.float_exception_flags, \
- sfprf, GETPC()); \
+ sfifprf, GETPC()); \
} \
\
if (r2sp) { \
t.fld = do_frsp(env, t.fld, GETPC()); \
} \
\
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_MUL(xsmuldp, 1, float64, VsrD(0), 1, 0)
@@ -1828,7 +1845,7 @@
helper_compute_fprf_float128(env, t.f128);
*xt = t;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
}
/*
@@ -1837,9 +1854,9 @@
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_DIV(op, nels, tp, fld, sfprf, r2sp) \
+#define VSX_DIV(op, nels, tp, fld, sfifprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *xa, ppc_vsr_t *xb) \
{ \
@@ -1856,7 +1873,7 @@
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
float_invalid_op_div(env, tstat.float_exception_flags, \
- sfprf, GETPC()); \
+ sfifprf, GETPC()); \
} \
if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) { \
float_zero_divide_excp(env, GETPC()); \
@@ -1866,13 +1883,13 @@
t.fld = do_frsp(env, t.fld, GETPC()); \
} \
\
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_DIV(xsdivdp, 1, float64, VsrD(0), 1, 0)
@@ -1905,7 +1922,7 @@
helper_compute_fprf_float128(env, t.f128);
*xt = t;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
}
/*
@@ -1914,9 +1931,9 @@
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_RE(op, nels, tp, fld, sfprf, r2sp) \
+#define VSX_RE(op, nels, tp, fld, sfifprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = { }; \
@@ -1934,13 +1951,13 @@
t.fld = do_frsp(env, t.fld, GETPC()); \
} \
\
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_RE(xsredp, 1, float64, VsrD(0), 1, 0)
@@ -1954,9 +1971,9 @@
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_SQRT(op, nels, tp, fld, sfprf, r2sp) \
+#define VSX_SQRT(op, nels, tp, fld, sfifprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = { }; \
@@ -1972,20 +1989,20 @@
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
float_invalid_op_sqrt(env, tstat.float_exception_flags, \
- sfprf, GETPC()); \
+ sfifprf, GETPC()); \
} \
\
if (r2sp) { \
t.fld = do_frsp(env, t.fld, GETPC()); \
} \
\
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_SQRT(xssqrtdp, 1, float64, VsrD(0), 1, 0)
@@ -1999,9 +2016,9 @@
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_RSQRTE(op, nels, tp, fld, sfprf, r2sp) \
+#define VSX_RSQRTE(op, nels, tp, fld, sfifprf, r2sp) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = { }; \
@@ -2017,19 +2034,19 @@
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
float_invalid_op_sqrt(env, tstat.float_exception_flags, \
- sfprf, GETPC()); \
+ sfifprf, GETPC()); \
} \
if (r2sp) { \
t.fld = do_frsp(env, t.fld, GETPC()); \
} \
\
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_RSQRTE(xsrsqrtedp, 1, float64, VsrD(0), 1, 0)
@@ -2155,9 +2172,9 @@
* fld - vsr_t field (VsrD(*) or VsrW(*))
* maddflgs - flags for the float*muladd routine that control the
* various forms (madd, msub, nmadd, nmsub)
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_MADD(op, nels, tp, fld, maddflgs, sfprf) \
+#define VSX_MADD(op, nels, tp, fld, maddflgs, sfifprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *s1, ppc_vsr_t *s2, ppc_vsr_t *s3) \
{ \
@@ -2174,15 +2191,15 @@
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
float_invalid_op_madd(env, tstat.float_exception_flags, \
- sfprf, GETPC()); \
+ sfifprf, GETPC()); \
} \
\
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
} \
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_MADD(XSMADDDP, 1, float64, VsrD(0), MADD_FLGS, 1)
@@ -2234,7 +2251,7 @@
\
helper_compute_fprf_float128(env, t.f128); \
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, true, GETPC()); \
}
VSX_MADDQ(XSMADDQP, MADD_FLGS, 0)
@@ -2283,7 +2300,7 @@
\
memset(xt, 0, sizeof(*xt)); \
memset(&xt->fld, -r, sizeof(xt->fld)); \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, false, GETPC()); \
}
VSX_SCALAR_CMP(XSCMPEQDP, float64, eq, VsrD(0), 0)
@@ -2319,7 +2336,7 @@
env->fpscr |= cc << FPSCR_FPCC;
env->crf[BF(opcode)] = cc;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, false, GETPC());
}
void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode,
@@ -2348,7 +2365,7 @@
env->fpscr |= cc << FPSCR_FPCC;
env->crf[BF(opcode)] = cc;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, false, GETPC());
}
static inline void do_scalar_cmp(CPUPPCState *env, ppc_vsr_t *xa, ppc_vsr_t *xb,
@@ -2401,7 +2418,7 @@
float_invalid_op_vxvc(env, 0, GETPC());
}
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, false, GETPC());
}
void helper_xscmpodp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
@@ -2466,7 +2483,7 @@
float_invalid_op_vxvc(env, 0, GETPC());
}
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, false, GETPC());
}
void helper_xscmpoqp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
@@ -2505,7 +2522,7 @@
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, false, GETPC()); \
}
VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, VsrD(0))
@@ -2667,9 +2684,9 @@
* ttp - target type (float32 or float64)
* sfld - source vsr_t field
* tfld - target vsr_t field (f32 or f64)
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_CVT_FP_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf) \
+#define VSX_CVT_FP_TO_FP(op, nels, stp, ttp, sfld, tfld, sfifprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = { }; \
@@ -2682,19 +2699,19 @@
float_invalid_op_vxsnan(env, GETPC()); \
t.tfld = ttp##_snan_to_qnan(t.tfld); \
} \
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_##ttp(env, t.tfld); \
} \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, VsrW(0), VsrD(0), 1)
VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, VsrW(2 * i), VsrD(i), 0)
-#define VSX_CVT_FP_TO_FP2(op, nels, stp, ttp, sfprf) \
+#define VSX_CVT_FP_TO_FP2(op, nels, stp, ttp, sfifprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = { }; \
@@ -2707,14 +2724,14 @@
float_invalid_op_vxsnan(env, GETPC()); \
t.VsrW(2 * i) = ttp##_snan_to_qnan(t.VsrW(2 * i)); \
} \
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_##ttp(env, t.VsrW(2 * i)); \
} \
t.VsrW(2 * i + 1) = t.VsrW(2 * i); \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_CVT_FP_TO_FP2(xvcvdpsp, 2, float64, float32, 0)
@@ -2730,9 +2747,9 @@
* tfld - target vsr_t field (f32 or f64)
* sfprf - set FPRF
*/
-#define VSX_CVT_FP_TO_FP_VECTOR(op, nels, stp, ttp, sfld, tfld, sfprf) \
-void helper_##op(CPUPPCState *env, uint32_t opcode, \
- ppc_vsr_t *xt, ppc_vsr_t *xb) \
+#define VSX_CVT_FP_TO_FP_VECTOR(op, nels, stp, ttp, sfld, tfld, sfprf) \
+void helper_##op(CPUPPCState *env, uint32_t opcode, \
+ ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = *xt; \
int i; \
@@ -2750,7 +2767,7 @@
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, true, GETPC()); \
}
VSX_CVT_FP_TO_FP_VECTOR(xscvdpqp, 1, float64, float128, VsrD(0), f128, 1)
@@ -2764,9 +2781,9 @@
* ttp - target type
* sfld - source vsr_t field
* tfld - target vsr_t field
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_CVT_FP_TO_FP_HP(op, nels, stp, ttp, sfld, tfld, sfprf) \
+#define VSX_CVT_FP_TO_FP_HP(op, nels, stp, ttp, sfld, tfld, sfifprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = { }; \
@@ -2779,13 +2796,13 @@
float_invalid_op_vxsnan(env, GETPC()); \
t.tfld = ttp##_snan_to_qnan(t.tfld); \
} \
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_##ttp(env, t.tfld); \
} \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_CVT_FP_TO_FP_HP(xscvdphp, 1, float64, float16, VsrD(0), VsrH(3), 1)
@@ -2810,7 +2827,7 @@
}
*xt = t;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, false, GETPC());
}
void helper_XSCVQPDP(CPUPPCState *env, uint32_t ro, ppc_vsr_t *xt,
@@ -2833,7 +2850,7 @@
helper_compute_fprf_float64(env, t.VsrD(0));
*xt = t;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
}
uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
@@ -2876,7 +2893,7 @@
return (result << 32) | result;
}
-uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
+uint64_t helper_XSCVSPDPN(uint64_t xb)
{
return helper_todouble(xb >> 32);
}
@@ -2889,9 +2906,10 @@
* ttp - target type (int32, uint32, int64 or uint64)
* sfld - source vsr_t field
* tfld - target vsr_t field
+ * sfi - set FI
* rnan - resulting NaN
*/
-#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, rnan) \
+#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, sfi, rnan) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
int all_flags = env->fp_status.float_exception_flags, flags; \
@@ -2910,20 +2928,23 @@
\
*xt = t; \
env->fp_status.float_exception_flags = all_flags; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfi, GETPC()); \
}
-VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), \
+VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), true, \
0x8000000000000000ULL)
-VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, VsrD(0), VsrD(0), 0ULL)
-VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, VsrD(i), VsrD(i), \
+VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, VsrD(0), VsrD(0), true, 0ULL)
+VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, VsrD(i), VsrD(i), false, \
0x8000000000000000ULL)
-VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, VsrD(i), VsrD(i), 0ULL)
-VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, VsrW(2 * i), VsrD(i), \
+VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, VsrD(i), VsrD(i), false, \
+ 0ULL)
+VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, VsrW(2 * i), VsrD(i), false, \
0x8000000000000000ULL)
-VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), 0x80000000U)
-VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2 * i), VsrD(i), 0ULL)
-VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), 0U)
+VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), false, \
+ 0x80000000ULL)
+VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2 * i), VsrD(i), \
+ false, 0ULL)
+VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), false, 0U)
#define VSX_CVT_FP_TO_INT128(op, tp, rnan) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
@@ -2940,7 +2961,7 @@
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, true, GETPC()); \
}
VSX_CVT_FP_TO_INT128(XSCVQPUQZ, uint128, 0)
@@ -2955,7 +2976,7 @@
* words 0 and 1 (and words 2 and 3) of the result register, as
* is required by this version of the architecture.
*/
-#define VSX_CVT_FP_TO_INT2(op, nels, stp, ttp, rnan) \
+#define VSX_CVT_FP_TO_INT2(op, nels, stp, ttp, sfi, rnan) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
int all_flags = env->fp_status.float_exception_flags, flags; \
@@ -2977,13 +2998,13 @@
\
*xt = t; \
env->fp_status.float_exception_flags = all_flags; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfi, GETPC()); \
}
-VSX_CVT_FP_TO_INT2(xscvdpsxws, 1, float64, int32, 0x80000000U)
-VSX_CVT_FP_TO_INT2(xscvdpuxws, 1, float64, uint32, 0U)
-VSX_CVT_FP_TO_INT2(xvcvdpsxws, 2, float64, int32, 0x80000000U)
-VSX_CVT_FP_TO_INT2(xvcvdpuxws, 2, float64, uint32, 0U)
+VSX_CVT_FP_TO_INT2(xscvdpsxws, 1, float64, int32, true, 0x80000000U)
+VSX_CVT_FP_TO_INT2(xscvdpuxws, 1, float64, uint32, true, 0U)
+VSX_CVT_FP_TO_INT2(xvcvdpsxws, 2, float64, int32, false, 0x80000000U)
+VSX_CVT_FP_TO_INT2(xvcvdpuxws, 2, float64, uint32, false, 0U)
/*
* VSX_CVT_FP_TO_INT_VECTOR - VSX floating point to integer conversion
@@ -3008,7 +3029,7 @@
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, true, GETPC()); \
}
VSX_CVT_FP_TO_INT_VECTOR(xscvqpsdz, float128, int64, f128, VsrD(0), \
@@ -3028,9 +3049,9 @@
* sfld - source vsr_t field
* tfld - target vsr_t field
* jdef - definition of the j index (i or 2*i)
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, sfprf, r2sp) \
+#define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, sfifprf, r2sp)\
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = { }; \
@@ -3041,13 +3062,13 @@
if (r2sp) { \
t.tfld = do_frsp(env, t.tfld, GETPC()); \
} \
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.tfld); \
} \
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, VsrD(0), VsrD(0), 1, 0)
@@ -3073,7 +3094,7 @@
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, false, GETPC()); \
}
VSX_CVT_INT_TO_FP2(xvcvsxdsp, int64, float32)
@@ -3085,7 +3106,7 @@
helper_reset_fpstatus(env); \
xt->f128 = tp##_to_float128(xb->s128, &env->fp_status); \
helper_compute_fprf_float128(env, xt->f128); \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, true, GETPC()); \
}
VSX_CVT_INT128_TO_FP(XSCVUQQP, uint128);
@@ -3109,7 +3130,7 @@
helper_compute_fprf_##ttp(env, t.tfld); \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, true, GETPC()); \
}
VSX_CVT_INT_TO_FP_VECTOR(xscvsdqp, int64, float128, VsrD(0), f128)
@@ -3129,9 +3150,9 @@
* tp - type (float32 or float64)
* fld - vsr_t field (VsrD(*) or VsrW(*))
* rmode - rounding mode
- * sfprf - set FPRF
+ * sfifprf - set FI and FPRF
*/
-#define VSX_ROUND(op, nels, tp, fld, rmode, sfprf) \
+#define VSX_ROUND(op, nels, tp, fld, rmode, sfifprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
ppc_vsr_t t = { }; \
@@ -3151,7 +3172,7 @@
} else { \
t.fld = tp##_round_to_int(xb->fld, &env->fp_status); \
} \
- if (sfprf) { \
+ if (sfifprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
} \
@@ -3167,7 +3188,7 @@
} \
\
*xt = t; \
- do_float_check_status(env, GETPC()); \
+ do_float_check_status(env, sfifprf, GETPC()); \
}
VSX_ROUND(xsrdpi, 1, float64, VsrD(0), float_round_ties_away, 1)
@@ -3195,11 +3216,11 @@
uint64_t xt = do_frsp(env, xb, GETPC());
helper_compute_fprf_float64(env, xt);
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
return xt;
}
-void helper_xvxsigsp(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)
+void helper_XVXSIGSP(ppc_vsr_t *xt, ppc_vsr_t *xb)
{
ppc_vsr_t t = { };
uint32_t exp, i, fraction;
@@ -3355,7 +3376,7 @@
}
helper_compute_fprf_float128(env, t.f128);
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
*xt = t;
}
@@ -3408,7 +3429,7 @@
helper_compute_fprf_float128(env, t.f128);
*xt = t;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
}
void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode,
@@ -3434,7 +3455,7 @@
helper_compute_fprf_float128(env, t.f128);
*xt = t;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
}
void helper_xssubqp(CPUPPCState *env, uint32_t opcode,
@@ -3460,5 +3481,315 @@
helper_compute_fprf_float128(env, t.f128);
*xt = t;
- do_float_check_status(env, GETPC());
+ do_float_check_status(env, true, GETPC());
+}
+
+static inline void vsxger_excp(CPUPPCState *env, uintptr_t retaddr)
+{
+ /*
+ * XV*GER instructions execute and set the FPSCR as if exceptions
+ * are disabled and only at the end throw an exception
+ */
+ target_ulong enable;
+ enable = env->fpscr & (FP_ENABLES | FP_FI | FP_FR);
+ env->fpscr &= ~(FP_ENABLES | FP_FI | FP_FR);
+ int status = get_float_exception_flags(&env->fp_status);
+ if (unlikely(status & float_flag_invalid)) {
+ if (status & float_flag_invalid_snan) {
+ float_invalid_op_vxsnan(env, 0);
+ }
+ if (status & float_flag_invalid_imz) {
+ float_invalid_op_vximz(env, false, 0);
+ }
+ if (status & float_flag_invalid_isi) {
+ float_invalid_op_vxisi(env, false, 0);
+ }
+ }
+ do_float_check_status(env, false, retaddr);
+ env->fpscr |= enable;
+ do_fpscr_check_status(env, retaddr);
+}
+
+typedef float64 extract_f16(float16, float_status *);
+
+static float64 extract_hf16(float16 in, float_status *fp_status)
+{
+ return float16_to_float64(in, true, fp_status);
+}
+
+static float64 extract_bf16(bfloat16 in, float_status *fp_status)
+{
+ return bfloat16_to_float64(in, fp_status);
+}
+
+static void vsxger16(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask, bool acc,
+ bool neg_mul, bool neg_acc, extract_f16 extract)
+{
+ float32 r, aux_acc;
+ float64 psum, va, vb, vc, vd;
+ int i, j, xmsk_bit, ymsk_bit;
+ uint8_t pmsk = FIELD_EX32(mask, GER_MSK, PMSK),
+ xmsk = FIELD_EX32(mask, GER_MSK, XMSK),
+ ymsk = FIELD_EX32(mask, GER_MSK, YMSK);
+ float_status *excp_ptr = &env->fp_status;
+ for (i = 0, xmsk_bit = 1 << 3; i < 4; i++, xmsk_bit >>= 1) {
+ for (j = 0, ymsk_bit = 1 << 3; j < 4; j++, ymsk_bit >>= 1) {
+ if ((xmsk_bit & xmsk) && (ymsk_bit & ymsk)) {
+ va = !(pmsk & 2) ? float64_zero :
+ extract(a->VsrHF(2 * i), excp_ptr);
+ vb = !(pmsk & 2) ? float64_zero :
+ extract(b->VsrHF(2 * j), excp_ptr);
+ vc = !(pmsk & 1) ? float64_zero :
+ extract(a->VsrHF(2 * i + 1), excp_ptr);
+ vd = !(pmsk & 1) ? float64_zero :
+ extract(b->VsrHF(2 * j + 1), excp_ptr);
+ psum = float64_mul(va, vb, excp_ptr);
+ psum = float64r32_muladd(vc, vd, psum, 0, excp_ptr);
+ r = float64_to_float32(psum, excp_ptr);
+ if (acc) {
+ aux_acc = at[i].VsrSF(j);
+ if (neg_mul) {
+ r = bfp32_neg(r);
+ }
+ if (neg_acc) {
+ aux_acc = bfp32_neg(aux_acc);
+ }
+ r = float32_add(r, aux_acc, excp_ptr);
+ }
+ at[i].VsrSF(j) = r;
+ } else {
+ at[i].VsrSF(j) = float32_zero;
+ }
+ }
+ }
+ vsxger_excp(env, GETPC());
+}
+
+typedef void vsxger_zero(ppc_vsr_t *at, int, int);
+
+typedef void vsxger_muladd_f(ppc_vsr_t *, ppc_vsr_t *, ppc_vsr_t *, int, int,
+ int flags, float_status *s);
+
+static void vsxger_muladd32(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
+ int j, int flags, float_status *s)
+{
+ at[i].VsrSF(j) = float32_muladd(a->VsrSF(i), b->VsrSF(j),
+ at[i].VsrSF(j), flags, s);
+}
+
+static void vsxger_mul32(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
+ int j, int flags, float_status *s)
+{
+ at[i].VsrSF(j) = float32_mul(a->VsrSF(i), b->VsrSF(j), s);
+}
+
+static void vsxger_zero32(ppc_vsr_t *at, int i, int j)
+{
+ at[i].VsrSF(j) = float32_zero;
+}
+
+static void vsxger_muladd64(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
+ int j, int flags, float_status *s)
+{
+ if (j >= 2) {
+ j -= 2;
+ at[i].VsrDF(j) = float64_muladd(a[i / 2].VsrDF(i % 2), b->VsrDF(j),
+ at[i].VsrDF(j), flags, s);
+ }
+}
+
+static void vsxger_mul64(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
+ int j, int flags, float_status *s)
+{
+ if (j >= 2) {
+ j -= 2;
+ at[i].VsrDF(j) = float64_mul(a[i / 2].VsrDF(i % 2), b->VsrDF(j), s);
+ }
+}
+
+static void vsxger_zero64(ppc_vsr_t *at, int i, int j)
+{
+ if (j >= 2) {
+ j -= 2;
+ at[i].VsrDF(j) = float64_zero;
+ }
+}
+
+static void vsxger(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask, bool acc, bool neg_mul,
+ bool neg_acc, vsxger_muladd_f mul, vsxger_muladd_f muladd,
+ vsxger_zero zero)
+{
+ int i, j, xmsk_bit, ymsk_bit, op_flags;
+ uint8_t xmsk = mask & 0x0F;
+ uint8_t ymsk = (mask >> 4) & 0x0F;
+ float_status *excp_ptr = &env->fp_status;
+ op_flags = (neg_acc ^ neg_mul) ? float_muladd_negate_c : 0;
+ op_flags |= (neg_mul) ? float_muladd_negate_result : 0;
+ helper_reset_fpstatus(env);
+ for (i = 0, xmsk_bit = 1 << 3; i < 4; i++, xmsk_bit >>= 1) {
+ for (j = 0, ymsk_bit = 1 << 3; j < 4; j++, ymsk_bit >>= 1) {
+ if ((xmsk_bit & xmsk) && (ymsk_bit & ymsk)) {
+ if (acc) {
+ muladd(at, a, b, i, j, op_flags, excp_ptr);
+ } else {
+ mul(at, a, b, i, j, op_flags, excp_ptr);
+ }
+ } else {
+ zero(at, i, j);
+ }
+ }
+ }
+ vsxger_excp(env, GETPC());
+}
+
+QEMU_FLATTEN
+void helper_XVBF16GER2(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, false, false, false, extract_bf16);
+}
+
+QEMU_FLATTEN
+void helper_XVBF16GER2PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, true, false, false, extract_bf16);
+}
+
+QEMU_FLATTEN
+void helper_XVBF16GER2PN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, true, false, true, extract_bf16);
+}
+
+QEMU_FLATTEN
+void helper_XVBF16GER2NP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, true, true, false, extract_bf16);
+}
+
+QEMU_FLATTEN
+void helper_XVBF16GER2NN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, true, true, true, extract_bf16);
+}
+
+QEMU_FLATTEN
+void helper_XVF16GER2(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, false, false, false, extract_hf16);
+}
+
+QEMU_FLATTEN
+void helper_XVF16GER2PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, true, false, false, extract_hf16);
+}
+
+QEMU_FLATTEN
+void helper_XVF16GER2PN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, true, false, true, extract_hf16);
+}
+
+QEMU_FLATTEN
+void helper_XVF16GER2NP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, true, true, false, extract_hf16);
+}
+
+QEMU_FLATTEN
+void helper_XVF16GER2NN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger16(env, a, b, at, mask, true, true, true, extract_hf16);
+}
+
+QEMU_FLATTEN
+void helper_XVF32GER(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, false, false, false, vsxger_mul32,
+ vsxger_muladd32, vsxger_zero32);
+}
+
+QEMU_FLATTEN
+void helper_XVF32GERPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, true, false, false, vsxger_mul32,
+ vsxger_muladd32, vsxger_zero32);
+}
+
+QEMU_FLATTEN
+void helper_XVF32GERPN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, true, false, true, vsxger_mul32,
+ vsxger_muladd32, vsxger_zero32);
+}
+
+QEMU_FLATTEN
+void helper_XVF32GERNP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, true, true, false, vsxger_mul32,
+ vsxger_muladd32, vsxger_zero32);
+}
+
+QEMU_FLATTEN
+void helper_XVF32GERNN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, true, true, true, vsxger_mul32,
+ vsxger_muladd32, vsxger_zero32);
+}
+
+QEMU_FLATTEN
+void helper_XVF64GER(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, false, false, false, vsxger_mul64,
+ vsxger_muladd64, vsxger_zero64);
+}
+
+QEMU_FLATTEN
+void helper_XVF64GERPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, true, false, false, vsxger_mul64,
+ vsxger_muladd64, vsxger_zero64);
+}
+
+QEMU_FLATTEN
+void helper_XVF64GERPN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, true, false, true, vsxger_mul64,
+ vsxger_muladd64, vsxger_zero64);
+}
+
+QEMU_FLATTEN
+void helper_XVF64GERNP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, true, true, false, vsxger_mul64,
+ vsxger_muladd64, vsxger_zero64);
+}
+
+QEMU_FLATTEN
+void helper_XVF64GERNN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ vsxger(env, a, b, at, mask, true, true, true, vsxger_mul64,
+ vsxger_muladd64, vsxger_zero64);
}
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index aa6773c..6233e28 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -59,8 +59,8 @@
DEF_HELPER_FLAGS_1(popcntw, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_2(bpermd, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_3(srad, tl, env, tl, tl)
-DEF_HELPER_0(darn32, tl)
-DEF_HELPER_0(darn64, tl)
+DEF_HELPER_FLAGS_0(darn32, TCG_CALL_NO_RWG, tl)
+DEF_HELPER_FLAGS_0(darn64, TCG_CALL_NO_RWG, tl)
#endif
DEF_HELPER_FLAGS_1(cntlsw32, TCG_CALL_NO_RWG_SE, i32, i32)
@@ -120,7 +120,7 @@
DEF_HELPER_2(fres, i64, env, i64)
DEF_HELPER_2(frsqrte, i64, env, i64)
DEF_HELPER_2(frsqrtes, i64, env, i64)
-DEF_HELPER_4(fsel, i64, env, i64, i64, i64)
+DEF_HELPER_FLAGS_3(FSEL, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
DEF_HELPER_FLAGS_2(ftdiv, TCG_CALL_NO_RWG_SE, i32, i64, i64)
DEF_HELPER_FLAGS_1(ftsqrt, TCG_CALL_NO_RWG_SE, i32, i64)
@@ -133,15 +133,19 @@
#define dh_ctype_vsr ppc_vsr_t *
#define dh_typecode_vsr dh_typecode_ptr
-DEF_HELPER_3(vavgub, void, avr, avr, avr)
-DEF_HELPER_3(vavguh, void, avr, avr, avr)
-DEF_HELPER_3(vavguw, void, avr, avr, avr)
-DEF_HELPER_3(vabsdub, void, avr, avr, avr)
-DEF_HELPER_3(vabsduh, void, avr, avr, avr)
-DEF_HELPER_3(vabsduw, void, avr, avr, avr)
-DEF_HELPER_3(vavgsb, void, avr, avr, avr)
-DEF_HELPER_3(vavgsh, void, avr, avr, avr)
-DEF_HELPER_3(vavgsw, void, avr, avr, avr)
+#define dh_alias_acc ptr
+#define dh_ctype_acc ppc_acc_t *
+#define dh_typecode_acc dh_typecode_ptr
+
+DEF_HELPER_FLAGS_3(vavgub, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vavguh, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vavguw, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vabsdub, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vabsduh, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vabsduw, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vavgsb, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vavgsh, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vavgsw, TCG_CALL_NO_RWG, void, avr, avr, avr)
DEF_HELPER_4(vcmpeqfp, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpgefp, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpgtfp, void, env, avr, avr, avr)
@@ -153,12 +157,12 @@
DEF_HELPER_4(vcmpgefp_dot, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpgtfp_dot, void, env, avr, avr, avr)
DEF_HELPER_4(vcmpbfp_dot, void, env, avr, avr, avr)
-DEF_HELPER_3(vmrglb, void, avr, avr, avr)
-DEF_HELPER_3(vmrglh, void, avr, avr, avr)
-DEF_HELPER_3(vmrglw, void, avr, avr, avr)
-DEF_HELPER_3(vmrghb, void, avr, avr, avr)
-DEF_HELPER_3(vmrghh, void, avr, avr, avr)
-DEF_HELPER_3(vmrghw, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vmrglb, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vmrglh, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vmrglw, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vmrghb, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vmrghh, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vmrghw, TCG_CALL_NO_RWG, void, avr, avr, avr)
DEF_HELPER_FLAGS_3(VMULESB, TCG_CALL_NO_RWG, void, avr, avr, avr)
DEF_HELPER_FLAGS_3(VMULESH, TCG_CALL_NO_RWG, void, avr, avr, avr)
DEF_HELPER_FLAGS_3(VMULESW, TCG_CALL_NO_RWG, void, avr, avr, avr)
@@ -171,15 +175,15 @@
DEF_HELPER_FLAGS_3(VMULOUB, TCG_CALL_NO_RWG, void, avr, avr, avr)
DEF_HELPER_FLAGS_3(VMULOUH, TCG_CALL_NO_RWG, void, avr, avr, avr)
DEF_HELPER_FLAGS_3(VMULOUW, TCG_CALL_NO_RWG, void, avr, avr, avr)
-DEF_HELPER_3(vslo, void, avr, avr, avr)
-DEF_HELPER_3(vsro, void, avr, avr, avr)
-DEF_HELPER_3(vsrv, void, avr, avr, avr)
-DEF_HELPER_3(vslv, void, avr, avr, avr)
-DEF_HELPER_3(vaddcuw, void, avr, avr, avr)
-DEF_HELPER_2(vprtybw, void, avr, avr)
-DEF_HELPER_2(vprtybd, void, avr, avr)
-DEF_HELPER_2(vprtybq, void, avr, avr)
-DEF_HELPER_3(vsubcuw, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vslo, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vsro, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vsrv, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vslv, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vaddcuw, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_2(vprtybw, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vprtybd, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vprtybq, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_3(vsubcuw, TCG_CALL_NO_RWG, void, avr, avr, avr)
DEF_HELPER_FLAGS_5(vaddsbs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
DEF_HELPER_FLAGS_5(vaddshs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
DEF_HELPER_FLAGS_5(vaddsws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
@@ -192,19 +196,19 @@
DEF_HELPER_FLAGS_5(vsububs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
DEF_HELPER_FLAGS_5(vsubuhs, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
DEF_HELPER_FLAGS_5(vsubuws, TCG_CALL_NO_RWG, void, avr, avr, avr, avr, i32)
-DEF_HELPER_3(vadduqm, void, avr, avr, avr)
-DEF_HELPER_4(vaddecuq, void, avr, avr, avr, avr)
-DEF_HELPER_4(vaddeuqm, void, avr, avr, avr, avr)
-DEF_HELPER_3(vaddcuq, void, avr, avr, avr)
-DEF_HELPER_3(vsubuqm, void, avr, avr, avr)
-DEF_HELPER_4(vsubecuq, void, avr, avr, avr, avr)
-DEF_HELPER_4(vsubeuqm, void, avr, avr, avr, avr)
-DEF_HELPER_3(vsubcuq, void, avr, avr, avr)
-DEF_HELPER_4(vsldoi, void, avr, avr, avr, i32)
-DEF_HELPER_3(vextractub, void, avr, avr, i32)
-DEF_HELPER_3(vextractuh, void, avr, avr, i32)
-DEF_HELPER_3(vextractuw, void, avr, avr, i32)
-DEF_HELPER_3(vextractd, void, avr, avr, i32)
+DEF_HELPER_FLAGS_3(vadduqm, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_4(vaddecuq, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(vaddeuqm, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vaddcuq, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vsubuqm, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_4(vsubecuq, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(vsubeuqm, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vsubcuq, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_4(vsldoi, TCG_CALL_NO_RWG, void, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_3(vextractub, TCG_CALL_NO_RWG, void, avr, avr, i32)
+DEF_HELPER_FLAGS_3(vextractuh, TCG_CALL_NO_RWG, void, avr, avr, i32)
+DEF_HELPER_FLAGS_3(vextractuw, TCG_CALL_NO_RWG, void, avr, avr, i32)
+DEF_HELPER_FLAGS_3(vextractd, TCG_CALL_NO_RWG, void, avr, avr, i32)
DEF_HELPER_4(VINSBLX, void, env, avr, i64, tl)
DEF_HELPER_4(VINSHLX, void, env, avr, i64, tl)
DEF_HELPER_4(VINSWLX, void, env, avr, i64, tl)
@@ -213,18 +217,18 @@
DEF_HELPER_FLAGS_2(VSTRIBR, TCG_CALL_NO_RWG, i32, avr, avr)
DEF_HELPER_FLAGS_2(VSTRIHL, TCG_CALL_NO_RWG, i32, avr, avr)
DEF_HELPER_FLAGS_2(VSTRIHR, TCG_CALL_NO_RWG, i32, avr, avr)
-DEF_HELPER_2(vnegw, void, avr, avr)
-DEF_HELPER_2(vnegd, void, avr, avr)
-DEF_HELPER_2(vupkhpx, void, avr, avr)
-DEF_HELPER_2(vupklpx, void, avr, avr)
-DEF_HELPER_2(vupkhsb, void, avr, avr)
-DEF_HELPER_2(vupkhsh, void, avr, avr)
-DEF_HELPER_2(vupkhsw, void, avr, avr)
-DEF_HELPER_2(vupklsb, void, avr, avr)
-DEF_HELPER_2(vupklsh, void, avr, avr)
-DEF_HELPER_2(vupklsw, void, avr, avr)
-DEF_HELPER_5(vmsumubm, void, env, avr, avr, avr, avr)
-DEF_HELPER_5(vmsummbm, void, env, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_2(vnegw, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vnegd, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vupkhpx, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vupklpx, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vupkhsb, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vupkhsh, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vupkhsw, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vupklsb, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vupklsh, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vupklsw, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_4(VMSUMUBM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(VMSUMMBM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
DEF_HELPER_FLAGS_4(VPERM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
DEF_HELPER_FLAGS_4(VPERMR, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
DEF_HELPER_4(vpkshss, void, env, avr, avr, avr)
@@ -239,14 +243,14 @@
DEF_HELPER_4(vpkuhum, void, env, avr, avr, avr)
DEF_HELPER_4(vpkuwum, void, env, avr, avr, avr)
DEF_HELPER_4(vpkudum, void, env, avr, avr, avr)
-DEF_HELPER_3(vpkpx, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vpkpx, TCG_CALL_NO_RWG, void, avr, avr, avr)
DEF_HELPER_5(vmhaddshs, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vmhraddshs, void, env, avr, avr, avr, avr)
-DEF_HELPER_5(vmsumuhm, void, env, avr, avr, avr, avr)
-DEF_HELPER_5(vmsumuhs, void, env, avr, avr, avr, avr)
-DEF_HELPER_5(vmsumshm, void, env, avr, avr, avr, avr)
-DEF_HELPER_5(vmsumshs, void, env, avr, avr, avr, avr)
-DEF_HELPER_4(vmladduhm, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(VMSUMUHM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_5(VMSUMUHS, void, env, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(VMSUMSHM, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
+DEF_HELPER_5(VMSUMSHS, void, env, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_4(vmladduhm, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
DEF_HELPER_FLAGS_2(mtvscr, TCG_CALL_NO_RWG, void, env, i32)
DEF_HELPER_FLAGS_1(mfvscr, TCG_CALL_NO_RWG, i32, env)
DEF_HELPER_3(lvebx, void, env, avr, tl)
@@ -289,59 +293,59 @@
DEF_HELPER_4(vctuxs, void, env, avr, avr, i32)
DEF_HELPER_4(vctsxs, void, env, avr, avr, i32)
-DEF_HELPER_2(vclzb, void, avr, avr)
-DEF_HELPER_2(vclzh, void, avr, avr)
-DEF_HELPER_2(vctzb, void, avr, avr)
-DEF_HELPER_2(vctzh, void, avr, avr)
-DEF_HELPER_2(vctzw, void, avr, avr)
-DEF_HELPER_2(vctzd, void, avr, avr)
-DEF_HELPER_2(vpopcntb, void, avr, avr)
-DEF_HELPER_2(vpopcnth, void, avr, avr)
-DEF_HELPER_2(vpopcntw, void, avr, avr)
-DEF_HELPER_2(vpopcntd, void, avr, avr)
-DEF_HELPER_1(vclzlsbb, tl, avr)
-DEF_HELPER_1(vctzlsbb, tl, avr)
-DEF_HELPER_3(vbpermd, void, avr, avr, avr)
-DEF_HELPER_3(vbpermq, void, avr, avr, avr)
-DEF_HELPER_3(vpmsumb, void, avr, avr, avr)
-DEF_HELPER_3(vpmsumh, void, avr, avr, avr)
-DEF_HELPER_3(vpmsumw, void, avr, avr, avr)
-DEF_HELPER_3(vpmsumd, void, avr, avr, avr)
-DEF_HELPER_2(vextublx, tl, tl, avr)
-DEF_HELPER_2(vextuhlx, tl, tl, avr)
-DEF_HELPER_2(vextuwlx, tl, tl, avr)
-DEF_HELPER_2(vextubrx, tl, tl, avr)
-DEF_HELPER_2(vextuhrx, tl, tl, avr)
-DEF_HELPER_2(vextuwrx, tl, tl, avr)
+DEF_HELPER_FLAGS_2(vclzb, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vclzh, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vctzb, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vctzh, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vctzw, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vctzd, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vpopcntb, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vpopcnth, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vpopcntw, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_2(vpopcntd, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_1(vclzlsbb, TCG_CALL_NO_RWG, tl, avr)
+DEF_HELPER_FLAGS_1(vctzlsbb, TCG_CALL_NO_RWG, tl, avr)
+DEF_HELPER_FLAGS_3(vbpermd, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vbpermq, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vpmsumb, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vpmsumh, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vpmsumw, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vpmsumd, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_2(vextublx, TCG_CALL_NO_RWG, tl, tl, avr)
+DEF_HELPER_FLAGS_2(vextuhlx, TCG_CALL_NO_RWG, tl, tl, avr)
+DEF_HELPER_FLAGS_2(vextuwlx, TCG_CALL_NO_RWG, tl, tl, avr)
+DEF_HELPER_FLAGS_2(vextubrx, TCG_CALL_NO_RWG, tl, tl, avr)
+DEF_HELPER_FLAGS_2(vextuhrx, TCG_CALL_NO_RWG, tl, tl, avr)
+DEF_HELPER_FLAGS_2(vextuwrx, TCG_CALL_NO_RWG, tl, tl, avr)
DEF_HELPER_5(VEXTDUBVLX, void, env, avr, avr, avr, tl)
DEF_HELPER_5(VEXTDUHVLX, void, env, avr, avr, avr, tl)
DEF_HELPER_5(VEXTDUWVLX, void, env, avr, avr, avr, tl)
DEF_HELPER_5(VEXTDDVLX, void, env, avr, avr, avr, tl)
-DEF_HELPER_2(vsbox, void, avr, avr)
-DEF_HELPER_3(vcipher, void, avr, avr, avr)
-DEF_HELPER_3(vcipherlast, void, avr, avr, avr)
-DEF_HELPER_3(vncipher, void, avr, avr, avr)
-DEF_HELPER_3(vncipherlast, void, avr, avr, avr)
-DEF_HELPER_3(vshasigmaw, void, avr, avr, i32)
-DEF_HELPER_3(vshasigmad, void, avr, avr, i32)
-DEF_HELPER_4(vpermxor, void, avr, avr, avr, avr)
+DEF_HELPER_FLAGS_2(vsbox, TCG_CALL_NO_RWG, void, avr, avr)
+DEF_HELPER_FLAGS_3(vcipher, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vcipherlast, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vncipher, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vncipherlast, TCG_CALL_NO_RWG, void, avr, avr, avr)
+DEF_HELPER_FLAGS_3(vshasigmaw, TCG_CALL_NO_RWG, void, avr, avr, i32)
+DEF_HELPER_FLAGS_3(vshasigmad, TCG_CALL_NO_RWG, void, avr, avr, i32)
+DEF_HELPER_FLAGS_4(vpermxor, TCG_CALL_NO_RWG, void, avr, avr, avr, avr)
-DEF_HELPER_4(bcdadd, i32, avr, avr, avr, i32)
-DEF_HELPER_4(bcdsub, i32, avr, avr, avr, i32)
-DEF_HELPER_3(bcdcfn, i32, avr, avr, i32)
-DEF_HELPER_3(bcdctn, i32, avr, avr, i32)
-DEF_HELPER_3(bcdcfz, i32, avr, avr, i32)
-DEF_HELPER_3(bcdctz, i32, avr, avr, i32)
-DEF_HELPER_3(bcdcfsq, i32, avr, avr, i32)
-DEF_HELPER_3(bcdctsq, i32, avr, avr, i32)
-DEF_HELPER_4(bcdcpsgn, i32, avr, avr, avr, i32)
-DEF_HELPER_3(bcdsetsgn, i32, avr, avr, i32)
-DEF_HELPER_4(bcds, i32, avr, avr, avr, i32)
-DEF_HELPER_4(bcdus, i32, avr, avr, avr, i32)
-DEF_HELPER_4(bcdsr, i32, avr, avr, avr, i32)
-DEF_HELPER_4(bcdtrunc, i32, avr, avr, avr, i32)
-DEF_HELPER_4(bcdutrunc, i32, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_4(bcdadd, TCG_CALL_NO_RWG, i32, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_4(bcdsub, TCG_CALL_NO_RWG, i32, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_3(bcdcfn, TCG_CALL_NO_RWG, i32, avr, avr, i32)
+DEF_HELPER_FLAGS_3(bcdctn, TCG_CALL_NO_RWG, i32, avr, avr, i32)
+DEF_HELPER_FLAGS_3(bcdcfz, TCG_CALL_NO_RWG, i32, avr, avr, i32)
+DEF_HELPER_FLAGS_3(bcdctz, TCG_CALL_NO_RWG, i32, avr, avr, i32)
+DEF_HELPER_FLAGS_3(bcdcfsq, TCG_CALL_NO_RWG, i32, avr, avr, i32)
+DEF_HELPER_FLAGS_3(bcdctsq, TCG_CALL_NO_RWG, i32, avr, avr, i32)
+DEF_HELPER_FLAGS_4(bcdcpsgn, TCG_CALL_NO_RWG, i32, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_3(bcdsetsgn, TCG_CALL_NO_RWG, i32, avr, avr, i32)
+DEF_HELPER_FLAGS_4(bcds, TCG_CALL_NO_RWG, i32, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_4(bcdus, TCG_CALL_NO_RWG, i32, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_4(bcdsr, TCG_CALL_NO_RWG, i32, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_4(bcdtrunc, TCG_CALL_NO_RWG, i32, avr, avr, avr, i32)
+DEF_HELPER_FLAGS_4(bcdutrunc, TCG_CALL_NO_RWG, i32, avr, avr, avr, i32)
DEF_HELPER_4(xsadddp, void, env, vsr, vsr, vsr)
DEF_HELPER_5(xsaddqp, void, env, i32, vsr, vsr, vsr)
@@ -395,7 +399,7 @@
DEF_HELPER_3(xscvhpdp, void, env, vsr, vsr)
DEF_HELPER_4(xscvsdqp, void, env, i32, vsr, vsr)
DEF_HELPER_3(xscvspdp, void, env, vsr, vsr)
-DEF_HELPER_2(xscvspdpn, i64, env, i64)
+DEF_HELPER_FLAGS_1(XSCVSPDPN, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_3(xscvdpsxds, void, env, vsr, vsr)
DEF_HELPER_3(xscvdpsxws, void, env, vsr, vsr)
DEF_HELPER_3(xscvdpuxds, void, env, vsr, vsr)
@@ -528,15 +532,44 @@
DEF_HELPER_FLAGS_2(XXGENPCVDM_be_comp, TCG_CALL_NO_RWG, void, vsr, avr)
DEF_HELPER_FLAGS_2(XXGENPCVDM_le_exp, TCG_CALL_NO_RWG, void, vsr, avr)
DEF_HELPER_FLAGS_2(XXGENPCVDM_le_comp, TCG_CALL_NO_RWG, void, vsr, avr)
-DEF_HELPER_4(xxextractuw, void, env, vsr, vsr, i32)
+DEF_HELPER_FLAGS_3(XXEXTRACTUW, TCG_CALL_NO_RWG, void, vsr, vsr, i32)
DEF_HELPER_FLAGS_5(XXPERMX, TCG_CALL_NO_RWG, void, vsr, vsr, vsr, vsr, tl)
-DEF_HELPER_4(xxinsertw, void, env, vsr, vsr, i32)
-DEF_HELPER_3(xvxsigsp, void, env, vsr, vsr)
+DEF_HELPER_FLAGS_3(XXINSERTW, TCG_CALL_NO_RWG, void, vsr, vsr, i32)
+DEF_HELPER_FLAGS_2(XVXSIGSP, TCG_CALL_NO_RWG, void, vsr, vsr)
DEF_HELPER_FLAGS_5(XXEVAL, TCG_CALL_NO_RWG, void, vsr, vsr, vsr, vsr, i32)
-DEF_HELPER_5(XXBLENDVB, void, vsr, vsr, vsr, vsr, i32)
-DEF_HELPER_5(XXBLENDVH, void, vsr, vsr, vsr, vsr, i32)
-DEF_HELPER_5(XXBLENDVW, void, vsr, vsr, vsr, vsr, i32)
-DEF_HELPER_5(XXBLENDVD, void, vsr, vsr, vsr, vsr, i32)
+DEF_HELPER_FLAGS_5(XXBLENDVB, TCG_CALL_NO_RWG, void, vsr, vsr, vsr, vsr, i32)
+DEF_HELPER_FLAGS_5(XXBLENDVH, TCG_CALL_NO_RWG, void, vsr, vsr, vsr, vsr, i32)
+DEF_HELPER_FLAGS_5(XXBLENDVW, TCG_CALL_NO_RWG, void, vsr, vsr, vsr, vsr, i32)
+DEF_HELPER_FLAGS_5(XXBLENDVD, TCG_CALL_NO_RWG, void, vsr, vsr, vsr, vsr, i32)
+DEF_HELPER_5(XVI4GER8, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVI4GER8PP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVI8GER4, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVI8GER4PP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVI8GER4SPP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVI16GER2, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVI16GER2S, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVI16GER2PP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVI16GER2SPP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF16GER2, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF16GER2PP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF16GER2PN, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF16GER2NP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF16GER2NN, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVBF16GER2, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVBF16GER2PP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVBF16GER2PN, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVBF16GER2NP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVBF16GER2NN, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF32GER, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF32GERPP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF32GERPN, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF32GERNP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF32GERNN, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF64GER, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF64GERPP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF64GERPN, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF64GERNP, void, env, vsr, vsr, acc, i32)
+DEF_HELPER_5(XVF64GERNN, void, env, vsr, vsr, acc, i32)
DEF_HELPER_2(efscfsi, i32, env, i32)
DEF_HELPER_2(efscfui, i32, env, i32)
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index 6159a15..12235ea 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -292,7 +292,7 @@
if (global && (env->tlb_need_flush & TLB_NEED_GLOBAL_FLUSH)) {
env->tlb_need_flush &= ~TLB_NEED_GLOBAL_FLUSH;
env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
- tlb_flush_all_cpus_synced(cs);
+ tlb_flush_all_cpus(cs);
return;
}
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 39372fe..18a94fa 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -17,6 +17,9 @@
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
#
+&A frt fra frb frc rc:bool
+@A ...... frt:5 fra:5 frb:5 frc:5 ..... rc:1 &A
+
&D rt ra si:int64_t
@D ...... rt:5 ra:5 si:s16 &D
@@ -151,6 +154,9 @@
&X_vrt_frbp vrt frbp
@X_vrt_frbp ...... vrt:5 ..... ....0 .......... . &X_vrt_frbp frbp=%x_frbp
+&X_a ra
+@X_a ...... ra:3 .. ..... ..... .......... . &X_a
+
%xx_xt 0:1 21:5
%xx_xb 1:1 11:5
%xx_xa 2:1 16:5
@@ -158,8 +164,10 @@
&XX2 xt xb
@XX2 ...... ..... ..... ..... ......... .. &XX2 xt=%xx_xt xb=%xx_xb
-&XX2_uim2 xt xb uim:uint8_t
-@XX2_uim2 ...... ..... ... uim:2 ..... ......... .. &XX2_uim2 xt=%xx_xt xb=%xx_xb
+&XX2_uim xt xb uim:uint8_t
+@XX2_uim2 ...... ..... ... uim:2 ..... ......... .. &XX2_uim xt=%xx_xt xb=%xx_xb
+
+@XX2_uim4 ...... ..... . uim:4 ..... ......... .. &XX2_uim xt=%xx_xt xb=%xx_xb
&XX2_bf_xb bf xb
@XX2_bf_xb ...... bf:3 .. ..... ..... ......... . . &XX2_bf_xb xb=%xx_xb
@@ -167,6 +175,13 @@
&XX3 xt xa xb
@XX3 ...... ..... ..... ..... ........ ... &XX3 xt=%xx_xt xa=%xx_xa xb=%xx_xb
+# 32 bit GER instructions have all mask bits considered 1
+&MMIRR_XX3 xa xb xt pmsk xmsk ymsk
+%xx_at 23:3
+%xx_xa_pair 2:1 17:4 !function=times_2
+@XX3_at ...... ... .. ..... ..... ........ ... &MMIRR_XX3 xt=%xx_at xb=%xx_xb \
+ pmsk=255 xmsk=15 ymsk=15
+
&XX3_dm xt xa xb dm
@XX3_dm ...... ..... ..... ..... . dm:2 ..... ... &XX3_dm xt=%xx_xt xa=%xx_xa xb=%xx_xb
@@ -308,6 +323,10 @@
STFDX 011111 ..... ...... .... 1011010111 - @X
STFDUX 011111 ..... ...... .... 1011110111 - @X
+### Floating-Point Select Instruction
+
+FSEL 111111 ..... ..... ..... ..... 10111 . @A
+
### Move To/From System Register Instructions
SETBC 011111 ..... ..... ----- 0110000000 - @X_bi
@@ -590,6 +609,13 @@
## Vector Multiply-Sum Instructions
+VMSUMUBM 000100 ..... ..... ..... ..... 100100 @VA
+VMSUMMBM 000100 ..... ..... ..... ..... 100101 @VA
+VMSUMSHM 000100 ..... ..... ..... ..... 101000 @VA
+VMSUMSHS 000100 ..... ..... ..... ..... 101001 @VA
+VMSUMUHM 000100 ..... ..... ..... ..... 100110 @VA
+VMSUMUHS 000100 ..... ..... ..... ..... 100111 @VA
+
VMSUMCUD 000100 ..... ..... ..... ..... 010111 @VA
VMSUMUDM 000100 ..... ..... ..... ..... 100011 @VA
@@ -659,6 +685,9 @@
## VSX Permute Instructions
+XXEXTRACTUW 111100 ..... - .... ..... 010100101 .. @XX2_uim4
+XXINSERTW 111100 ..... - .... ..... 010110101 .. @XX2_uim4
+
XXPERM 111100 ..... ..... ..... 00011010 ... @XX3
XXPERMR 111100 ..... ..... ..... 00111010 ... @XX3
XXPERMDI 111100 ..... ..... ..... 0 .. 01010 ... @XX3_dm
@@ -701,6 +730,11 @@
XSCVSQQP 111111 ..... 01011 ..... 1101000100 - @X_tb
XVCVBF16SPN 111100 ..... 10000 ..... 111011011 .. @XX2
XVCVSPBF16 111100 ..... 10001 ..... 111011011 .. @XX2
+XSCVSPDPN 111100 ..... ----- ..... 101001011 .. @XX2
+
+## VSX Binary Floating-Point Math Support Instructions
+
+XVXSIGSP 111100 ..... 01001 ..... 111011011 .. @XX2
## VSX Vector Test Least-Significant Bit by Byte Instruction
@@ -710,3 +744,45 @@
&XL_s s:uint8_t
@XL_s ......-------------- s:1 .......... - &XL_s
RFEBB 010011-------------- . 0010010010 - @XL_s
+
+## Accumulator Instructions
+
+XXMFACC 011111 ... -- 00000 ----- 0010110001 - @X_a
+XXMTACC 011111 ... -- 00001 ----- 0010110001 - @X_a
+XXSETACCZ 011111 ... -- 00011 ----- 0010110001 - @X_a
+
+## VSX GER instruction
+
+XVI4GER8 111011 ... -- ..... ..... 00100011 ..- @XX3_at xa=%xx_xa
+XVI4GER8PP 111011 ... -- ..... ..... 00100010 ..- @XX3_at xa=%xx_xa
+XVI8GER4 111011 ... -- ..... ..... 00000011 ..- @XX3_at xa=%xx_xa
+XVI8GER4PP 111011 ... -- ..... ..... 00000010 ..- @XX3_at xa=%xx_xa
+XVI16GER2 111011 ... -- ..... ..... 01001011 ..- @XX3_at xa=%xx_xa
+XVI16GER2PP 111011 ... -- ..... ..... 01101011 ..- @XX3_at xa=%xx_xa
+XVI8GER4SPP 111011 ... -- ..... ..... 01100011 ..- @XX3_at xa=%xx_xa
+XVI16GER2S 111011 ... -- ..... ..... 00101011 ..- @XX3_at xa=%xx_xa
+XVI16GER2SPP 111011 ... -- ..... ..... 00101010 ..- @XX3_at xa=%xx_xa
+
+XVBF16GER2 111011 ... -- ..... ..... 00110011 ..- @XX3_at xa=%xx_xa
+XVBF16GER2PP 111011 ... -- ..... ..... 00110010 ..- @XX3_at xa=%xx_xa
+XVBF16GER2PN 111011 ... -- ..... ..... 10110010 ..- @XX3_at xa=%xx_xa
+XVBF16GER2NP 111011 ... -- ..... ..... 01110010 ..- @XX3_at xa=%xx_xa
+XVBF16GER2NN 111011 ... -- ..... ..... 11110010 ..- @XX3_at xa=%xx_xa
+
+XVF16GER2 111011 ... -- ..... ..... 00010011 ..- @XX3_at xa=%xx_xa
+XVF16GER2PP 111011 ... -- ..... ..... 00010010 ..- @XX3_at xa=%xx_xa
+XVF16GER2PN 111011 ... -- ..... ..... 10010010 ..- @XX3_at xa=%xx_xa
+XVF16GER2NP 111011 ... -- ..... ..... 01010010 ..- @XX3_at xa=%xx_xa
+XVF16GER2NN 111011 ... -- ..... ..... 11010010 ..- @XX3_at xa=%xx_xa
+
+XVF32GER 111011 ... -- ..... ..... 00011011 ..- @XX3_at xa=%xx_xa
+XVF32GERPP 111011 ... -- ..... ..... 00011010 ..- @XX3_at xa=%xx_xa
+XVF32GERPN 111011 ... -- ..... ..... 10011010 ..- @XX3_at xa=%xx_xa
+XVF32GERNP 111011 ... -- ..... ..... 01011010 ..- @XX3_at xa=%xx_xa
+XVF32GERNN 111011 ... -- ..... ..... 11011010 ..- @XX3_at xa=%xx_xa
+
+XVF64GER 111011 ... -- .... 0 ..... 00111011 ..- @XX3_at xa=%xx_xa_pair
+XVF64GERPP 111011 ... -- .... 0 ..... 00111010 ..- @XX3_at xa=%xx_xa_pair
+XVF64GERPN 111011 ... -- .... 0 ..... 10111010 ..- @XX3_at xa=%xx_xa_pair
+XVF64GERNP 111011 ... -- .... 0 ..... 01111010 ..- @XX3_at xa=%xx_xa_pair
+XVF64GERNN 111011 ... -- .... 0 ..... 11111010 ..- @XX3_at xa=%xx_xa_pair
diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index 691e8fe..de115c1 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -68,6 +68,20 @@
...... ..... ..... ..... ..... .. .... \
&8RR_XX4_uim3 xt=%8rr_xx_xt xa=%8rr_xx_xa xb=%8rr_xx_xb xc=%8rr_xx_xc
+# Format MMIRR:XX3
+&MMIRR_XX3 !extern xa xb xt pmsk xmsk ymsk
+%xx3_xa 2:1 16:5
+%xx3_xb 1:1 11:5
+%xx3_at 23:3
+%xx3_xa_pair 2:1 17:4 !function=times_2
+@MMIRR_XX3 ...... .. .... .. . . ........ xmsk:4 ymsk:4 \
+ ...... ... .. ..... ..... ........ ... \
+ &MMIRR_XX3 xa=%xx3_xa xb=%xx3_xb xt=%xx3_at
+
+@MMIRR_XX3_NO_P ...... .. .... .. . . ........ xmsk:4 .... \
+ ...... ... .. ..... ..... ........ ... \
+ &MMIRR_XX3 xb=%xx3_xb xt=%xx3_at pmsk=1
+
### Fixed-Point Load Instructions
PLBZ 000001 10 0--.-- .................. \
@@ -115,6 +129,71 @@
PSTFD 000001 10 0--.-- .................. \
110110 ..... ..... ................ @PLS_D
+## VSX GER instruction
+
+PMXVI4GER8 000001 11 1001 -- - - pmsk:8 ........ \
+ 111011 ... -- ..... ..... 00100011 ..- @MMIRR_XX3
+PMXVI4GER8PP 000001 11 1001 -- - - pmsk:8 ........ \
+ 111011 ... -- ..... ..... 00100010 ..- @MMIRR_XX3
+PMXVI8GER4 000001 11 1001 -- - - pmsk:4 ---- ........ \
+ 111011 ... -- ..... ..... 00000011 ..- @MMIRR_XX3
+PMXVI8GER4PP 000001 11 1001 -- - - pmsk:4 ---- ........ \
+ 111011 ... -- ..... ..... 00000010 ..- @MMIRR_XX3
+PMXVI16GER2 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 01001011 ..- @MMIRR_XX3
+PMXVI16GER2PP 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 01101011 ..- @MMIRR_XX3
+PMXVI8GER4SPP 000001 11 1001 -- - - pmsk:4 ---- ........ \
+ 111011 ... -- ..... ..... 01100011 ..- @MMIRR_XX3
+PMXVI16GER2S 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 00101011 ..- @MMIRR_XX3
+PMXVI16GER2SPP 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 00101010 ..- @MMIRR_XX3
+
+PMXVBF16GER2 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 00110011 ..- @MMIRR_XX3
+PMXVBF16GER2PP 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 00110010 ..- @MMIRR_XX3
+PMXVBF16GER2PN 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 10110010 ..- @MMIRR_XX3
+PMXVBF16GER2NP 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 01110010 ..- @MMIRR_XX3
+PMXVBF16GER2NN 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 11110010 ..- @MMIRR_XX3
+
+PMXVF16GER2 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 00010011 ..- @MMIRR_XX3
+PMXVF16GER2PP 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 00010010 ..- @MMIRR_XX3
+PMXVF16GER2PN 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 10010010 ..- @MMIRR_XX3
+PMXVF16GER2NP 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 01010010 ..- @MMIRR_XX3
+PMXVF16GER2NN 000001 11 1001 -- - - pmsk:2 ------ ........ \
+ 111011 ... -- ..... ..... 11010010 ..- @MMIRR_XX3
+
+PMXVF32GER 000001 11 1001 -- - - -------- .... ymsk:4 \
+ 111011 ... -- ..... ..... 00011011 ..- @MMIRR_XX3_NO_P xa=%xx3_xa
+PMXVF32GERPP 000001 11 1001 -- - - -------- .... ymsk:4 \
+ 111011 ... -- ..... ..... 00011010 ..- @MMIRR_XX3_NO_P xa=%xx3_xa
+PMXVF32GERPN 000001 11 1001 -- - - -------- .... ymsk:4 \
+ 111011 ... -- ..... ..... 10011010 ..- @MMIRR_XX3_NO_P xa=%xx3_xa
+PMXVF32GERNP 000001 11 1001 -- - - -------- .... ymsk:4 \
+ 111011 ... -- ..... ..... 01011010 ..- @MMIRR_XX3_NO_P xa=%xx3_xa
+PMXVF32GERNN 000001 11 1001 -- - - -------- .... ymsk:4 \
+ 111011 ... -- ..... ..... 11011010 ..- @MMIRR_XX3_NO_P xa=%xx3_xa
+
+PMXVF64GER 000001 11 1001 -- - - -------- .... ymsk:2 -- \
+ 111011 ... -- ....0 ..... 00111011 ..- @MMIRR_XX3_NO_P xa=%xx3_xa_pair
+PMXVF64GERPP 000001 11 1001 -- - - -------- .... ymsk:2 -- \
+ 111011 ... -- ....0 ..... 00111010 ..- @MMIRR_XX3_NO_P xa=%xx3_xa_pair
+PMXVF64GERPN 000001 11 1001 -- - - -------- .... ymsk:2 -- \
+ 111011 ... -- ....0 ..... 10111010 ..- @MMIRR_XX3_NO_P xa=%xx3_xa_pair
+PMXVF64GERNP 000001 11 1001 -- - - -------- .... ymsk:2 -- \
+ 111011 ... -- ....0 ..... 01111010 ..- @MMIRR_XX3_NO_P xa=%xx3_xa_pair
+PMXVF64GERNN 000001 11 1001 -- - - -------- .... ymsk:2 -- \
+ 111011 ... -- ....0 ..... 11111010 ..- @MMIRR_XX3_NO_P xa=%xx3_xa_pair
+
### Prefixed No-operation Instruction
@PNOP 000001 11 0000-- 000000000000000000 \
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 8c16745..105b626 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -782,6 +782,136 @@
VCT(sxs, cvtsdsw, s32)
#undef VCT
+typedef int64_t do_ger(uint32_t, uint32_t, uint32_t);
+
+static int64_t ger_rank8(uint32_t a, uint32_t b, uint32_t mask)
+{
+ int64_t psum = 0;
+ for (int i = 0; i < 8; i++, mask >>= 1) {
+ if (mask & 1) {
+ psum += sextract32(a, 4 * i, 4) * sextract32(b, 4 * i, 4);
+ }
+ }
+ return psum;
+}
+
+static int64_t ger_rank4(uint32_t a, uint32_t b, uint32_t mask)
+{
+ int64_t psum = 0;
+ for (int i = 0; i < 4; i++, mask >>= 1) {
+ if (mask & 1) {
+ psum += sextract32(a, 8 * i, 8) * (int64_t)extract32(b, 8 * i, 8);
+ }
+ }
+ return psum;
+}
+
+static int64_t ger_rank2(uint32_t a, uint32_t b, uint32_t mask)
+{
+ int64_t psum = 0;
+ for (int i = 0; i < 2; i++, mask >>= 1) {
+ if (mask & 1) {
+ psum += sextract32(a, 16 * i, 16) * sextract32(b, 16 * i, 16);
+ }
+ }
+ return psum;
+}
+
+static void xviger(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b, ppc_acc_t *at,
+ uint32_t mask, bool sat, bool acc, do_ger ger)
+{
+ uint8_t pmsk = FIELD_EX32(mask, GER_MSK, PMSK),
+ xmsk = FIELD_EX32(mask, GER_MSK, XMSK),
+ ymsk = FIELD_EX32(mask, GER_MSK, YMSK);
+ uint8_t xmsk_bit, ymsk_bit;
+ int64_t psum;
+ int i, j;
+ for (i = 0, xmsk_bit = 1 << 3; i < 4; i++, xmsk_bit >>= 1) {
+ for (j = 0, ymsk_bit = 1 << 3; j < 4; j++, ymsk_bit >>= 1) {
+ if ((xmsk_bit & xmsk) && (ymsk_bit & ymsk)) {
+ psum = ger(a->VsrW(i), b->VsrW(j), pmsk);
+ if (acc) {
+ psum += at[i].VsrSW(j);
+ }
+ if (sat && psum > INT32_MAX) {
+ set_vscr_sat(env);
+ at[i].VsrSW(j) = INT32_MAX;
+ } else if (sat && psum < INT32_MIN) {
+ set_vscr_sat(env);
+ at[i].VsrSW(j) = INT32_MIN;
+ } else {
+ at[i].VsrSW(j) = (int32_t) psum;
+ }
+ } else {
+ at[i].VsrSW(j) = 0;
+ }
+ }
+ }
+}
+
+QEMU_FLATTEN
+void helper_XVI4GER8(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, false, false, ger_rank8);
+}
+
+QEMU_FLATTEN
+void helper_XVI4GER8PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, false, true, ger_rank8);
+}
+
+QEMU_FLATTEN
+void helper_XVI8GER4(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, false, false, ger_rank4);
+}
+
+QEMU_FLATTEN
+void helper_XVI8GER4PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, false, true, ger_rank4);
+}
+
+QEMU_FLATTEN
+void helper_XVI8GER4SPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, true, true, ger_rank4);
+}
+
+QEMU_FLATTEN
+void helper_XVI16GER2(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, false, false, ger_rank2);
+}
+
+QEMU_FLATTEN
+void helper_XVI16GER2S(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, true, false, ger_rank2);
+}
+
+QEMU_FLATTEN
+void helper_XVI16GER2PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, false, true, ger_rank2);
+}
+
+QEMU_FLATTEN
+void helper_XVI16GER2SPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
+ ppc_acc_t *at, uint32_t mask)
+{
+ xviger(env, a, b, at, mask, true, true, ger_rank2);
+}
+
target_ulong helper_vclzlsbb(ppc_avr_t *r)
{
target_ulong count = 0;
@@ -875,8 +1005,7 @@
#undef VMRG_DO
#undef VMRG
-void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
- ppc_avr_t *b, ppc_avr_t *c)
+void helper_VMSUMMBM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int32_t prod[16];
int i;
@@ -891,8 +1020,7 @@
}
}
-void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
- ppc_avr_t *b, ppc_avr_t *c)
+void helper_VMSUMSHM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int32_t prod[8];
int i;
@@ -906,7 +1034,7 @@
}
}
-void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
+void helper_VMSUMSHS(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
ppc_avr_t *b, ppc_avr_t *c)
{
int32_t prod[8];
@@ -928,8 +1056,7 @@
}
}
-void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
- ppc_avr_t *b, ppc_avr_t *c)
+void helper_VMSUMUBM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
uint16_t prod[16];
int i;
@@ -944,8 +1071,7 @@
}
}
-void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
- ppc_avr_t *b, ppc_avr_t *c)
+void helper_VMSUMUHM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
uint32_t prod[8];
int i;
@@ -959,7 +1085,7 @@
}
}
-void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
+void helper_VMSUMUHS(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
ppc_avr_t *b, ppc_avr_t *c)
{
uint32_t prod[8];
@@ -1647,8 +1773,7 @@
VSTRI(VSTRIHR, H, 8, false)
#undef VSTRI
-void helper_xxextractuw(CPUPPCState *env, ppc_vsr_t *xt,
- ppc_vsr_t *xb, uint32_t index)
+void helper_XXEXTRACTUW(ppc_vsr_t *xt, ppc_vsr_t *xb, uint32_t index)
{
ppc_vsr_t t = { };
size_t es = sizeof(uint32_t);
@@ -1663,8 +1788,7 @@
*xt = t;
}
-void helper_xxinsertw(CPUPPCState *env, ppc_vsr_t *xt,
- ppc_vsr_t *xb, uint32_t index)
+void helper_XXINSERTW(ppc_vsr_t *xt, ppc_vsr_t *xb, uint32_t index)
{
ppc_vsr_t t = *xt;
size_t es = sizeof(uint32_t);
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 8094e0b..2add128 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -18,6 +18,8 @@
#ifndef PPC_INTERNAL_H
#define PPC_INTERNAL_H
+#include "hw/registerfields.h"
+
#define FUNC_MASK(name, ret_type, size, max_val) \
static inline ret_type name(uint##size##_t start, \
uint##size##_t end) \
@@ -291,4 +293,17 @@
uintptr_t retaddr);
#endif
+FIELD(GER_MSK, XMSK, 0, 4)
+FIELD(GER_MSK, YMSK, 4, 4)
+FIELD(GER_MSK, PMSK, 8, 8)
+
+static inline int ger_pack_masks(int pmsk, int ymsk, int xmsk)
+{
+ int msk = 0;
+ msk = FIELD_DP32(msk, GER_MSK, XMSK, xmsk);
+ msk = FIELD_DP32(msk, GER_MSK, YMSK, ymsk);
+ msk = FIELD_DP32(msk, GER_MSK, PMSK, pmsk);
+ return msk;
+}
+
#endif /* PPC_INTERNAL_H */
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index 7104a5c..a7d9036 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -157,7 +157,8 @@
| PPC2_ATOMIC_ISA206 | PPC2_FP_CVT_ISA206
| PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207
| PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207
- | PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_TM;
+ | PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 | PPC2_TM
+ | PPC2_MEM_LWSYNC;
env->spr[SPR_LR] = env->lr;
env->spr[SPR_CTR] = env->ctr;
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index fa34f81..1d6daa4 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3513,7 +3513,32 @@
/* eieio */
static void gen_eieio(DisasContext *ctx)
{
- TCGBar bar = TCG_MO_LD_ST;
+ TCGBar bar = TCG_MO_ALL;
+
+ /*
+ * eieio has complex semanitcs. It provides memory ordering between
+ * operations in the set:
+ * - loads from CI memory.
+ * - stores to CI memory.
+ * - stores to WT memory.
+ *
+ * It separately also orders memory for operations in the set:
+ * - stores to cacheble memory.
+ *
+ * It also serializes instructions:
+ * - dcbt and dcbst.
+ *
+ * It separately serializes:
+ * - tlbie and tlbsync.
+ *
+ * And separately serializes:
+ * - slbieg, slbiag, and slbsync.
+ *
+ * The end result is that CI memory ordering requires TCG_MO_ALL
+ * and it is not possible to special-case more relaxed ordering for
+ * cacheable accesses. TCG_BAR_SC is required to provide this
+ * serialization.
+ */
/*
* POWER9 has a eieio instruction variant using bit 6 as a hint to
@@ -4016,8 +4041,13 @@
/* sync */
static void gen_sync(DisasContext *ctx)
{
+ TCGBar bar = TCG_MO_ALL;
uint32_t l = (ctx->opcode >> 21) & 3;
+ if ((l == 1) && (ctx->insns_flags2 & PPC2_MEM_LWSYNC)) {
+ bar = TCG_MO_LD_LD | TCG_MO_LD_ST | TCG_MO_ST_ST;
+ }
+
/*
* We may need to check for a pending TLB flush.
*
@@ -4029,7 +4059,8 @@
if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
gen_check_tlb_flush(ctx, true);
}
- tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
+
+ tcg_gen_mb(bar | TCG_BAR_SC);
}
/* wait */
diff --git a/target/ppc/translate/fp-impl.c.inc b/target/ppc/translate/fp-impl.c.inc
index cfb27bd..f9b58b8 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -222,8 +222,34 @@
tcg_temp_free_i64(t1);
}
-/* fsel */
-_GEN_FLOAT_ACB(sel, 0x3F, 0x17, 0, PPC_FLOAT_FSEL);
+static bool trans_FSEL(DisasContext *ctx, arg_A *a)
+{
+ TCGv_i64 t0, t1, t2;
+
+ REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSEL);
+ REQUIRE_FPU(ctx);
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+
+ get_fpr(t0, a->fra);
+ get_fpr(t1, a->frb);
+ get_fpr(t2, a->frc);
+
+ gen_helper_FSEL(t0, t0, t1, t2);
+ set_fpr(a->frt, t0);
+ if (a->rc) {
+ gen_set_cr1_from_fpscr(ctx);
+ }
+
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+ tcg_temp_free_i64(t2);
+
+ return true;
+}
+
/* fsub - fsubs */
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
/* Optional: */
diff --git a/target/ppc/translate/fp-ops.c.inc b/target/ppc/translate/fp-ops.c.inc
index 4260635..0538ab2 100644
--- a/target/ppc/translate/fp-ops.c.inc
+++ b/target/ppc/translate/fp-ops.c.inc
@@ -24,7 +24,6 @@
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
-_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
diff --git a/target/ppc/translate/vmx-impl.c.inc b/target/ppc/translate/vmx-impl.c.inc
index 764ac45..d7524c3 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -2553,20 +2553,17 @@
tcg_temp_free_ptr(rd);
}
-static bool trans_VPERM(DisasContext *ctx, arg_VA *a)
+static bool do_va_helper(DisasContext *ctx, arg_VA *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
{
TCGv_ptr vrt, vra, vrb, vrc;
-
- REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
REQUIRE_VECTOR(ctx);
vrt = gen_avr_ptr(a->vrt);
vra = gen_avr_ptr(a->vra);
vrb = gen_avr_ptr(a->vrb);
vrc = gen_avr_ptr(a->rc);
-
- gen_helper_VPERM(vrt, vra, vrb, vrc);
-
+ gen_helper(vrt, vra, vrb, vrc);
tcg_temp_free_ptr(vrt);
tcg_temp_free_ptr(vra);
tcg_temp_free_ptr(vrb);
@@ -2575,27 +2572,8 @@
return true;
}
-static bool trans_VPERMR(DisasContext *ctx, arg_VA *a)
-{
- TCGv_ptr vrt, vra, vrb, vrc;
-
- REQUIRE_INSNS_FLAGS2(ctx, ISA300);
- REQUIRE_VECTOR(ctx);
-
- vrt = gen_avr_ptr(a->vrt);
- vra = gen_avr_ptr(a->vra);
- vrb = gen_avr_ptr(a->vrb);
- vrc = gen_avr_ptr(a->rc);
-
- gen_helper_VPERMR(vrt, vra, vrb, vrc);
-
- tcg_temp_free_ptr(vrt);
- tcg_temp_free_ptr(vra);
- tcg_temp_free_ptr(vrb);
- tcg_temp_free_ptr(vrc);
-
- return true;
-}
+TRANS_FLAGS(ALTIVEC, VPERM, do_va_helper, gen_helper_VPERM)
+TRANS_FLAGS2(ISA300, VPERMR, do_va_helper, gen_helper_VPERMR)
static bool trans_VSEL(DisasContext *ctx, arg_VA *a)
{
@@ -2609,9 +2587,33 @@
return true;
}
-GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
-GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
-GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
+TRANS_FLAGS(ALTIVEC, VMSUMUBM, do_va_helper, gen_helper_VMSUMUBM)
+TRANS_FLAGS(ALTIVEC, VMSUMMBM, do_va_helper, gen_helper_VMSUMMBM)
+TRANS_FLAGS(ALTIVEC, VMSUMSHM, do_va_helper, gen_helper_VMSUMSHM)
+TRANS_FLAGS(ALTIVEC, VMSUMUHM, do_va_helper, gen_helper_VMSUMUHM)
+
+static bool do_va_env_helper(DisasContext *ctx, arg_VA *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ TCGv_ptr vrt, vra, vrb, vrc;
+ REQUIRE_VECTOR(ctx);
+
+ vrt = gen_avr_ptr(a->vrt);
+ vra = gen_avr_ptr(a->vra);
+ vrb = gen_avr_ptr(a->vrb);
+ vrc = gen_avr_ptr(a->rc);
+ gen_helper(cpu_env, vrt, vra, vrb, vrc);
+ tcg_temp_free_ptr(vrt);
+ tcg_temp_free_ptr(vra);
+ tcg_temp_free_ptr(vrb);
+ tcg_temp_free_ptr(vrc);
+
+ return true;
+}
+
+TRANS_FLAGS(ALTIVEC, VMSUMUHS, do_va_env_helper, gen_helper_VMSUMUHS)
+TRANS_FLAGS(ALTIVEC, VMSUMSHS, do_va_env_helper, gen_helper_VMSUMSHS)
+
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
GEN_VXFORM_NOA(vclzb, 1, 28)
diff --git a/target/ppc/translate/vmx-ops.c.inc b/target/ppc/translate/vmx-ops.c.inc
index d960648..d7cc578 100644
--- a/target/ppc/translate/vmx-ops.c.inc
+++ b/target/ppc/translate/vmx-ops.c.inc
@@ -221,13 +221,9 @@
GEN_VXFORM_UIMM(vctuxs, 5, 14),
GEN_VXFORM_UIMM(vctsxs, 5, 15),
-
#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
-GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18),
-GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19),
-GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20),
GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23),
GEN_VXFORM_DUAL(vclzb, vpopcntb, 1, 28, PPC_NONE, PPC2_ALTIVEC_207),
diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc
index 3692740..7acdbce 100644
--- a/target/ppc/translate/vsx-impl.c.inc
+++ b/target/ppc/translate/vsx-impl.c.inc
@@ -17,6 +17,13 @@
return r;
}
+static inline TCGv_ptr gen_acc_ptr(int reg)
+{
+ TCGv_ptr r = tcg_temp_new_ptr();
+ tcg_gen_addi_ptr(r, cpu_env, acc_full_offset(reg));
+ return r;
+}
+
#define VSX_LOAD_SCALAR(name, operation) \
static void gen_##name(DisasContext *ctx) \
{ \
@@ -1045,7 +1052,27 @@
GEN_VSX_HELPER_X2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300)
GEN_VSX_HELPER_R2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300)
GEN_VSX_HELPER_X2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
-GEN_VSX_HELPER_XT_XB_ENV(xscvspdpn, 0x16, 0x14, 0, PPC2_VSX207)
+
+bool trans_XSCVSPDPN(DisasContext *ctx, arg_XX2 *a)
+{
+ TCGv_i64 tmp;
+
+ REQUIRE_INSNS_FLAGS2(ctx, VSX207);
+ REQUIRE_VSX(ctx);
+
+ tmp = tcg_temp_new_i64();
+ get_cpu_vsr(tmp, a->xb, true);
+
+ gen_helper_XSCVSPDPN(tmp, tmp);
+
+ set_cpu_vsr(a->xt, tmp, true);
+ set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
+
+ tcg_temp_free_i64(tmp);
+
+ return true;
+}
+
GEN_VSX_HELPER_X2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX)
GEN_VSX_HELPER_X2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX)
GEN_VSX_HELPER_X2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX)
@@ -1565,7 +1592,7 @@
return true;
}
-static bool trans_XXSPLTW(DisasContext *ctx, arg_XX2_uim2 *a)
+static bool trans_XXSPLTW(DisasContext *ctx, arg_XX2_uim *a)
{
int tofs, bofs;
@@ -1775,42 +1802,35 @@
tcg_temp_free_i64(xtl);
}
-#define VSX_EXTRACT_INSERT(name) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr xt, xb; \
- TCGv_i32 t0; \
- TCGv_i64 t1; \
- uint8_t uimm = UIMM4(ctx->opcode); \
- \
- if (unlikely(!ctx->vsx_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VSXU); \
- return; \
- } \
- xt = gen_vsr_ptr(xT(ctx->opcode)); \
- xb = gen_vsr_ptr(xB(ctx->opcode)); \
- t0 = tcg_temp_new_i32(); \
- t1 = tcg_temp_new_i64(); \
- /* \
- * uimm > 15 out of bound and for \
- * uimm > 12 handle as per hardware in helper \
- */ \
- if (uimm > 15) { \
- tcg_gen_movi_i64(t1, 0); \
- set_cpu_vsr(xT(ctx->opcode), t1, true); \
- set_cpu_vsr(xT(ctx->opcode), t1, false); \
- return; \
- } \
- tcg_gen_movi_i32(t0, uimm); \
- gen_helper_##name(cpu_env, xt, xb, t0); \
- tcg_temp_free_ptr(xb); \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_i32(t0); \
- tcg_temp_free_i64(t1); \
+static bool do_vsx_extract_insert(DisasContext *ctx, arg_XX2_uim *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i32))
+{
+ TCGv_i64 zero = tcg_constant_i64(0);
+ TCGv_ptr xt, xb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ /*
+ * uim > 15 out of bound and for
+ * uim > 12 handle as per hardware in helper
+ */
+ if (a->uim > 15) {
+ set_cpu_vsr(a->xt, zero, true);
+ set_cpu_vsr(a->xt, zero, false);
+ } else {
+ xt = gen_vsr_ptr(a->xt);
+ xb = gen_vsr_ptr(a->xb);
+ gen_helper(xt, xb, tcg_constant_i32(a->uim));
+ tcg_temp_free_ptr(xb);
+ tcg_temp_free_ptr(xt);
+ }
+
+ return true;
}
-VSX_EXTRACT_INSERT(xxextractuw)
-VSX_EXTRACT_INSERT(xxinsertw)
+TRANS(XXEXTRACTUW, do_vsx_extract_insert, gen_helper_XXEXTRACTUW)
+TRANS(XXINSERTW, do_vsx_extract_insert, gen_helper_XXINSERTW)
#ifdef TARGET_PPC64
static void gen_xsxexpdp(DisasContext *ctx)
@@ -2131,7 +2151,23 @@
tcg_temp_free_i64(xbl);
}
-GEN_VSX_HELPER_X2(xvxsigsp, 0x00, 0x04, 0, PPC2_ISA300)
+static bool trans_XVXSIGSP(DisasContext *ctx, arg_XX2 *a)
+{
+ TCGv_ptr t, b;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ t = gen_vsr_ptr(a->xt);
+ b = gen_vsr_ptr(a->xb);
+
+ gen_helper_XVXSIGSP(t, b);
+
+ tcg_temp_free_ptr(t);
+ tcg_temp_free_ptr(b);
+
+ return true;
+}
static void gen_xvxsigdp(DisasContext *ctx)
{
@@ -2787,6 +2823,129 @@
return true;
}
+ /*
+ * The PowerISA 3.1 mentions that for the current version of the
+ * architecture, "the hardware implementation provides the effect of
+ * ACC[i] and VSRs 4*i to 4*i + 3 logically containing the same data"
+ * and "The Accumulators introduce no new logical state at this time"
+ * (page 501). For now it seems unnecessary to create new structures,
+ * so ACC[i] is the same as VSRs 4*i to 4*i+3 and therefore
+ * move to and from accumulators are no-ops.
+ */
+static bool trans_XXMFACC(DisasContext *ctx, arg_X_a *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+ return true;
+}
+
+static bool trans_XXMTACC(DisasContext *ctx, arg_X_a *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+ return true;
+}
+
+static bool trans_XXSETACCZ(DisasContext *ctx, arg_X_a *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+ tcg_gen_gvec_dup_imm(MO_64, acc_full_offset(a->ra), 64, 64, 0);
+ return true;
+}
+
+static bool do_ger(DisasContext *ctx, arg_MMIRR_XX3 *a,
+ void (*helper)(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32))
+{
+ uint32_t mask;
+ TCGv_ptr xt, xa, xb;
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+ if (unlikely((a->xa / 4 == a->xt) || (a->xb / 4 == a->xt))) {
+ gen_invalid(ctx);
+ return true;
+ }
+
+ xt = gen_acc_ptr(a->xt);
+ xa = gen_vsr_ptr(a->xa);
+ xb = gen_vsr_ptr(a->xb);
+
+ mask = ger_pack_masks(a->pmsk, a->ymsk, a->xmsk);
+ helper(cpu_env, xa, xb, xt, tcg_constant_i32(mask));
+ tcg_temp_free_ptr(xt);
+ tcg_temp_free_ptr(xa);
+ tcg_temp_free_ptr(xb);
+ return true;
+}
+
+TRANS(XVI4GER8, do_ger, gen_helper_XVI4GER8)
+TRANS(XVI4GER8PP, do_ger, gen_helper_XVI4GER8PP)
+TRANS(XVI8GER4, do_ger, gen_helper_XVI8GER4)
+TRANS(XVI8GER4PP, do_ger, gen_helper_XVI8GER4PP)
+TRANS(XVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP)
+TRANS(XVI16GER2, do_ger, gen_helper_XVI16GER2)
+TRANS(XVI16GER2PP, do_ger, gen_helper_XVI16GER2PP)
+TRANS(XVI16GER2S, do_ger, gen_helper_XVI16GER2S)
+TRANS(XVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP)
+
+TRANS64(PMXVI4GER8, do_ger, gen_helper_XVI4GER8)
+TRANS64(PMXVI4GER8PP, do_ger, gen_helper_XVI4GER8PP)
+TRANS64(PMXVI8GER4, do_ger, gen_helper_XVI8GER4)
+TRANS64(PMXVI8GER4PP, do_ger, gen_helper_XVI8GER4PP)
+TRANS64(PMXVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP)
+TRANS64(PMXVI16GER2, do_ger, gen_helper_XVI16GER2)
+TRANS64(PMXVI16GER2PP, do_ger, gen_helper_XVI16GER2PP)
+TRANS64(PMXVI16GER2S, do_ger, gen_helper_XVI16GER2S)
+TRANS64(PMXVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP)
+
+TRANS(XVBF16GER2, do_ger, gen_helper_XVBF16GER2)
+TRANS(XVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP)
+TRANS(XVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN)
+TRANS(XVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP)
+TRANS(XVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN)
+
+TRANS(XVF16GER2, do_ger, gen_helper_XVF16GER2)
+TRANS(XVF16GER2PP, do_ger, gen_helper_XVF16GER2PP)
+TRANS(XVF16GER2PN, do_ger, gen_helper_XVF16GER2PN)
+TRANS(XVF16GER2NP, do_ger, gen_helper_XVF16GER2NP)
+TRANS(XVF16GER2NN, do_ger, gen_helper_XVF16GER2NN)
+
+TRANS(XVF32GER, do_ger, gen_helper_XVF32GER)
+TRANS(XVF32GERPP, do_ger, gen_helper_XVF32GERPP)
+TRANS(XVF32GERPN, do_ger, gen_helper_XVF32GERPN)
+TRANS(XVF32GERNP, do_ger, gen_helper_XVF32GERNP)
+TRANS(XVF32GERNN, do_ger, gen_helper_XVF32GERNN)
+
+TRANS(XVF64GER, do_ger, gen_helper_XVF64GER)
+TRANS(XVF64GERPP, do_ger, gen_helper_XVF64GERPP)
+TRANS(XVF64GERPN, do_ger, gen_helper_XVF64GERPN)
+TRANS(XVF64GERNP, do_ger, gen_helper_XVF64GERNP)
+TRANS(XVF64GERNN, do_ger, gen_helper_XVF64GERNN)
+
+TRANS64(PMXVBF16GER2, do_ger, gen_helper_XVBF16GER2)
+TRANS64(PMXVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP)
+TRANS64(PMXVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN)
+TRANS64(PMXVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP)
+TRANS64(PMXVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN)
+
+TRANS64(PMXVF16GER2, do_ger, gen_helper_XVF16GER2)
+TRANS64(PMXVF16GER2PP, do_ger, gen_helper_XVF16GER2PP)
+TRANS64(PMXVF16GER2PN, do_ger, gen_helper_XVF16GER2PN)
+TRANS64(PMXVF16GER2NP, do_ger, gen_helper_XVF16GER2NP)
+TRANS64(PMXVF16GER2NN, do_ger, gen_helper_XVF16GER2NN)
+
+TRANS64(PMXVF32GER, do_ger, gen_helper_XVF32GER)
+TRANS64(PMXVF32GERPP, do_ger, gen_helper_XVF32GERPP)
+TRANS64(PMXVF32GERPN, do_ger, gen_helper_XVF32GERPN)
+TRANS64(PMXVF32GERNP, do_ger, gen_helper_XVF32GERNP)
+TRANS64(PMXVF32GERNN, do_ger, gen_helper_XVF32GERNN)
+
+TRANS64(PMXVF64GER, do_ger, gen_helper_XVF64GER)
+TRANS64(PMXVF64GERPP, do_ger, gen_helper_XVF64GERPP)
+TRANS64(PMXVF64GERPN, do_ger, gen_helper_XVF64GERPN)
+TRANS64(PMXVF64GERNP, do_ger, gen_helper_XVF64GERNP)
+TRANS64(PMXVF64GERNN, do_ger, gen_helper_XVF64GERNN)
+
#undef GEN_XX2FORM
#undef GEN_XX3FORM
#undef GEN_XX2IFORM
diff --git a/target/ppc/translate/vsx-ops.c.inc b/target/ppc/translate/vsx-ops.c.inc
index b8fd116..bff14bb 100644
--- a/target/ppc/translate/vsx-ops.c.inc
+++ b/target/ppc/translate/vsx-ops.c.inc
@@ -156,7 +156,6 @@
GEN_XX2FORM_EO(xvxexpdp, 0x16, 0x1D, 0x00, PPC2_ISA300),
GEN_XX2FORM_EO(xvxsigdp, 0x16, 0x1D, 0x01, PPC2_ISA300),
GEN_XX2FORM_EO(xvxexpsp, 0x16, 0x1D, 0x08, PPC2_ISA300),
-GEN_XX2FORM_EO(xvxsigsp, 0x16, 0x1D, 0x09, PPC2_ISA300),
/* DCMX = bit[25] << 6 | bit[29] << 5 | bit[11:15] */
#define GEN_XX2FORM_DCMX(name, opc2, opc3, fl2) \
@@ -200,7 +199,6 @@
GEN_XX2FORM_EO(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300),
GEN_VSX_XFORM_300_EO(xscvsdqp, 0x04, 0x1A, 0x0A, 0x00000001),
GEN_XX2FORM(xscvspdp, 0x12, 0x14, PPC2_VSX),
-GEN_XX2FORM(xscvspdpn, 0x16, 0x14, PPC2_VSX207),
GEN_XX2FORM(xscvdpsxds, 0x10, 0x15, PPC2_VSX),
GEN_XX2FORM(xscvdpsxws, 0x10, 0x05, PPC2_VSX),
GEN_XX2FORM(xscvdpuxds, 0x10, 0x14, PPC2_VSX),
@@ -322,5 +320,3 @@
GEN_XX3FORM(xxmrghw, 0x08, 0x02, PPC2_VSX),
GEN_XX3FORM(xxmrglw, 0x08, 0x06, PPC2_VSX),
GEN_XX3FORM_DM(xxsldwi, 0x08, 0x00),
-GEN_XX2FORM_EXT(xxextractuw, 0x0A, 0x0A, PPC2_ISA300),
-GEN_XX2FORM_EXT(xxinsertw, 0x0A, 0x0B, PPC2_ISA300),
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index cfcd121..de4483e 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -1832,13 +1832,14 @@
static void tcg_out_mb(TCGContext *s, TCGArg a0)
{
- uint32_t insn = HWSYNC;
- a0 &= TCG_MO_ALL;
- if (a0 == TCG_MO_LD_LD) {
+ uint32_t insn;
+
+ if (a0 & TCG_MO_ST_LD) {
+ insn = HWSYNC;
+ } else {
insn = LWSYNC;
- } else if (a0 == TCG_MO_ST_ST) {
- insn = EIEIO;
}
+
tcg_out32(s, insn);
}
@@ -4008,3 +4009,4 @@
#undef VMULOUB
#undef VMULOUH
#undef VMULOUW
+#undef VMSUMUHM