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