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