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