[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 064/115] target/i386: fix fisttpl, fisttpll handling of out-of-ran
From: |
Paolo Bonzini |
Subject: |
[PULL 064/115] target/i386: fix fisttpl, fisttpll handling of out-of-range values |
Date: |
Thu, 11 Jun 2020 15:43:58 -0400 |
From: Joseph Myers <joseph@codesourcery.com>
The fist / fistt family of instructions should all store the most
negative integer in the destination format when the rounded /
truncated integer result is out of range or the input is an invalid
encoding, infinity or NaN. The fisttpl and fisttpll implementations
(32-bit and 64-bit results, truncate towards zero) failed to do this,
producing the most positive integer in some cases instead. Fix this
by copying the code used to handle this issue for fistpl and fistpll,
adjusted to use the _round_to_zero functions for the actual
conversion (but without any other changes to that code).
Signed-off-by: Joseph Myers <joseph@codesourcery.com>
Message-Id: <alpine.DEB.2.21.2005152119160.3469@digraph.polyomino.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/fpu_helper.c | 28 ++++++++-
tests/tcg/i386/test-i386-fisttp.c | 100 ++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+), 2 deletions(-)
create mode 100644 tests/tcg/i386/test-i386-fisttp.c
diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c
index 41f6f391ca..9c93f385b1 100644
--- a/target/i386/fpu_helper.c
+++ b/target/i386/fpu_helper.c
@@ -338,12 +338,36 @@ int32_t helper_fistt_ST0(CPUX86State *env)
int32_t helper_fisttl_ST0(CPUX86State *env)
{
- return floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
+ int32_t val;
+ signed char old_exp_flags;
+
+ old_exp_flags = get_float_exception_flags(&env->fp_status);
+ set_float_exception_flags(0, &env->fp_status);
+
+ val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status);
+ if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
+ val = 0x80000000;
+ }
+ set_float_exception_flags(get_float_exception_flags(&env->fp_status)
+ | old_exp_flags, &env->fp_status);
+ return val;
}
int64_t helper_fisttll_ST0(CPUX86State *env)
{
- return floatx80_to_int64_round_to_zero(ST0, &env->fp_status);
+ int64_t val;
+ signed char old_exp_flags;
+
+ old_exp_flags = get_float_exception_flags(&env->fp_status);
+ set_float_exception_flags(0, &env->fp_status);
+
+ val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status);
+ if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) {
+ val = 0x8000000000000000ULL;
+ }
+ set_float_exception_flags(get_float_exception_flags(&env->fp_status)
+ | old_exp_flags, &env->fp_status);
+ return val;
}
void helper_fldt_ST0(CPUX86State *env, target_ulong ptr)
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;
+}
--
2.26.2
- [PULL 041/115] qom/object: factor out the initialization of hash table of properties, (continued)
- [PULL 041/115] qom/object: factor out the initialization of hash table of properties, Paolo Bonzini, 2020/06/11
- [PULL 055/115] target/i386: fix fscale handling of rounding precision, Paolo Bonzini, 2020/06/11
- [PULL 059/115] hw/elf_ops: Do not ignore write failures when loading ELF, Paolo Bonzini, 2020/06/11
- [PULL 025/115] hw/i386/vmport: Add reference to VMware open-vm-tools, Paolo Bonzini, 2020/06/11
- [PULL 017/115] hyperv: expose API to determine if synic is enabled, Paolo Bonzini, 2020/06/11
- [PULL 014/115] qom/object: Move Object typedef to 'qemu/typedefs.h', Paolo Bonzini, 2020/06/11
- [PULL 066/115] x86/cpu: Enable AVX512_VP2INTERSECT cpu feature, Paolo Bonzini, 2020/06/11
- [PULL 067/115] vfio/pci: Use kvm_irqchip_add_irqfd_notifier_gsi() for irqfds, Paolo Bonzini, 2020/06/11
- [PULL 035/115] hw/i386/vmport: Allow x2apic without IR, Paolo Bonzini, 2020/06/11
- [PULL 030/115] hw/i386/vmport: Report vmware-vmx-type in CMD_GETVERSION, Paolo Bonzini, 2020/06/11
- [PULL 064/115] target/i386: fix fisttpl, fisttpll handling of out-of-range values,
Paolo Bonzini <=
- [PULL 024/115] target/i386: fix phadd* with identical destination and source register, Paolo Bonzini, 2020/06/11
- [PULL 048/115] megasas: use unsigned type for reply_queue_head and check index, Paolo Bonzini, 2020/06/11
- [PULL 060/115] target/i386: fix floating-point load-constant rounding, Paolo Bonzini, 2020/06/11
- [PULL 019/115] vmbus: vmbus implementation, Paolo Bonzini, 2020/06/11
- [PULL 022/115] vmbus: add infrastructure to save/load vmbus requests, Paolo Bonzini, 2020/06/11
- [PULL 057/115] exec: Propagate cpu_memory_rw_debug() error, Paolo Bonzini, 2020/06/11
- [PULL 031/115] hw/i386/vmport: Introduce vmport.h, Paolo Bonzini, 2020/06/11
- [PULL 047/115] i386/kvm: fix a use-after-free when vcpu plug/unplug, Paolo Bonzini, 2020/06/11
- [PULL 040/115] qom: remove index from object_resolve_abs_path(), Paolo Bonzini, 2020/06/11
- [PULL 070/115] chardev/char-socket: Properly make qio connections non blocking, Paolo Bonzini, 2020/06/11