diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2015-09-17 09:02:13 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-09-20 04:19:52 -0400 |
commit | 57ca6897cd134efd8914cc230f602abad431c7db (patch) | |
tree | cb71434e669b053f27de7f70248e860620f8ab7c | |
parent | 73477bbb09e7022063d1737c7322ad2e08968c23 (diff) |
x86/fpu/math-emu, selftests: Add tests for FCMOV and FCOMI insns
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>
Link: http://lkml.kernel.org/r/1442494933-13798-1-git-send-email-dvlasenk@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/testing/selftests/x86/Makefile | 5 | ||||
-rw-r--r-- | tools/testing/selftests/x86/test_FCMOV.c | 93 | ||||
-rw-r--r-- | tools/testing/selftests/x86/test_FCOMI.c | 331 |
3 files changed, 427 insertions, 2 deletions
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 29089b24d18b..c4c9b9088998 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile | |||
@@ -5,7 +5,8 @@ include ../lib.mk | |||
5 | .PHONY: all all_32 all_64 warn_32bit_failure clean | 5 | .PHONY: all all_32 all_64 warn_32bit_failure clean |
6 | 6 | ||
7 | TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt | 7 | TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt |
8 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn | 8 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn \ |
9 | test_FCMOV test_FCOMI | ||
9 | 10 | ||
10 | TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) | 11 | TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) |
11 | BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) | 12 | BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) |
@@ -35,7 +36,7 @@ clean: | |||
35 | $(RM) $(BINARIES_32) $(BINARIES_64) | 36 | $(RM) $(BINARIES_32) $(BINARIES_64) |
36 | 37 | ||
37 | $(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c | 38 | $(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c |
38 | $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl | 39 | $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm |
39 | 40 | ||
40 | $(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c | 41 | $(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c |
41 | $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl | 42 | $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl |
diff --git a/tools/testing/selftests/x86/test_FCMOV.c b/tools/testing/selftests/x86/test_FCMOV.c new file mode 100644 index 000000000000..4adcca0c80c4 --- /dev/null +++ b/tools/testing/selftests/x86/test_FCMOV.c | |||
@@ -0,0 +1,93 @@ | |||
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 | |||
15 | #define TEST(insn) \ | ||
16 | long double __attribute__((noinline)) insn(long flags) \ | ||
17 | { \ | ||
18 | long double out; \ | ||
19 | asm ("\n" \ | ||
20 | " push %1""\n" \ | ||
21 | " popf""\n" \ | ||
22 | " fldpi""\n" \ | ||
23 | " fld1""\n" \ | ||
24 | " " #insn " %%st(1), %%st" "\n" \ | ||
25 | " ffree %%st(1)" "\n" \ | ||
26 | : "=t" (out) \ | ||
27 | : "r" (flags) \ | ||
28 | ); \ | ||
29 | return out; \ | ||
30 | } | ||
31 | |||
32 | TEST(fcmovb) | ||
33 | TEST(fcmove) | ||
34 | TEST(fcmovbe) | ||
35 | TEST(fcmovu) | ||
36 | TEST(fcmovnb) | ||
37 | TEST(fcmovne) | ||
38 | TEST(fcmovnbe) | ||
39 | TEST(fcmovnu) | ||
40 | |||
41 | enum { | ||
42 | CF = 1 << 0, | ||
43 | PF = 1 << 2, | ||
44 | ZF = 1 << 6, | ||
45 | }; | ||
46 | |||
47 | void sighandler(int sig) | ||
48 | { | ||
49 | printf("[FAIL]\tGot signal %d, exiting\n", sig); | ||
50 | exit(1); | ||
51 | } | ||
52 | |||
53 | int main(int argc, char **argv, char **envp) | ||
54 | { | ||
55 | int err = 0; | ||
56 | |||
57 | /* SIGILL triggers on 32-bit kernels w/o fcomi emulation | ||
58 | * when run with "no387 nofxsr". Other signals are caught | ||
59 | * just in case. | ||
60 | */ | ||
61 | signal(SIGILL, sighandler); | ||
62 | signal(SIGFPE, sighandler); | ||
63 | signal(SIGSEGV, sighandler); | ||
64 | |||
65 | printf("[RUN]\tTesting fcmovCC instructions\n"); | ||
66 | /* If fcmovCC() returns 1.0, the move wasn't done */ | ||
67 | err |= !(fcmovb(0) == 1.0); err |= !(fcmovnb(0) != 1.0); | ||
68 | err |= !(fcmove(0) == 1.0); err |= !(fcmovne(0) != 1.0); | ||
69 | err |= !(fcmovbe(0) == 1.0); err |= !(fcmovnbe(0) != 1.0); | ||
70 | err |= !(fcmovu(0) == 1.0); err |= !(fcmovnu(0) != 1.0); | ||
71 | |||
72 | err |= !(fcmovb(CF) != 1.0); err |= !(fcmovnb(CF) == 1.0); | ||
73 | err |= !(fcmove(CF) == 1.0); err |= !(fcmovne(CF) != 1.0); | ||
74 | err |= !(fcmovbe(CF) != 1.0); err |= !(fcmovnbe(CF) == 1.0); | ||
75 | err |= !(fcmovu(CF) == 1.0); err |= !(fcmovnu(CF) != 1.0); | ||
76 | |||
77 | err |= !(fcmovb(ZF) == 1.0); err |= !(fcmovnb(ZF) != 1.0); | ||
78 | err |= !(fcmove(ZF) != 1.0); err |= !(fcmovne(ZF) == 1.0); | ||
79 | err |= !(fcmovbe(ZF) != 1.0); err |= !(fcmovnbe(ZF) == 1.0); | ||
80 | err |= !(fcmovu(ZF) == 1.0); err |= !(fcmovnu(ZF) != 1.0); | ||
81 | |||
82 | err |= !(fcmovb(PF) == 1.0); err |= !(fcmovnb(PF) != 1.0); | ||
83 | err |= !(fcmove(PF) == 1.0); err |= !(fcmovne(PF) != 1.0); | ||
84 | err |= !(fcmovbe(PF) == 1.0); err |= !(fcmovnbe(PF) != 1.0); | ||
85 | err |= !(fcmovu(PF) != 1.0); err |= !(fcmovnu(PF) == 1.0); | ||
86 | |||
87 | if (!err) | ||
88 | printf("[OK]\tfcmovCC\n"); | ||
89 | else | ||
90 | printf("[FAIL]\tfcmovCC errors: %d\n", err); | ||
91 | |||
92 | return err; | ||
93 | } | ||
diff --git a/tools/testing/selftests/x86/test_FCOMI.c b/tools/testing/selftests/x86/test_FCOMI.c new file mode 100644 index 000000000000..db4933e31af9 --- /dev/null +++ b/tools/testing/selftests/x86/test_FCOMI.c | |||
@@ -0,0 +1,331 @@ | |||
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 | enum { | ||
17 | CF = 1 << 0, | ||
18 | PF = 1 << 2, | ||
19 | ZF = 1 << 6, | ||
20 | ARITH = CF | PF | ZF, | ||
21 | }; | ||
22 | |||
23 | long res_fcomi_pi_1; | ||
24 | long res_fcomi_1_pi; | ||
25 | long res_fcomi_1_1; | ||
26 | long res_fcomi_nan_1; | ||
27 | /* sNaN is s|111 1111 1|1xx xxxx xxxx xxxx xxxx xxxx */ | ||
28 | /* qNaN is s|111 1111 1|0xx xxxx xxxx xxxx xxxx xxxx (some x must be nonzero) */ | ||
29 | int snan = 0x7fc11111; | ||
30 | int qnan = 0x7f811111; | ||
31 | unsigned short snan1[5]; | ||
32 | /* sNaN80 is s|111 1111 1111 1111 |10xx xx...xx (some x must be nonzero) */ | ||
33 | unsigned short snan80[5] = { 0x1111, 0x1111, 0x1111, 0x8111, 0x7fff }; | ||
34 | |||
35 | int test(long flags) | ||
36 | { | ||
37 | feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); | ||
38 | |||
39 | asm ("\n" | ||
40 | |||
41 | " push %0""\n" | ||
42 | " popf""\n" | ||
43 | " fld1""\n" | ||
44 | " fldpi""\n" | ||
45 | " fcomi %%st(1), %%st" "\n" | ||
46 | " ffree %%st(0)" "\n" | ||
47 | " ffree %%st(1)" "\n" | ||
48 | " pushf""\n" | ||
49 | " pop res_fcomi_1_pi""\n" | ||
50 | |||
51 | " push %0""\n" | ||
52 | " popf""\n" | ||
53 | " fldpi""\n" | ||
54 | " fld1""\n" | ||
55 | " fcomi %%st(1), %%st" "\n" | ||
56 | " ffree %%st(0)" "\n" | ||
57 | " ffree %%st(1)" "\n" | ||
58 | " pushf""\n" | ||
59 | " pop res_fcomi_pi_1""\n" | ||
60 | |||
61 | " push %0""\n" | ||
62 | " popf""\n" | ||
63 | " fld1""\n" | ||
64 | " fld1""\n" | ||
65 | " fcomi %%st(1), %%st" "\n" | ||
66 | " ffree %%st(0)" "\n" | ||
67 | " ffree %%st(1)" "\n" | ||
68 | " pushf""\n" | ||
69 | " pop res_fcomi_1_1""\n" | ||
70 | : | ||
71 | : "r" (flags) | ||
72 | ); | ||
73 | if ((res_fcomi_1_pi & ARITH) != (0)) { | ||
74 | printf("[BAD]\tfcomi_1_pi with flags:%lx\n", flags); | ||
75 | return 1; | ||
76 | } | ||
77 | if ((res_fcomi_pi_1 & ARITH) != (CF)) { | ||
78 | printf("[BAD]\tfcomi_pi_1 with flags:%lx->%lx\n", flags, res_fcomi_pi_1 & ARITH); | ||
79 | return 1; | ||
80 | } | ||
81 | if ((res_fcomi_1_1 & ARITH) != (ZF)) { | ||
82 | printf("[BAD]\tfcomi_1_1 with flags:%lx\n", flags); | ||
83 | return 1; | ||
84 | } | ||
85 | if (fetestexcept(FE_INVALID) != 0) { | ||
86 | printf("[BAD]\tFE_INVALID is set in %s\n", __func__); | ||
87 | return 1; | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | int test_qnan(long flags) | ||
93 | { | ||
94 | feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); | ||
95 | |||
96 | asm ("\n" | ||
97 | " push %0""\n" | ||
98 | " popf""\n" | ||
99 | " flds qnan""\n" | ||
100 | " fld1""\n" | ||
101 | " fnclex""\n" // fld of a qnan raised FE_INVALID, clear it | ||
102 | " fcomi %%st(1), %%st" "\n" | ||
103 | " ffree %%st(0)" "\n" | ||
104 | " ffree %%st(1)" "\n" | ||
105 | " pushf""\n" | ||
106 | " pop res_fcomi_nan_1""\n" | ||
107 | : | ||
108 | : "r" (flags) | ||
109 | ); | ||
110 | if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { | ||
111 | printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); | ||
112 | return 1; | ||
113 | } | ||
114 | if (fetestexcept(FE_INVALID) != FE_INVALID) { | ||
115 | printf("[BAD]\tFE_INVALID is not set in %s\n", __func__); | ||
116 | return 1; | ||
117 | } | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | int testu_qnan(long flags) | ||
122 | { | ||
123 | feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); | ||
124 | |||
125 | asm ("\n" | ||
126 | " push %0""\n" | ||
127 | " popf""\n" | ||
128 | " flds qnan""\n" | ||
129 | " fld1""\n" | ||
130 | " fnclex""\n" // fld of a qnan raised FE_INVALID, clear it | ||
131 | " fucomi %%st(1), %%st" "\n" | ||
132 | " ffree %%st(0)" "\n" | ||
133 | " ffree %%st(1)" "\n" | ||
134 | " pushf""\n" | ||
135 | " pop res_fcomi_nan_1""\n" | ||
136 | : | ||
137 | : "r" (flags) | ||
138 | ); | ||
139 | if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { | ||
140 | printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); | ||
141 | return 1; | ||
142 | } | ||
143 | if (fetestexcept(FE_INVALID) != 0) { | ||
144 | printf("[BAD]\tFE_INVALID is set in %s\n", __func__); | ||
145 | return 1; | ||
146 | } | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | int testu_snan(long flags) | ||
151 | { | ||
152 | feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); | ||
153 | |||
154 | asm ("\n" | ||
155 | " push %0""\n" | ||
156 | " popf""\n" | ||
157 | // " flds snan""\n" // WRONG, this will convert 32-bit fp snan to a *qnan* in 80-bit fp register! | ||
158 | // " fstpt snan1""\n" // if uncommented, it prints "snan1:7fff c111 1100 0000 0000" - c111, not 8111! | ||
159 | // " fnclex""\n" // flds of a snan raised FE_INVALID, clear it | ||
160 | " fldt snan80""\n" // fldt never raise FE_INVALID | ||
161 | " fld1""\n" | ||
162 | " fucomi %%st(1), %%st" "\n" | ||
163 | " ffree %%st(0)" "\n" | ||
164 | " ffree %%st(1)" "\n" | ||
165 | " pushf""\n" | ||
166 | " pop res_fcomi_nan_1""\n" | ||
167 | : | ||
168 | : "r" (flags) | ||
169 | ); | ||
170 | if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { | ||
171 | printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); | ||
172 | return 1; | ||
173 | } | ||
174 | // printf("snan:%x snan1:%04x %04x %04x %04x %04x\n", snan, snan1[4], snan1[3], snan1[2], snan1[1], snan1[0]); | ||
175 | if (fetestexcept(FE_INVALID) != FE_INVALID) { | ||
176 | printf("[BAD]\tFE_INVALID is not set in %s\n", __func__); | ||
177 | return 1; | ||
178 | } | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | int testp(long flags) | ||
183 | { | ||
184 | feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); | ||
185 | |||
186 | asm ("\n" | ||
187 | |||
188 | " push %0""\n" | ||
189 | " popf""\n" | ||
190 | " fld1""\n" | ||
191 | " fldpi""\n" | ||
192 | " fcomip %%st(1), %%st" "\n" | ||
193 | " ffree %%st(0)" "\n" | ||
194 | " pushf""\n" | ||
195 | " pop res_fcomi_1_pi""\n" | ||
196 | |||
197 | " push %0""\n" | ||
198 | " popf""\n" | ||
199 | " fldpi""\n" | ||
200 | " fld1""\n" | ||
201 | " fcomip %%st(1), %%st" "\n" | ||
202 | " ffree %%st(0)" "\n" | ||
203 | " pushf""\n" | ||
204 | " pop res_fcomi_pi_1""\n" | ||
205 | |||
206 | " push %0""\n" | ||
207 | " popf""\n" | ||
208 | " fld1""\n" | ||
209 | " fld1""\n" | ||
210 | " fcomip %%st(1), %%st" "\n" | ||
211 | " ffree %%st(0)" "\n" | ||
212 | " pushf""\n" | ||
213 | " pop res_fcomi_1_1""\n" | ||
214 | : | ||
215 | : "r" (flags) | ||
216 | ); | ||
217 | if ((res_fcomi_1_pi & ARITH) != (0)) { | ||
218 | printf("[BAD]\tfcomi_1_pi with flags:%lx\n", flags); | ||
219 | return 1; | ||
220 | } | ||
221 | if ((res_fcomi_pi_1 & ARITH) != (CF)) { | ||
222 | printf("[BAD]\tfcomi_pi_1 with flags:%lx->%lx\n", flags, res_fcomi_pi_1 & ARITH); | ||
223 | return 1; | ||
224 | } | ||
225 | if ((res_fcomi_1_1 & ARITH) != (ZF)) { | ||
226 | printf("[BAD]\tfcomi_1_1 with flags:%lx\n", flags); | ||
227 | return 1; | ||
228 | } | ||
229 | if (fetestexcept(FE_INVALID) != 0) { | ||
230 | printf("[BAD]\tFE_INVALID is set in %s\n", __func__); | ||
231 | return 1; | ||
232 | } | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | int testp_qnan(long flags) | ||
237 | { | ||
238 | feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); | ||
239 | |||
240 | asm ("\n" | ||
241 | " push %0""\n" | ||
242 | " popf""\n" | ||
243 | " flds qnan""\n" | ||
244 | " fld1""\n" | ||
245 | " fnclex""\n" // fld of a qnan raised FE_INVALID, clear it | ||
246 | " fcomip %%st(1), %%st" "\n" | ||
247 | " ffree %%st(0)" "\n" | ||
248 | " pushf""\n" | ||
249 | " pop res_fcomi_nan_1""\n" | ||
250 | : | ||
251 | : "r" (flags) | ||
252 | ); | ||
253 | if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { | ||
254 | printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); | ||
255 | return 1; | ||
256 | } | ||
257 | if (fetestexcept(FE_INVALID) != FE_INVALID) { | ||
258 | printf("[BAD]\tFE_INVALID is not set in %s\n", __func__); | ||
259 | return 1; | ||
260 | } | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | int testup_qnan(long flags) | ||
265 | { | ||
266 | feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); | ||
267 | |||
268 | asm ("\n" | ||
269 | " push %0""\n" | ||
270 | " popf""\n" | ||
271 | " flds qnan""\n" | ||
272 | " fld1""\n" | ||
273 | " fnclex""\n" // fld of a qnan raised FE_INVALID, clear it | ||
274 | " fucomip %%st(1), %%st" "\n" | ||
275 | " ffree %%st(0)" "\n" | ||
276 | " pushf""\n" | ||
277 | " pop res_fcomi_nan_1""\n" | ||
278 | : | ||
279 | : "r" (flags) | ||
280 | ); | ||
281 | if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { | ||
282 | printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); | ||
283 | return 1; | ||
284 | } | ||
285 | if (fetestexcept(FE_INVALID) != 0) { | ||
286 | printf("[BAD]\tFE_INVALID is set in %s\n", __func__); | ||
287 | return 1; | ||
288 | } | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | void sighandler(int sig) | ||
293 | { | ||
294 | printf("[FAIL]\tGot signal %d, exiting\n", sig); | ||
295 | exit(1); | ||
296 | } | ||
297 | |||
298 | int main(int argc, char **argv, char **envp) | ||
299 | { | ||
300 | int err = 0; | ||
301 | |||
302 | /* SIGILL triggers on 32-bit kernels w/o fcomi emulation | ||
303 | * when run with "no387 nofxsr". Other signals are caught | ||
304 | * just in case. | ||
305 | */ | ||
306 | signal(SIGILL, sighandler); | ||
307 | signal(SIGFPE, sighandler); | ||
308 | signal(SIGSEGV, sighandler); | ||
309 | |||
310 | printf("[RUN]\tTesting f[u]comi[p] instructions\n"); | ||
311 | err |= test(0); | ||
312 | err |= test_qnan(0); | ||
313 | err |= testu_qnan(0); | ||
314 | err |= testu_snan(0); | ||
315 | err |= test(CF|ZF|PF); | ||
316 | err |= test_qnan(CF|ZF|PF); | ||
317 | err |= testu_qnan(CF|ZF|PF); | ||
318 | err |= testu_snan(CF|ZF|PF); | ||
319 | err |= testp(0); | ||
320 | err |= testp_qnan(0); | ||
321 | err |= testup_qnan(0); | ||
322 | err |= testp(CF|ZF|PF); | ||
323 | err |= testp_qnan(CF|ZF|PF); | ||
324 | err |= testup_qnan(CF|ZF|PF); | ||
325 | if (!err) | ||
326 | printf("[OK]\tf[u]comi[p]\n"); | ||
327 | else | ||
328 | printf("[FAIL]\tf[u]comi[p] errors: %d\n", err); | ||
329 | |||
330 | return err; | ||
331 | } | ||