qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

target/i386: fix fxam handling of invalid encodings

The fxam implementation does not check for invalid encodings, instead
treating them like NaN or normal numbers depending on the exponent.
Fix it to check that the high bit of the significand is set before
treating an encoding as NaN or normal, thus resulting in correct
handling (all of C0, C2 and C3 cleared) for invalid encodings.

Signed-off-by: Joseph Myers <joseph@codesourcery.com>
Message-Id: <alpine.DEB.2.21.2005132349311.11687@digraph.polyomino.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Joseph Myers and committed by
Paolo Bonzini
34b9cc07 80b4008c

+145 -2
+2 -2
target/i386/fpu_helper.c
··· 1099 1099 if (expdif == MAXEXPD) { 1100 1100 if (MANTD(temp) == 0x8000000000000000ULL) { 1101 1101 env->fpus |= 0x500; /* Infinity */ 1102 - } else { 1102 + } else if (MANTD(temp) & 0x8000000000000000ULL) { 1103 1103 env->fpus |= 0x100; /* NaN */ 1104 1104 } 1105 1105 } else if (expdif == 0) { ··· 1108 1108 } else { 1109 1109 env->fpus |= 0x4400; /* Denormal */ 1110 1110 } 1111 - } else { 1111 + } else if (MANTD(temp) & 0x8000000000000000ULL) { 1112 1112 env->fpus |= 0x400; 1113 1113 } 1114 1114 }
+143
tests/tcg/i386/test-i386-fxam.c
··· 1 + /* Test fxam instruction. */ 2 + 3 + #include <stdint.h> 4 + #include <stdio.h> 5 + 6 + union u { 7 + struct { uint64_t sig; uint16_t sign_exp; } s; 8 + long double ld; 9 + }; 10 + 11 + volatile union u ld_pseudo_m16382 = { .s = { UINT64_C(1) << 63, 0 } }; 12 + volatile union u ld_pseudo_nm16382 = { .s = { UINT64_C(1) << 63, 0x8000 } }; 13 + volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; 14 + volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; 15 + volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; 16 + volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; 17 + volatile union u ld_invalid_n1 = { .s = { 1, 0x8123 } }; 18 + volatile union u ld_invalid_n2 = { .s = { 0, 0x8123 } }; 19 + volatile union u ld_invalid_n3 = { .s = { 0, 0xffff } }; 20 + volatile union u ld_invalid_n4 = { .s = { (UINT64_C(1) << 63) - 1, 0xffff } }; 21 + 22 + #define C0 (1 << 8) 23 + #define C1 (1 << 9) 24 + #define C2 (1 << 10) 25 + #define C3 (1 << 14) 26 + #define FLAGS (C0 | C1 | C2 | C3) 27 + 28 + int main(void) 29 + { 30 + short sw; 31 + int ret = 0; 32 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (0.0L)); 33 + if ((sw & FLAGS) != C3) { 34 + printf("FAIL: +0\n"); 35 + ret = 1; 36 + } 37 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-0.0L)); 38 + if ((sw & FLAGS) != (C3 | C1)) { 39 + printf("FAIL: -0\n"); 40 + ret = 1; 41 + } 42 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (1.0L)); 43 + if ((sw & FLAGS) != C2) { 44 + printf("FAIL: +normal\n"); 45 + ret = 1; 46 + } 47 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-1.0L)); 48 + if ((sw & FLAGS) != (C2 | C1)) { 49 + printf("FAIL: -normal\n"); 50 + ret = 1; 51 + } 52 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_infl())); 53 + if ((sw & FLAGS) != (C2 | C0)) { 54 + printf("FAIL: +inf\n"); 55 + ret = 1; 56 + } 57 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_infl())); 58 + if ((sw & FLAGS) != (C2 | C1 | C0)) { 59 + printf("FAIL: -inf\n"); 60 + ret = 1; 61 + } 62 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_nanl(""))); 63 + if ((sw & FLAGS) != C0) { 64 + printf("FAIL: +nan\n"); 65 + ret = 1; 66 + } 67 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_nanl(""))); 68 + if ((sw & FLAGS) != (C1 | C0)) { 69 + printf("FAIL: -nan\n"); 70 + ret = 1; 71 + } 72 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (__builtin_nansl(""))); 73 + if ((sw & FLAGS) != C0) { 74 + printf("FAIL: +snan\n"); 75 + ret = 1; 76 + } 77 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-__builtin_nansl(""))); 78 + if ((sw & FLAGS) != (C1 | C0)) { 79 + printf("FAIL: -snan\n"); 80 + ret = 1; 81 + } 82 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (0x1p-16445L)); 83 + if ((sw & FLAGS) != (C3 | C2)) { 84 + printf("FAIL: +denormal\n"); 85 + ret = 1; 86 + } 87 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (-0x1p-16445L)); 88 + if ((sw & FLAGS) != (C3 | C2 | C1)) { 89 + printf("FAIL: -denormal\n"); 90 + ret = 1; 91 + } 92 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_pseudo_m16382.ld)); 93 + if ((sw & FLAGS) != (C3 | C2)) { 94 + printf("FAIL: +pseudo-denormal\n"); 95 + ret = 1; 96 + } 97 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_pseudo_nm16382.ld)); 98 + if ((sw & FLAGS) != (C3 | C2 | C1)) { 99 + printf("FAIL: -pseudo-denormal\n"); 100 + ret = 1; 101 + } 102 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_1.ld)); 103 + if ((sw & FLAGS) != 0) { 104 + printf("FAIL: +invalid 1\n"); 105 + ret = 1; 106 + } 107 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n1.ld)); 108 + if ((sw & FLAGS) != C1) { 109 + printf("FAIL: -invalid 1\n"); 110 + ret = 1; 111 + } 112 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_2.ld)); 113 + if ((sw & FLAGS) != 0) { 114 + printf("FAIL: +invalid 2\n"); 115 + ret = 1; 116 + } 117 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n2.ld)); 118 + if ((sw & FLAGS) != C1) { 119 + printf("FAIL: -invalid 2\n"); 120 + ret = 1; 121 + } 122 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_3.ld)); 123 + if ((sw & FLAGS) != 0) { 124 + printf("FAIL: +invalid 3\n"); 125 + ret = 1; 126 + } 127 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n3.ld)); 128 + if ((sw & FLAGS) != C1) { 129 + printf("FAIL: -invalid 3\n"); 130 + ret = 1; 131 + } 132 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_4.ld)); 133 + if ((sw & FLAGS) != 0) { 134 + printf("FAIL: +invalid 4\n"); 135 + ret = 1; 136 + } 137 + __asm__ volatile ("fxam\nfnstsw" : "=a" (sw) : "t" (ld_invalid_n4.ld)); 138 + if ((sw & FLAGS) != C1) { 139 + printf("FAIL: -invalid 4\n"); 140 + ret = 1; 141 + } 142 + return ret; 143 + }