• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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