Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
a58e2ecd DV |
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 | ||
17 | unsigned long long res64 = -1; | |
18 | unsigned int res32 = -1; | |
19 | unsigned short res16 = -1; | |
20 | ||
21 | int 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 | ||
112 | void sighandler(int sig) | |
113 | { | |
114 | printf("[FAIL]\tGot signal %d, exiting\n", sig); | |
115 | exit(1); | |
116 | } | |
117 | ||
118 | int 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 | } |