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 
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 	"	fisttp	res16""\n"
28 	"	fld1""\n"
29 	"	fisttpl	res32""\n"
30 	"	fld1""\n"
31 	"	fisttpll res64""\n"
32 	: : : "memory"
33 	);
34 	if (res16 != 1 || res32 != 1 || res64 != 1) {
35 		printf("[BAD]\tfisttp 1\n");
36 		return 1;
37 	}
38 	ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
39 	if (ex != 0) {
40 		printf("[BAD]\tfisttp 1: wrong exception state\n");
41 		return 1;
42 	}
43 
44 	feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
45 	asm volatile ("\n"
46 	"	fldpi""\n"
47 	"	fisttp	res16""\n"
48 	"	fldpi""\n"
49 	"	fisttpl	res32""\n"
50 	"	fldpi""\n"
51 	"	fisttpll res64""\n"
52 	: : : "memory"
53 	);
54 	if (res16 != 3 || res32 != 3 || res64 != 3) {
55 		printf("[BAD]\tfisttp pi\n");
56 		return 1;
57 	}
58 	ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
59 	if (ex != FE_INEXACT) {
60 		printf("[BAD]\tfisttp pi: wrong exception state\n");
61 		return 1;
62 	}
63 
64 	feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
65 	asm volatile ("\n"
66 	"	fldpi""\n"
67 	"	fchs""\n"
68 	"	fisttp	res16""\n"
69 	"	fldpi""\n"
70 	"	fchs""\n"
71 	"	fisttpl	res32""\n"
72 	"	fldpi""\n"
73 	"	fchs""\n"
74 	"	fisttpll res64""\n"
75 	: : : "memory"
76 	);
77 	if (res16 != 0xfffd || res32 != 0xfffffffd || res64 != 0xfffffffffffffffdULL) {
78 		printf("[BAD]\tfisttp -pi\n");
79 		return 1;
80 	}
81 	ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
82 	if (ex != FE_INEXACT) {
83 		printf("[BAD]\tfisttp -pi: wrong exception state\n");
84 		return 1;
85 	}
86 
87 	feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
88 	asm volatile ("\n"
89 	"	fldln2""\n"
90 	"	fisttp	res16""\n"
91 	"	fldln2""\n"
92 	"	fisttpl	res32""\n"
93 	"	fldln2""\n"
94 	"	fisttpll res64""\n"
95 	: : : "memory"
96 	);
97 	/* Test truncation to zero (round-to-nearest would give 1 here) */
98 	if (res16 != 0 || res32 != 0 || res64 != 0) {
99 		printf("[BAD]\tfisttp ln2\n");
100 		return 1;
101 	}
102 	ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
103 	if (ex != FE_INEXACT) {
104 		printf("[BAD]\tfisttp ln2: wrong exception state\n");
105 		return 1;
106 	}
107 
108 	return 0;
109 }
110 
111 void sighandler(int sig)
112 {
113 	printf("[FAIL]\tGot signal %d, exiting\n", sig);
114 	exit(1);
115 }
116 
117 int main(int argc, char **argv, char **envp)
118 {
119 	int err = 0;
120 
121 	/* SIGILL triggers on 32-bit kernels w/o fisttp emulation
122 	 * when run with "no387 nofxsr". Other signals are caught
123 	 * just in case.
124 	 */
125 	signal(SIGILL, sighandler);
126 	signal(SIGFPE, sighandler);
127 	signal(SIGSEGV, sighandler);
128 
129 	printf("[RUN]\tTesting fisttp instructions\n");
130 	err |= test();
131 	if (!err)
132 		printf("[OK]\tfisttp\n");
133 	else
134 		printf("[FAIL]\tfisttp errors: %d\n", err);
135 
136 	return err;
137 }
138