qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

test-i386-fscale.c (3583B)


      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 long double ld_third = 1.0L / 3.0L;
     12 volatile long double ld_four_thirds = 4.0L / 3.0L;
     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 
     18 volatile long double ld_res;
     19 
     20 int isnan_ld(long double x)
     21 {
     22   union u tmp = { .ld = x };
     23   return ((tmp.s.sign_exp & 0x7fff) == 0x7fff &&
     24           (tmp.s.sig >> 63) != 0 &&
     25           (tmp.s.sig << 1) != 0);
     26 }
     27 
     28 int issignaling_ld(long double x)
     29 {
     30     union u tmp = { .ld = x };
     31     return isnan_ld(x) && (tmp.s.sig & UINT64_C(0x4000000000000000)) == 0;
     32 }
     33 
     34 int main(void)
     35 {
     36     short cw;
     37     int ret = 0;
     38     __asm__ volatile ("fscale" : "=t" (ld_res) :
     39                       "0" (2.5L), "u" (__builtin_nansl("")));
     40     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
     41         printf("FAIL: fscale snan\n");
     42         ret = 1;
     43     }
     44     __asm__ volatile ("fscale" : "=t" (ld_res) :
     45                       "0" (2.5L), "u" (ld_invalid_1.ld));
     46     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
     47         printf("FAIL: fscale invalid 1\n");
     48         ret = 1;
     49     }
     50     __asm__ volatile ("fscale" : "=t" (ld_res) :
     51                       "0" (2.5L), "u" (ld_invalid_2.ld));
     52     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
     53         printf("FAIL: fscale invalid 2\n");
     54         ret = 1;
     55     }
     56     __asm__ volatile ("fscale" : "=t" (ld_res) :
     57                       "0" (2.5L), "u" (ld_invalid_3.ld));
     58     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
     59         printf("FAIL: fscale invalid 3\n");
     60         ret = 1;
     61     }
     62     __asm__ volatile ("fscale" : "=t" (ld_res) :
     63                       "0" (2.5L), "u" (ld_invalid_4.ld));
     64     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
     65         printf("FAIL: fscale invalid 4\n");
     66         ret = 1;
     67     }
     68     __asm__ volatile ("fscale" : "=t" (ld_res) :
     69                       "0" (0.0L), "u" (__builtin_infl()));
     70     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
     71         printf("FAIL: fscale 0 up inf\n");
     72         ret = 1;
     73     }
     74     __asm__ volatile ("fscale" : "=t" (ld_res) :
     75                       "0" (__builtin_infl()), "u" (-__builtin_infl()));
     76     if (!isnan_ld(ld_res) || issignaling_ld(ld_res)) {
     77         printf("FAIL: fscale inf down inf\n");
     78         ret = 1;
     79     }
     80     /* Set round-downward.  */
     81     __asm__ volatile ("fnstcw %0" : "=m" (cw));
     82     cw = (cw & ~0xc00) | 0x400;
     83     __asm__ volatile ("fldcw %0" : : "m" (cw));
     84     __asm__ volatile ("fscale" : "=t" (ld_res) :
     85                       "0" (1.0L), "u" (__builtin_infl()));
     86     if (ld_res != __builtin_infl()) {
     87         printf("FAIL: fscale finite up inf\n");
     88         ret = 1;
     89     }
     90     __asm__ volatile ("fscale" : "=t" (ld_res) :
     91                       "0" (-1.0L), "u" (-__builtin_infl()));
     92     if (ld_res != -0.0L || __builtin_copysignl(1.0L, ld_res) != -1.0L) {
     93         printf("FAIL: fscale finite down inf\n");
     94         ret = 1;
     95     }
     96     /* Set round-to-nearest with single-precision rounding.  */
     97     cw = cw & ~0xf00;
     98     __asm__ volatile ("fldcw %0" : : "m" (cw));
     99     __asm__ volatile ("fscale" : "=t" (ld_res) :
    100                       "0" (ld_third), "u" (2.0L));
    101     cw = cw | 0x300;
    102     __asm__ volatile ("fldcw %0" : : "m" (cw));
    103     if (ld_res != ld_four_thirds) {
    104         printf("FAIL: fscale single-precision\n");
    105         ret = 1;
    106     }
    107     return ret;
    108 }