diff options
author | Peter Maydell | 2020-06-13 00:06:22 +0200 |
---|---|---|
committer | Peter Maydell | 2020-06-13 00:06:22 +0200 |
commit | 7d3660e79830a069f1848bb4fa1cdf8f666424fb (patch) | |
tree | 5651ddf02414086c31d0bfca7713e1800d4f0fc8 /tests/tcg | |
parent | Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (diff) | |
parent | target/i386: Remove obsolete TODO file (diff) | |
download | qemu-7d3660e79830a069f1848bb4fa1cdf8f666424fb.tar.gz qemu-7d3660e79830a069f1848bb4fa1cdf8f666424fb.tar.xz qemu-7d3660e79830a069f1848bb4fa1cdf8f666424fb.zip |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* Miscellaneous fixes and feature enablement (many)
* SEV refactoring (David)
* Hyper-V initial support (Jon)
* i386 TCG fixes (x87 and SSE, Joseph)
* vmport cleanup and improvements (Philippe, Liran)
* Use-after-free with vCPU hot-unplug (Nengyuan)
* run-coverity-scan improvements (myself)
* Record/replay fixes (Pavel)
* -machine kernel_irqchip=split improvements for INTx (Peter)
* Code cleanups (Philippe)
* Crash and security fixes (PJP)
* HVF cleanups (Roman)
# gpg: Signature made Fri 12 Jun 2020 16:57:04 BST
# gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg: issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (116 commits)
target/i386: Remove obsolete TODO file
stubs: move Xen stubs to accel/
replay: fix replay shutdown for console mode
exec/cpu-common: Move MUSB specific typedefs to 'hw/usb/hcd-musb.h'
hw/usb: Move device-specific declarations to new 'hcd-musb.h' header
exec/memory: Remove unused MemoryRegionMmio type
checkpatch: reversed logic with acpi test checks
target/i386: sev: Unify SEVState and SevGuestState
target/i386: sev: Remove redundant handle field
target/i386: sev: Remove redundant policy field
target/i386: sev: Remove redundant cbitpos and reduced_phys_bits fields
target/i386: sev: Partial cleanup to sev_state global
target/i386: sev: Embed SEVState in SevGuestState
target/i386: sev: Rename QSevGuestInfo
target/i386: sev: Move local structure definitions into .c file
target/i386: sev: Remove unused QSevGuestInfoClass
xen: fix build without pci passthrough
i386: hvf: Drop HVFX86EmulatorState
i386: hvf: Move mmio_buf into CPUX86State
i386: hvf: Move lazy_flags into CPUX86State
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
# Conflicts:
# hw/i386/acpi-build.c
Diffstat (limited to 'tests/tcg')
-rw-r--r-- | tests/tcg/i386/Makefile.target | 3 | ||||
-rw-r--r-- | tests/tcg/i386/test-i386-fbstp.c | 140 | ||||
-rw-r--r-- | tests/tcg/i386/test-i386-fisttp.c | 100 | ||||
-rw-r--r-- | tests/tcg/i386/test-i386-fldcst.c | 199 | ||||
-rw-r--r-- | tests/tcg/i386/test-i386-fp-exceptions.c | 831 | ||||
-rw-r--r-- | tests/tcg/i386/test-i386-fscale.c | 108 | ||||
-rw-r--r-- | tests/tcg/i386/test-i386-fxam.c | 143 | ||||
-rw-r--r-- | tests/tcg/i386/test-i386-fxtract.c | 120 | ||||
-rw-r--r-- | tests/tcg/i386/test-i386-pcmpistri.c | 33 |
9 files changed, 1677 insertions, 0 deletions
diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index 43ee2e181e..53efec0668 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -10,6 +10,9 @@ ALL_X86_TESTS=$(I386_SRCS:.c=) SKIP_I386_TESTS=test-i386-ssse3 X86_64_TESTS:=$(filter test-i386-ssse3, $(ALL_X86_TESTS)) +test-i386-pcmpistri: CFLAGS += -msse4.2 +run-test-i386-pcmpistri: QEMU_OPTS += -cpu max + # # hello-i386 is a barebones app # diff --git a/tests/tcg/i386/test-i386-fbstp.c b/tests/tcg/i386/test-i386-fbstp.c new file mode 100644 index 0000000000..73bf56b9dc --- /dev/null +++ b/tests/tcg/i386/test-i386-fbstp.c @@ -0,0 +1,140 @@ +/* Test fbstp instruction. */ + +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; +volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; +volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; + +int main(void) +{ + int ret = 0; + unsigned char out[10]; + memset(out, 0xfe, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-0.0L) : "st"); + out[9] &= 0x80; + if (memcmp(out, "\0\0\0\0\0\0\0\0\0\x80", sizeof out) != 0) { + printf("FAIL: fbstp -0\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-0.1L) : "st"); + out[9] &= 0x80; + if (memcmp(out, "\0\0\0\0\0\0\0\0\0\x80", sizeof out) != 0) { + printf("FAIL: fbstp -0.1\n"); + ret = 1; + } + memset(out, 0x1f, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-987654321987654321.0L) : + "st"); + out[9] &= 0x80; + if (memcmp(out, "\x21\x43\x65\x87\x19\x32\x54\x76\x98\x80", + sizeof out) != 0) { + printf("FAIL: fbstp -987654321987654321\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (999999999999999999.5L) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp 999999999999999999.5\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (1000000000000000000.0L) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp 1000000000000000000\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (1e30L) : "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp 1e30\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-999999999999999999.5L) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -999999999999999999.5\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-1000000000000000000.0L) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -1000000000000000000\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-1e30L) : "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -1e30\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (__builtin_infl()) : "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp inf\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-__builtin_infl()) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -inf\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (__builtin_nanl("")) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp nan\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-__builtin_nanl("")) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp -nan\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_1.ld) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp invalid 1\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_2.ld) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp invalid 2\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_3.ld) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp invalid 3\n"); + ret = 1; + } + memset(out, 0x12, sizeof out); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_4.ld) : + "st"); + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { + printf("FAIL: fbstp invalid 4\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fisttp.c b/tests/tcg/i386/test-i386-fisttp.c new file mode 100644 index 0000000000..16af59a774 --- /dev/null +++ b/tests/tcg/i386/test-i386-fisttp.c @@ -0,0 +1,100 @@ +/* Test fisttpl and fisttpll instructions. */ + +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; + +int main(void) +{ + int ret = 0; + int32_t res_32; + int64_t res_64; + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (0x1p100L) : "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl 0x1p100\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (-0x1p100L) : "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl -0x1p100\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (__builtin_infl()) : + "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl inf\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (-__builtin_infl()) : + "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl -inf\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (__builtin_nanl("")) : + "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl nan\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : + "t" (-__builtin_nanl("")) : "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl -nan\n"); + ret = 1; + } + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (ld_invalid_1.ld) : + "st"); + if (res_32 != INT32_MIN) { + printf("FAIL: fisttpl invalid\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (0x1p100L) : "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll 0x1p100\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (-0x1p100L) : "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll -0x1p100\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (__builtin_infl()) : + "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll inf\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (-__builtin_infl()) : + "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll -inf\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : + "t" (__builtin_nanl("")) : "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll nan\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : + "t" (-__builtin_nanl("")) : "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll -nan\n"); + ret = 1; + } + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (ld_invalid_1.ld) : + "st"); + if (res_64 != INT64_MIN) { + printf("FAIL: fisttpll invalid\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fldcst.c b/tests/tcg/i386/test-i386-fldcst.c new file mode 100644 index 0000000000..e635432ccf --- /dev/null +++ b/tests/tcg/i386/test-i386-fldcst.c @@ -0,0 +1,199 @@ +/* Test instructions loading floating-point constants. */ + +#include <stdint.h> +#include <stdio.h> + +volatile long double ld_res; + +int main(void) +{ + short cw; + int ret = 0; + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=t" (ld_res)); + if (ld_res != 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=t" (ld_res)); + if (ld_res != 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=t" (ld_res)); + if (ld_res != 0x3.5269e12f346e2bf8p+0L) { + printf("FAIL: fldl2t Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2t" : "=t" (ld_res)); + if (ld_res != 0x3.5269e12f346e2bfcp+0L) { + printf("FAIL: fldl2t U\n"); + ret = 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=t" (ld_res)); + if (ld_res != 0x1.71547652b82fe178p+0L) { + printf("FAIL: fldl2e N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=t" (ld_res)); + if (ld_res != 0x1.71547652b82fe176p+0L) { + printf("FAIL: fldl2e D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=t" (ld_res)); + if (ld_res != 0x1.71547652b82fe176p+0L) { + printf("FAIL: fldl2e Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldl2e" : "=t" (ld_res)); + if (ld_res != 0x1.71547652b82fe178p+0L) { + printf("FAIL: fldl2e U\n"); + ret = 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=t" (ld_res)); + if (ld_res != 0x3.243f6a8885a308d4p+0L) { + printf("FAIL: fldpi N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=t" (ld_res)); + if (ld_res != 0x3.243f6a8885a308dp+0L) { + printf("FAIL: fldpi D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=t" (ld_res)); + if (ld_res != 0x3.243f6a8885a308dp+0L) { + printf("FAIL: fldpi Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldpi" : "=t" (ld_res)); + if (ld_res != 0x3.243f6a8885a308d4p+0L) { + printf("FAIL: fldpi U\n"); + ret = 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=t" (ld_res)); + if (ld_res != 0x4.d104d427de7fbcc8p-4L) { + printf("FAIL: fldlg2 N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=t" (ld_res)); + if (ld_res != 0x4.d104d427de7fbccp-4L) { + printf("FAIL: fldlg2 D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=t" (ld_res)); + if (ld_res != 0x4.d104d427de7fbccp-4L) { + printf("FAIL: fldlg2 Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldlg2" : "=t" (ld_res)); + if (ld_res != 0x4.d104d427de7fbcc8p-4L) { + printf("FAIL: fldlg2 U\n"); + ret = 1; + } + + /* Round to nearest. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x000; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=t" (ld_res)); + if (ld_res != 0xb.17217f7d1cf79acp-4L) { + printf("FAIL: fldln2 N\n"); + ret = 1; + } + /* Round downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=t" (ld_res)); + if (ld_res != 0xb.17217f7d1cf79abp-4L) { + printf("FAIL: fldln2 D\n"); + ret = 1; + } + /* Round toward zero. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0xc00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=t" (ld_res)); + if (ld_res != 0xb.17217f7d1cf79abp-4L) { + printf("FAIL: fldln2 Z\n"); + ret = 1; + } + /* Round upward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x800; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fldln2" : "=t" (ld_res)); + if (ld_res != 0xb.17217f7d1cf79acp-4L) { + printf("FAIL: fldln2 U\n"); + ret = 1; + } + + return ret; +} diff --git a/tests/tcg/i386/test-i386-fp-exceptions.c b/tests/tcg/i386/test-i386-fp-exceptions.c new file mode 100644 index 0000000000..dfb7117c17 --- /dev/null +++ b/tests/tcg/i386/test-i386-fp-exceptions.c @@ -0,0 +1,831 @@ +/* Test floating-point exceptions. */ + +#include <float.h> +#include <stdint.h> +#include <stdio.h> + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile float f_res; +volatile double d_res; +volatile long double ld_res; +volatile long double ld_res2; + +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile float f_snan = __builtin_nansf(""); +volatile double d_snan = __builtin_nans(""); +volatile long double ld_third = 1.0L / 3.0L; +volatile long double ld_snan = __builtin_nansl(""); +volatile long double ld_nan = __builtin_nanl(""); +volatile long double ld_inf = __builtin_infl(); +volatile long double ld_ninf = -__builtin_infl(); +volatile long double ld_one = 1.0L; +volatile long double ld_zero = 0.0L; +volatile long double ld_nzero = -0.0L; +volatile long double ld_min = LDBL_MIN; +volatile long double ld_max = LDBL_MAX; +volatile long double ld_nmax = -LDBL_MAX; + +#define IE (1 << 0) +#define ZE (1 << 2) +#define OE (1 << 3) +#define UE (1 << 4) +#define PE (1 << 5) +#define EXC (IE | ZE | OE | UE | PE) + +int main(void) +{ + short sw; + unsigned char out[10]; + int ret = 0; + int16_t res_16; + int32_t res_32; + int64_t res_64; + + __asm__ volatile ("fnclex"); + ld_res = f_snan; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: widen float snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = d_snan; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: widen double snan\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: narrow float underflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: narrow double underflow\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: narrow float overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: narrow double overflow\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: narrow float inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: narrow double inexact\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_snan; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: narrow float snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_snan; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: narrow double snan\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + f_res = ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: narrow float invalid\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + d_res = ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: narrow double invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("frndint" : "=t" (ld_res) : "0" (ld_min)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: frndint min\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("frndint" : "=t" (ld_res) : "0" (ld_snan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: frndint snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("frndint" : "=t" (ld_res) : "0" (ld_invalid_1.ld)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: frndint invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fcom" : : "t" (ld_nan), "u" (ld_zero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fcom nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fucom" : : "t" (ld_nan), "u" (ld_zero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fucom nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fucom" : : "t" (ld_snan), "u" (ld_zero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fucom snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fucom" : : "t" (1.0L), "u" (ld_invalid_1.ld)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fucom invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + ld_res = ld_max + ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: add overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_max + ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: add inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf + ld_ninf; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: add inf -inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_snan + ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: add snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third + ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: add invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + ld_res = ld_max - ld_nmax; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: sub overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_max - ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: sub inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf - ld_inf; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: sub inf inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_snan - ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: sub snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third - ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: sub invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + ld_res = ld_max * ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: mul overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third * ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: mul inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_min * ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: mul underflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf * ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: mul inf 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_snan * ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: mul snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third * ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: mul invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + ld_res = ld_max / ld_min; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: div overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_one / ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: div inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_min / ld_max; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: div underflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_one / ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != ZE) { + printf("FAIL: div 1 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf / ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: div inf 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_nan / ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: div nan 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_zero / ld_zero; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: div 0 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_inf / ld_inf; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: div inf inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_snan / ld_third; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: div snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + ld_res = ld_third / ld_invalid_1.ld; + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: div invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_max)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fsqrt inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_nmax)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fsqrt -max\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_ninf)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fsqrt -inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_snan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fsqrt snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_invalid_1.ld)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fsqrt invalid\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (ld_nzero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fsqrt -0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fsqrt" : "=t" (ld_res) : "0" (-__builtin_nanl(""))); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fsqrt -nan\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fistp inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (32767.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistp 32767.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (-32768.51L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistp -32768.51\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistp nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistp %0" : "=m" (res_16) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistp invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fistpl inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (2147483647.5L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpl 2147483647.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (-2147483648.51L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpl -2147483648.51\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpl nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpl %0" : "=m" (res_32) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpl invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fistpll inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (0x1p63) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpll 0x1p63\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (-0x1.1p63L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpll -0x1.1p63\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpll nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fistpll %0" : "=m" (res_64) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fistpll invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fisttp inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (32768.0L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp 32768\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (32768.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp 32768.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (-32769.0L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp -32769\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (-32769.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp -32769.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttp %0" : "=m" (res_16) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttp invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fisttpl inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (2147483648.0L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpl 2147483648\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (-2147483649.0L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpl -2147483649\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpl nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpl %0" : "=m" (res_32) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpl invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (1.5L) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fisttpll inexact\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (0x1p63) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpll 0x1p63\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (-0x1.1p63L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpll -0x1.1p63\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpll nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fisttpll %0" : "=m" (res_64) : "t" (ld_invalid_1.ld) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fisttpll invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_zero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != ZE) { + printf("FAIL: fxtract 0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_nzero)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != ZE) { + printf("FAIL: fxtract -0\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_inf)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fxtract inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_nan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != 0) { + printf("FAIL: fxtract nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_snan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fxtract snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fxtract" : "=t" (ld_res), "=u" (ld_res2) : + "0" (ld_invalid_1.ld)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fxtract invalid\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_min), "u" (ld_max)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (OE | PE)) { + printf("FAIL: fscale overflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_max), "u" (ld_nmax)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != (UE | PE)) { + printf("FAIL: fscale underflow\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_zero), "u" (ld_inf)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale 0 inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_inf), "u" (ld_ninf)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale inf -inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_one), "u" (ld_snan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale 1 snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : "0" (ld_snan), "u" (ld_nan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale snan nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (ld_invalid_1.ld), "u" (ld_one)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (ld_invalid_1.ld), "u" (ld_nan)); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fscale invalid nan\n"); + ret = 1; + } + + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (1.5L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != PE) { + printf("FAIL: fbstp 1.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (999999999999999999.5L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp 999999999999999999.5\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-1000000000000000000.0L) : + "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp -1000000000000000000\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_inf) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp inf\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_nan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp nan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_snan) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp snan\n"); + ret = 1; + } + __asm__ volatile ("fnclex"); + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_1.ld) : "st"); + __asm__ volatile ("fnstsw" : "=a" (sw)); + if ((sw & EXC) != IE) { + printf("FAIL: fbstp invalid\n"); + ret = 1; + } + + return ret; +} diff --git a/tests/tcg/i386/test-i386-fscale.c b/tests/tcg/i386/test-i386-fscale.c new file mode 100644 index 0000000000..d23b3cfeec --- /dev/null +++ b/tests/tcg/i386/test-i386-fscale.c @@ -0,0 +1,108 @@ +/* Test fscale instruction. */ + +#include <stdint.h> +#include <stdio.h> + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile long double ld_third = 1.0L / 3.0L; +volatile long double ld_four_thirds = 4.0L / 3.0L; +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; +volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; +volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; + +volatile long double ld_res; + +int isnan_ld(long double x) +{ + union u tmp = { .ld = x }; + return ((tmp.s.sign_exp & 0x7fff) == 0x7fff && + (tmp.s.sig >> 63) != 0 && + (tmp.s.sig << 1) != 0); +} + +int issignaling_ld(long double x) +{ + union u tmp = { .ld = x }; + return isnan_ld(x) && (tmp.s.sig & UINT64_C(0x4000000000000000)) == 0; +} + +int main(void) +{ + short cw; + int ret = 0; + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (__builtin_nansl(""))); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale snan\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (ld_invalid_1.ld)); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (ld_invalid_2.ld)); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale invalid 2\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (ld_invalid_3.ld)); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale invalid 3\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (2.5L), "u" (ld_invalid_4.ld)); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale invalid 4\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (0.0L), "u" (__builtin_infl())); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale 0 up inf\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (__builtin_infl()), "u" (-__builtin_infl())); + if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { + printf("FAIL: fscale inf down inf\n"); + ret = 1; + } + /* Set round-downward. */ + __asm__ volatile ("fnstcw %0" : "=m" (cw)); + cw = (cw & ~0xc00) | 0x400; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (1.0L), "u" (__builtin_infl())); + if (ld_res != __builtin_infl()) { + printf("FAIL: fscale finite up inf\n"); + ret = 1; + } + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (-1.0L), "u" (-__builtin_infl())); + if (ld_res != -0.0L || __builtin_copysignl(1.0L, ld_res) != -1.0L) { + printf("FAIL: fscale finite down inf\n"); + ret = 1; + } + /* Set round-to-nearest with single-precision rounding. */ + cw = cw & ~0xf00; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + __asm__ volatile ("fscale" : "=t" (ld_res) : + "0" (ld_third), "u" (2.0L)); + cw = cw | 0x300; + __asm__ volatile ("fldcw %0" : : "m" (cw)); + if (ld_res != ld_four_thirds) { + printf("FAIL: fscale single-precision\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fxam.c b/tests/tcg/i386/test-i386-fxam.c new file mode 100644 index 0000000000..ddd76ca42d --- /dev/null +++ b/tests/tcg/i386/test-i386-fxam.c @@ -0,0 +1,143 @@ +/* Test fxam instruction. */ + +#include <stdint.h> +#include <stdio.h> + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile union u ld_pseudo_m16382 = { .s = { UINT64_C(1) << 63, 0 } }; +volatile union u ld_pseudo_nm16382 = { .s = { UINT64_C(1) << 63, 0x8000 } }; +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; +volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; +volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; +volatile union u ld_invalid_n1 = { .s = { 1, 0x8123 } }; +volatile union u ld_invalid_n2 = { .s = { 0, 0x8123 } }; +volatile union u ld_invalid_n3 = { .s = { 0, 0xffff } }; +volatile union u ld_invalid_n4 = { .s = { (UINT64_C(1) << 63) - 1, 0xffff } }; + +#define C0 (1 << 8) +#define C1 (1 << 9) +#define C2 (1 << 10) +#define C3 (1 << 14) +#define FLAGS (C0 | C1 | C2 | C3) + +int main(void) +{ + short sw; + int ret = 0; + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (0.0L)); + if ((sw & FLAGS) != C3) { + printf("FAIL: +0\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-0.0L)); + if ((sw & FLAGS) != (C3 | C1)) { + printf("FAIL: -0\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (1.0L)); + if ((sw & FLAGS) != C2) { + printf("FAIL: +normal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-1.0L)); + if ((sw & FLAGS) != (C2 | C1)) { + printf("FAIL: -normal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_infl())); + if ((sw & FLAGS) != (C2 | C0)) { + printf("FAIL: +inf\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_infl())); + if ((sw & FLAGS) != (C2 | C1 | C0)) { + printf("FAIL: -inf\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_nanl(""))); + if ((sw & FLAGS) != C0) { + printf("FAIL: +nan\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_nanl(""))); + if ((sw & FLAGS) != (C1 | C0)) { + printf("FAIL: -nan\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_nansl(""))); + if ((sw & FLAGS) != C0) { + printf("FAIL: +snan\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_nansl(""))); + if ((sw & FLAGS) != (C1 | C0)) { + printf("FAIL: -snan\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (0x1p-16445L)); + if ((sw & FLAGS) != (C3 | C2)) { + printf("FAIL: +denormal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-0x1p-16445L)); + if ((sw & FLAGS) != (C3 | C2 | C1)) { + printf("FAIL: -denormal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_pseudo_m16382.ld)); + if ((sw & FLAGS) != (C3 | C2)) { + printf("FAIL: +pseudo-denormal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_pseudo_nm16382.ld)); + if ((sw & FLAGS) != (C3 | C2 | C1)) { + printf("FAIL: -pseudo-denormal\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_1.ld)); + if ((sw & FLAGS) != 0) { + printf("FAIL: +invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n1.ld)); + if ((sw & FLAGS) != C1) { + printf("FAIL: -invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_2.ld)); + if ((sw & FLAGS) != 0) { + printf("FAIL: +invalid 2\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n2.ld)); + if ((sw & FLAGS) != C1) { + printf("FAIL: -invalid 2\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_3.ld)); + if ((sw & FLAGS) != 0) { + printf("FAIL: +invalid 3\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n3.ld)); + if ((sw & FLAGS) != C1) { + printf("FAIL: -invalid 3\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_4.ld)); + if ((sw & FLAGS) != 0) { + printf("FAIL: +invalid 4\n"); + ret = 1; + } + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n4.ld)); + if ((sw & FLAGS) != C1) { + printf("FAIL: -invalid 4\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-fxtract.c b/tests/tcg/i386/test-i386-fxtract.c new file mode 100644 index 0000000000..64fd93d333 --- /dev/null +++ b/tests/tcg/i386/test-i386-fxtract.c @@ -0,0 +1,120 @@ +/* Test fxtract instruction. */ + +#include <stdint.h> +#include <stdio.h> + +union u { + struct { uint64_t sig; uint16_t sign_exp; } s; + long double ld; +}; + +volatile union u ld_pseudo_m16382 = { .s = { UINT64_C(1) << 63, 0 } }; +volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; +volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; +volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; +volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; + +volatile long double ld_sig, ld_exp; + +int isnan_ld(long double x) +{ + union u tmp = { .ld = x }; + return ((tmp.s.sign_exp & 0x7fff) == 0x7fff && + (tmp.s.sig >> 63) != 0 && + (tmp.s.sig << 1) != 0); +} + +int issignaling_ld(long double x) +{ + union u tmp = { .ld = x }; + return isnan_ld(x) && (tmp.s.sig & UINT64_C(0x4000000000000000)) == 0; +} + +int main(void) +{ + int ret = 0; + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : "0" (2.5L)); + if (ld_sig != 1.25L || ld_exp != 1.0L) { + printf("FAIL: fxtract 2.5\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : "0" (0.0L)); + if (ld_sig != 0.0L || __builtin_copysignl(1.0L, ld_sig) != 1.0L || + ld_exp != -__builtin_infl()) { + printf("FAIL: fxtract 0.0\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : "0" (-0.0L)); + if (ld_sig != -0.0L || __builtin_copysignl(1.0L, ld_sig) != -1.0L || + ld_exp != -__builtin_infl()) { + printf("FAIL: fxtract -0.0\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (__builtin_infl())); + if (ld_sig != __builtin_infl() || ld_exp != __builtin_infl()) { + printf("FAIL: fxtract inf\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (-__builtin_infl())); + if (ld_sig != -__builtin_infl() || ld_exp != __builtin_infl()) { + printf("FAIL: fxtract -inf\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (__builtin_nanl(""))); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract qnan\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (__builtin_nansl(""))); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract snan\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (0x1p-16445L)); + if (ld_sig != 1.0L || ld_exp != -16445.0L) { + printf("FAIL: fxtract subnormal\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_pseudo_m16382.ld)); + if (ld_sig != 1.0L || ld_exp != -16382.0L) { + printf("FAIL: fxtract pseudo\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_invalid_1.ld)); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract invalid 1\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_invalid_2.ld)); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract invalid 2\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_invalid_3.ld)); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract invalid 3\n"); + ret = 1; + } + __asm__ volatile ("fxtract" : "=t" (ld_sig), "=u" (ld_exp) : + "0" (ld_invalid_4.ld)); + if (!isnan_ld(ld_sig) || issignaling_ld(ld_sig) || + !isnan_ld(ld_exp) || issignaling_ld(ld_exp)) { + printf("FAIL: fxtract invalid 4\n"); + ret = 1; + } + return ret; +} diff --git a/tests/tcg/i386/test-i386-pcmpistri.c b/tests/tcg/i386/test-i386-pcmpistri.c new file mode 100644 index 0000000000..1e81ae611a --- /dev/null +++ b/tests/tcg/i386/test-i386-pcmpistri.c @@ -0,0 +1,33 @@ +/* Test pcmpistri instruction. */ + +#include <nmmintrin.h> +#include <stdio.h> + +union u { + __m128i x; + unsigned char uc[16]; +}; + +union u s0 = { .uc = { 0 } }; +union u s1 = { .uc = "abcdefghijklmnop" }; +union u s2 = { .uc = "bcdefghijklmnopa" }; +union u s3 = { .uc = "bcdefghijklmnab" }; + +int +main(void) +{ + int ret = 0; + if (_mm_cmpistri(s0.x, s0.x, 0x4c) != 15) { + printf("FAIL: pcmpistri test 1\n"); + ret = 1; + } + if (_mm_cmpistri(s1.x, s2.x, 0x4c) != 15) { + printf("FAIL: pcmpistri test 2\n"); + ret = 1; + } + if (_mm_cmpistri(s1.x, s3.x, 0x4c) != 16) { + printf("FAIL: pcmpistri test 3\n"); + ret = 1; + } + return ret; +} |