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 short cw; 35 int ret = 0; 36 __asm__ volatile ("fscale" : "=t" (ld_res) : 37 "0" (2.5L), "u" (__builtin_nansl(""))); 38 if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { 39 printf("FAIL: fscale snan\n"); 40 ret = 1; 41 } 42 __asm__ volatile ("fscale" : "=t" (ld_res) : 43 "0" (2.5L), "u" (ld_invalid_1.ld)); 44 if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { 45 printf("FAIL: fscale invalid 1\n"); 46 ret = 1; 47 } 48 __asm__ volatile ("fscale" : "=t" (ld_res) : 49 "0" (2.5L), "u" (ld_invalid_2.ld)); 50 if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { 51 printf("FAIL: fscale invalid 2\n"); 52 ret = 1; 53 } 54 __asm__ volatile ("fscale" : "=t" (ld_res) : 55 "0" (2.5L), "u" (ld_invalid_3.ld)); 56 if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { 57 printf("FAIL: fscale invalid 3\n"); 58 ret = 1; 59 } 60 __asm__ volatile ("fscale" : "=t" (ld_res) : 61 "0" (2.5L), "u" (ld_invalid_4.ld)); 62 if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { 63 printf("FAIL: fscale invalid 4\n"); 64 ret = 1; 65 } 66 __asm__ volatile ("fscale" : "=t" (ld_res) : 67 "0" (0.0L), "u" (__builtin_infl())); 68 if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { 69 printf("FAIL: fscale 0 up inf\n"); 70 ret = 1; 71 } 72 __asm__ volatile ("fscale" : "=t" (ld_res) : 73 "0" (__builtin_infl()), "u" (-__builtin_infl())); 74 if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) { 75 printf("FAIL: fscale inf down inf\n"); 76 ret = 1; 77 } 78 /* Set round-downward. */ 79 __asm__ volatile ("fnstcw %0" : "=m" (cw)); 80 cw = (cw & ~0xc00) | 0x400; 81 __asm__ volatile ("fldcw %0" : : "m" (cw)); 82 __asm__ volatile ("fscale" : "=t" (ld_res) : 83 "0" (1.0L), "u" (__builtin_infl())); 84 if (ld_res != __builtin_infl()) { 85 printf("FAIL: fscale finite up inf\n"); 86 ret = 1; 87 } 88 __asm__ volatile ("fscale" : "=t" (ld_res) : 89 "0" (-1.0L), "u" (-__builtin_infl())); 90 if (ld_res != -0.0L || __builtin_copysignl(1.0L, ld_res) != -1.0L) { 91 printf("FAIL: fscale finite down inf\n"); 92 ret = 1; 93 } 94 return ret; 95 } 96