Skip to content

Commit a58e2ec

Browse files
dvlasenkIngo Molnar
authored andcommitted
x86/fpu/math-emu, selftests: Add test for FISTTP instructions
$ ./test_FISTTP_32 [RUN] Testing fisttp instructions [OK] fisttp Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Shuah Khan <shuahkh@osg.samsung.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/1442757790-27233-1-git-send-email-dvlasenk@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 9a9d864 commit a58e2ec

File tree

2 files changed

+138
-1
lines changed

2 files changed

+138
-1
lines changed

tools/testing/selftests/x86/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ include ../lib.mk
66

77
TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt
88
TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn \
9-
test_FCMOV test_FCOMI
9+
test_FCMOV test_FCOMI test_FISTTP
1010

1111
TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
1212
BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
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+
}

0 commit comments

Comments
 (0)