1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <stdio.h>
23
24const int FPINVF_BIT = 1;
25const int FPINVF = 1 << FPINVF_BIT;
26const int FPDBZF_BIT = 2;
27const int FPDBZF = 1 << FPDBZF_BIT;
28const int FPOVFF_BIT = 3;
29const int FPOVFF = 1 << FPOVFF_BIT;
30const int FPUNFF_BIT = 4;
31const int FPUNFF = 1 << FPUNFF_BIT;
32const int FPINPF_BIT = 5;
33const int FPINPF = 1 << FPINPF_BIT;
34
35const int SF_ZERO = 0x00000000;
36const int SF_NaN = 0x7fc00000;
37const int SF_NaN_special = 0x7f800001;
38const int SF_ANY = 0x3f800000;
39const int SF_HEX_NAN = 0xffffffff;
40
41const long long DF_NaN = 0x7ff8000000000000ULL;
42const long long DF_ANY = 0x3f80000000000000ULL;
43const long long DF_HEX_NAN = 0xffffffffffffffffULL;
44
45int err;
46
47#define CLEAR_FPSTATUS \
48 "r2 = usr\n\t" \
49 "r2 = clrbit(r2, #1)\n\t" \
50 "r2 = clrbit(r2, #2)\n\t" \
51 "r2 = clrbit(r2, #3)\n\t" \
52 "r2 = clrbit(r2, #4)\n\t" \
53 "r2 = clrbit(r2, #5)\n\t" \
54 "usr = r2\n\t"
55
56static void check_fpstatus_bit(int usr, int expect, int flag, const char *n)
57{
58 int bit = 1 << flag;
59 if ((usr & bit) != (expect & bit)) {
60 printf("ERROR %s: usr = %d, expect = %d\n", n,
61 (usr >> flag) & 1, (expect >> flag) & 1);
62 err++;
63 }
64}
65
66static void check_fpstatus(int usr, int expect)
67{
68 check_fpstatus_bit(usr, expect, FPINVF_BIT, "Invalid");
69 check_fpstatus_bit(usr, expect, FPDBZF_BIT, "Div by zero");
70 check_fpstatus_bit(usr, expect, FPOVFF_BIT, "Overflow");
71 check_fpstatus_bit(usr, expect, FPUNFF_BIT, "Underflow");
72 check_fpstatus_bit(usr, expect, FPINPF_BIT, "Inexact");
73}
74
75static void check32(int val, int expect)
76{
77 if (val != expect) {
78 printf("ERROR: 0x%x != 0x%x\n", val, expect);
79 err++;
80 }
81}
82static void check64(unsigned long long val, unsigned long long expect)
83{
84 if (val != expect) {
85 printf("ERROR: 0x%llx != 0x%llx\n", val, expect);
86 err++;
87 }
88}
89
90static void check_compare_exception(void)
91{
92 int cmp;
93 int usr;
94
95
96 asm (CLEAR_FPSTATUS
97 "p0 = sfcmp.eq(%2, %3)\n\t"
98 "%0 = p0\n\t"
99 "%1 = usr\n\t"
100 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
101 : "r2", "p0", "usr");
102 check32(cmp, 0);
103 check_fpstatus(usr, 0);
104
105 asm (CLEAR_FPSTATUS
106 "p0 = sfcmp.gt(%2, %3)\n\t"
107 "%0 = p0\n\t"
108 "%1 = usr\n\t"
109 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
110 : "r2", "p0", "usr");
111 check32(cmp, 0);
112 check_fpstatus(usr, 0);
113
114 asm (CLEAR_FPSTATUS
115 "p0 = sfcmp.ge(%2, %3)\n\t"
116 "%0 = p0\n\t"
117 "%1 = usr\n\t"
118 : "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
119 : "r2", "p0", "usr");
120 check32(cmp, 0);
121 check_fpstatus(usr, 0);
122
123 asm (CLEAR_FPSTATUS
124 "p0 = dfcmp.eq(%2, %3)\n\t"
125 "%0 = p0\n\t"
126 "%1 = usr\n\t"
127 : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
128 : "r2", "p0", "usr");
129 check32(cmp, 0);
130 check_fpstatus(usr, 0);
131
132 asm (CLEAR_FPSTATUS
133 "p0 = dfcmp.gt(%2, %3)\n\t"
134 "%0 = p0\n\t"
135 "%1 = usr\n\t"
136 : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
137 : "r2", "p0", "usr");
138 check32(cmp, 0);
139 check_fpstatus(usr, 0);
140
141 asm (CLEAR_FPSTATUS
142 "p0 = dfcmp.ge(%2, %3)\n\t"
143 "%0 = p0\n\t"
144 "%1 = usr\n\t"
145 : "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
146 : "r2", "p0", "usr");
147 check32(cmp, 0);
148 check_fpstatus(usr, 0);
149}
150
151static void check_sfminmax(void)
152{
153 int minmax;
154 int usr;
155
156
157
158
159
160
161
162 asm (CLEAR_FPSTATUS
163 "%0 = sfmin(%2, %3)\n\t"
164 "%1 = usr\n\t"
165 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
166 : "r2", "usr");
167 check64(minmax, SF_ANY);
168 check_fpstatus(usr, 0);
169
170 asm (CLEAR_FPSTATUS
171 "%0 = sfmax(%2, %3)\n\t"
172 "%1 = usr\n\t"
173 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
174 : "r2", "usr");
175 check64(minmax, SF_ANY);
176 check_fpstatus(usr, 0);
177
178
179
180
181
182
183
184 asm (CLEAR_FPSTATUS
185 "%0 = sfmin(%2, %3)\n\t"
186 "%1 = usr\n\t"
187 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
188 : "r2", "usr");
189 check64(minmax, SF_HEX_NAN);
190 check_fpstatus(usr, 0);
191
192 asm (CLEAR_FPSTATUS
193 "%0 = sfmax(%2, %3)\n\t"
194 "%1 = usr\n\t"
195 : "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
196 : "r2", "usr");
197 check64(minmax, SF_HEX_NAN);
198 check_fpstatus(usr, 0);
199}
200
201static void check_dfminmax(void)
202{
203 unsigned long long minmax;
204 int usr;
205
206
207
208
209
210
211
212 asm (CLEAR_FPSTATUS
213 "%0 = dfmin(%2, %3)\n\t"
214 "%1 = usr\n\t"
215 : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
216 : "r2", "usr");
217 check64(minmax, DF_ANY);
218 check_fpstatus(usr, FPINVF);
219
220 asm (CLEAR_FPSTATUS
221 "%0 = dfmax(%2, %3)\n\t"
222 "%1 = usr\n\t"
223 : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
224 : "r2", "usr");
225 check64(minmax, DF_ANY);
226 check_fpstatus(usr, FPINVF);
227
228
229
230
231
232
233
234 asm (CLEAR_FPSTATUS
235 "%0 = dfmin(%2, %3)\n\t"
236 "%1 = usr\n\t"
237 : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_NaN)
238 : "r2", "usr");
239 check64(minmax, DF_HEX_NAN);
240 check_fpstatus(usr, FPINVF);
241
242 asm (CLEAR_FPSTATUS
243 "%0 = dfmax(%2, %3)\n\t"
244 "%1 = usr\n\t"
245 : "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_NaN)
246 : "r2", "usr");
247 check64(minmax, DF_HEX_NAN);
248 check_fpstatus(usr, FPINVF);
249}
250
251static void check_canonical_NaN(void)
252{
253 int sf_result;
254 unsigned long long df_result;
255 int usr;
256
257
258 asm(CLEAR_FPSTATUS
259 "%0 = sfadd(%2, %3)\n\t"
260 "%1 = usr\n\t"
261 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
262 : "r2", "usr");
263 check32(sf_result, SF_HEX_NAN);
264 check_fpstatus(usr, 0);
265
266 asm(CLEAR_FPSTATUS
267 "%0 = sfsub(%2, %3)\n\t"
268 "%1 = usr\n\t"
269 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
270 : "r2", "usr");
271 check32(sf_result, SF_HEX_NAN);
272 check_fpstatus(usr, 0);
273
274 asm(CLEAR_FPSTATUS
275 "%0 = sfmpy(%2, %3)\n\t"
276 "%1 = usr\n\t"
277 : "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
278 : "r2", "usr");
279 check32(sf_result, SF_HEX_NAN);
280 check_fpstatus(usr, 0);
281
282 sf_result = SF_ZERO;
283 asm(CLEAR_FPSTATUS
284 "%0 += sfmpy(%2, %3)\n\t"
285 "%1 = usr\n\t"
286 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
287 : "r2", "usr");
288 check32(sf_result, SF_HEX_NAN);
289 check_fpstatus(usr, 0);
290
291 sf_result = SF_ZERO;
292 asm(CLEAR_FPSTATUS
293 "p0 = !cmp.eq(r0, r0)\n\t"
294 "%0 += sfmpy(%2, %3, p0):scale\n\t"
295 "%1 = usr\n\t"
296 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
297 : "r2", "usr", "p0");
298 check32(sf_result, SF_HEX_NAN);
299 check_fpstatus(usr, 0);
300
301 sf_result = SF_ZERO;
302 asm(CLEAR_FPSTATUS
303 "%0 -= sfmpy(%2, %3)\n\t"
304 "%1 = usr\n\t"
305 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
306 : "r2", "usr");
307 check32(sf_result, SF_HEX_NAN);
308 check_fpstatus(usr, 0);
309
310 sf_result = SF_ZERO;
311 asm(CLEAR_FPSTATUS
312 "%0 += sfmpy(%2, %3):lib\n\t"
313 "%1 = usr\n\t"
314 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
315 : "r2", "usr");
316 check32(sf_result, SF_HEX_NAN);
317 check_fpstatus(usr, 0);
318
319 sf_result = SF_ZERO;
320 asm(CLEAR_FPSTATUS
321 "%0 -= sfmpy(%2, %3):lib\n\t"
322 "%1 = usr\n\t"
323 : "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
324 : "r2", "usr");
325 check32(sf_result, SF_HEX_NAN);
326 check_fpstatus(usr, 0);
327
328 asm(CLEAR_FPSTATUS
329 "%0 = convert_df2sf(%2)\n\t"
330 "%1 = usr\n\t"
331 : "=r"(sf_result), "=r"(usr) : "r"(DF_NaN)
332 : "r2", "usr");
333 check32(sf_result, SF_HEX_NAN);
334 check_fpstatus(usr, 0);
335
336 asm(CLEAR_FPSTATUS
337 "%0 = dfadd(%2, %3)\n\t"
338 "%1 = usr\n\t"
339 : "=r"(df_result), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
340 : "r2", "usr");
341 check64(df_result, DF_HEX_NAN);
342 check_fpstatus(usr, 0);
343
344 asm(CLEAR_FPSTATUS
345 "%0 = dfsub(%2, %3)\n\t"
346 "%1 = usr\n\t"
347 : "=r"(df_result), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
348 : "r2", "usr");
349 check64(df_result, DF_HEX_NAN);
350 check_fpstatus(usr, 0);
351
352 asm(CLEAR_FPSTATUS
353 "%0 = convert_sf2df(%2)\n\t"
354 "%1 = usr\n\t"
355 : "=r"(df_result), "=r"(usr) : "r"(SF_NaN)
356 : "r2", "usr");
357 check64(df_result, DF_HEX_NAN);
358 check_fpstatus(usr, 0);
359}
360
361int main()
362{
363 check_compare_exception();
364 check_sfminmax();
365 check_dfminmax();
366 check_canonical_NaN();
367
368 puts(err ? "FAIL" : "PASS");
369 return err ? 1 : 0;
370}
371