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

source code of linux/tools/testing/selftests/x86/test_FISTTP.c