xref: /qemu/tests/tcg/i386/test-i386-fscale.c (revision b40eec96b26028b68c3594fbf34b6d6f029df26a)
1 /* Test fscale 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_invalid_1 = { .s = { 1, 1234 } };
12 volatile union u ld_invalid_2 = { .s = { 0, 1234 } };
13 volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } };
14 volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } };
15 
16 volatile long double ld_res;
17 
18 int isnan_ld(long double x)
19 {
20   union u tmp = { .ld = x };
21   return ((tmp.s.sign_exp & 0x7fff) == 0x7fff &&
22           (tmp.s.sig >> 63) != 0 &&
23           (tmp.s.sig << 1) != 0);
24 }
25 
26 int issignaling_ld(long double x)
27 {
28     union u tmp = { .ld = x };
29     return isnan_ld(x) && (tmp.s.sig & UINT64_C(0x4000000000000000)) == 0;
30 }
31 
32 int main(void)
33 {
34     int ret = 0;
35     __asm__ volatile ("fscale" : "=t" (ld_res) :
36                       "0" (2.5L), "u" (__builtin_nansl("")));
37     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
38         printf("FAIL: fscale snan\n");
39         ret = 1;
40     }
41     __asm__ volatile ("fscale" : "=t" (ld_res) :
42                       "0" (2.5L), "u" (ld_invalid_1.ld));
43     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
44         printf("FAIL: fscale invalid 1\n");
45         ret = 1;
46     }
47     __asm__ volatile ("fscale" : "=t" (ld_res) :
48                       "0" (2.5L), "u" (ld_invalid_2.ld));
49     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
50         printf("FAIL: fscale invalid 2\n");
51         ret = 1;
52     }
53     __asm__ volatile ("fscale" : "=t" (ld_res) :
54                       "0" (2.5L), "u" (ld_invalid_3.ld));
55     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
56         printf("FAIL: fscale invalid 3\n");
57         ret = 1;
58     }
59     __asm__ volatile ("fscale" : "=t" (ld_res) :
60                       "0" (2.5L), "u" (ld_invalid_4.ld));
61     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
62         printf("FAIL: fscale invalid 4\n");
63         ret = 1;
64     }
65     return ret;
66 }
67