xref: /qemu/tests/tcg/i386/test-i386-fscale.c (revision b40eec96b26028b68c3594fbf34b6d6f029df26a)
10d48b436SJoseph Myers /* Test fscale instruction.  */
20d48b436SJoseph Myers 
30d48b436SJoseph Myers #include <stdint.h>
40d48b436SJoseph Myers #include <stdio.h>
50d48b436SJoseph Myers 
60d48b436SJoseph Myers union u {
70d48b436SJoseph Myers     struct { uint64_t sig; uint16_t sign_exp; } s;
80d48b436SJoseph Myers     long double ld;
90d48b436SJoseph Myers };
100d48b436SJoseph Myers 
11*b40eec96SJoseph Myers volatile union u ld_invalid_1 = { .s = { 1, 1234 } };
12*b40eec96SJoseph Myers volatile union u ld_invalid_2 = { .s = { 0, 1234 } };
13*b40eec96SJoseph Myers volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } };
14*b40eec96SJoseph Myers volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } };
15*b40eec96SJoseph Myers 
160d48b436SJoseph Myers volatile long double ld_res;
170d48b436SJoseph Myers 
180d48b436SJoseph Myers int isnan_ld(long double x)
190d48b436SJoseph Myers {
200d48b436SJoseph Myers   union u tmp = { .ld = x };
210d48b436SJoseph Myers   return ((tmp.s.sign_exp & 0x7fff) == 0x7fff &&
220d48b436SJoseph Myers           (tmp.s.sig >> 63) != 0 &&
230d48b436SJoseph Myers           (tmp.s.sig << 1) != 0);
240d48b436SJoseph Myers }
250d48b436SJoseph Myers 
260d48b436SJoseph Myers int issignaling_ld(long double x)
270d48b436SJoseph Myers {
280d48b436SJoseph Myers     union u tmp = { .ld = x };
290d48b436SJoseph Myers     return isnan_ld(x) && (tmp.s.sig & UINT64_C(0x4000000000000000)) == 0;
300d48b436SJoseph Myers }
310d48b436SJoseph Myers 
320d48b436SJoseph Myers int main(void)
330d48b436SJoseph Myers {
340d48b436SJoseph Myers     int ret = 0;
350d48b436SJoseph Myers     __asm__ volatile ("fscale" : "=t" (ld_res) :
360d48b436SJoseph Myers                       "0" (2.5L), "u" (__builtin_nansl("")));
370d48b436SJoseph Myers     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
380d48b436SJoseph Myers         printf("FAIL: fscale snan\n");
390d48b436SJoseph Myers         ret = 1;
400d48b436SJoseph Myers     }
41*b40eec96SJoseph Myers     __asm__ volatile ("fscale" : "=t" (ld_res) :
42*b40eec96SJoseph Myers                       "0" (2.5L), "u" (ld_invalid_1.ld));
43*b40eec96SJoseph Myers     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
44*b40eec96SJoseph Myers         printf("FAIL: fscale invalid 1\n");
45*b40eec96SJoseph Myers         ret = 1;
46*b40eec96SJoseph Myers     }
47*b40eec96SJoseph Myers     __asm__ volatile ("fscale" : "=t" (ld_res) :
48*b40eec96SJoseph Myers                       "0" (2.5L), "u" (ld_invalid_2.ld));
49*b40eec96SJoseph Myers     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
50*b40eec96SJoseph Myers         printf("FAIL: fscale invalid 2\n");
51*b40eec96SJoseph Myers         ret = 1;
52*b40eec96SJoseph Myers     }
53*b40eec96SJoseph Myers     __asm__ volatile ("fscale" : "=t" (ld_res) :
54*b40eec96SJoseph Myers                       "0" (2.5L), "u" (ld_invalid_3.ld));
55*b40eec96SJoseph Myers     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
56*b40eec96SJoseph Myers         printf("FAIL: fscale invalid 3\n");
57*b40eec96SJoseph Myers         ret = 1;
58*b40eec96SJoseph Myers     }
59*b40eec96SJoseph Myers     __asm__ volatile ("fscale" : "=t" (ld_res) :
60*b40eec96SJoseph Myers                       "0" (2.5L), "u" (ld_invalid_4.ld));
61*b40eec96SJoseph Myers     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
62*b40eec96SJoseph Myers         printf("FAIL: fscale invalid 4\n");
63*b40eec96SJoseph Myers         ret = 1;
64*b40eec96SJoseph Myers     }
650d48b436SJoseph Myers     return ret;
660d48b436SJoseph Myers }
67