GNU Linux-libre 4.14.290-gnu1
[releases.git] / tools / testing / selftests / x86 / test_FISTTP.c
1 // SPDX-License-Identifier: GPL-2.0
2 #undef _GNU_SOURCE
3 #define _GNU_SOURCE 1
4 #undef __USE_GNU
5 #define __USE_GNU 1
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <signal.h>
11 #include <sys/types.h>
12 #include <sys/select.h>
13 #include <sys/time.h>
14 #include <sys/wait.h>
15 #include <fenv.h>
16
17 unsigned long long res64 = -1;
18 unsigned int res32 = -1;
19 unsigned short res16 = -1;
20
21 int test(void)
22 {
23         int ex;
24
25         feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
26         asm volatile ("\n"
27         "       fld1""\n"
28         "       fisttp  res16""\n"
29         "       fld1""\n"
30         "       fisttpl res32""\n"
31         "       fld1""\n"
32         "       fisttpll res64""\n"
33         : : : "memory"
34         );
35         if (res16 != 1 || res32 != 1 || res64 != 1) {
36                 printf("[BAD]\tfisttp 1\n");
37                 return 1;
38         }
39         ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
40         if (ex != 0) {
41                 printf("[BAD]\tfisttp 1: wrong exception state\n");
42                 return 1;
43         }
44
45         feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
46         asm volatile ("\n"
47         "       fldpi""\n"
48         "       fisttp  res16""\n"
49         "       fldpi""\n"
50         "       fisttpl res32""\n"
51         "       fldpi""\n"
52         "       fisttpll res64""\n"
53         : : : "memory"
54         );
55         if (res16 != 3 || res32 != 3 || res64 != 3) {
56                 printf("[BAD]\tfisttp pi\n");
57                 return 1;
58         }
59         ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
60         if (ex != FE_INEXACT) {
61                 printf("[BAD]\tfisttp pi: wrong exception state\n");
62                 return 1;
63         }
64
65         feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
66         asm volatile ("\n"
67         "       fldpi""\n"
68         "       fchs""\n"
69         "       fisttp  res16""\n"
70         "       fldpi""\n"
71         "       fchs""\n"
72         "       fisttpl res32""\n"
73         "       fldpi""\n"
74         "       fchs""\n"
75         "       fisttpll res64""\n"
76         : : : "memory"
77         );
78         if (res16 != 0xfffd || res32 != 0xfffffffd || res64 != 0xfffffffffffffffdULL) {
79                 printf("[BAD]\tfisttp -pi\n");
80                 return 1;
81         }
82         ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
83         if (ex != FE_INEXACT) {
84                 printf("[BAD]\tfisttp -pi: wrong exception state\n");
85                 return 1;
86         }
87
88         feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
89         asm volatile ("\n"
90         "       fldln2""\n"
91         "       fisttp  res16""\n"
92         "       fldln2""\n"
93         "       fisttpl res32""\n"
94         "       fldln2""\n"
95         "       fisttpll res64""\n"
96         : : : "memory"
97         );
98         /* Test truncation to zero (round-to-nearest would give 1 here) */
99         if (res16 != 0 || res32 != 0 || res64 != 0) {
100                 printf("[BAD]\tfisttp ln2\n");
101                 return 1;
102         }
103         ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
104         if (ex != FE_INEXACT) {
105                 printf("[BAD]\tfisttp ln2: wrong exception state\n");
106                 return 1;
107         }
108
109         return 0;
110 }
111
112 void sighandler(int sig)
113 {
114         printf("[FAIL]\tGot signal %d, exiting\n", sig);
115         exit(1);
116 }
117
118 int main(int argc, char **argv, char **envp)
119 {
120         int err = 0;
121
122         /* SIGILL triggers on 32-bit kernels w/o fisttp emulation
123          * when run with "no387 nofxsr". Other signals are caught
124          * just in case.
125          */
126         signal(SIGILL, sighandler);
127         signal(SIGFPE, sighandler);
128         signal(SIGSEGV, sighandler);
129
130         printf("[RUN]\tTesting fisttp instructions\n");
131         err |= test();
132         if (!err)
133                 printf("[OK]\tfisttp\n");
134         else
135                 printf("[FAIL]\tfisttp errors: %d\n", err);
136
137         return err;
138 }