drd/tests/swapcontext: Improve the portability of this test further
[valgrind.git] / none / tests / ppc32 / test_dfp3.c
blobf8596de38f366bbb9b4faf5fdfb4cf9627940af5
1 /* Copyright (C) 2012 IBM
3 Author: Maynard Johnson <maynardj@us.ibm.com>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
18 The GNU General Public License is contained in the file COPYING.
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <string.h>
26 #if defined(HAS_DFP)
28 register double f14 __asm__ ("fr14");
29 register double f15 __asm__ ("fr15");
30 register double f16 __asm__ ("fr16");
31 register double f17 __asm__ ("fr17");
32 register double f18 __asm__ ("fr18");
33 register double f19 __asm__ ("fr19");
36 typedef unsigned char Bool;
37 #define True 1
38 #define False 0
41 #define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
43 #define SET_CR(_arg) \
44 __asm__ __volatile__ ("mtcr %0" : : "b"(_arg) : ALLCR );
46 #define SET_XER(_arg) \
47 __asm__ __volatile__ ("mtxer %0" : : "b"(_arg) : "xer" );
49 #define GET_CR(_lval) \
50 __asm__ __volatile__ ("mfcr %0" : "=b"(_lval) )
52 #define GET_XER(_lval) \
53 __asm__ __volatile__ ("mfxer %0" : "=b"(_lval) )
55 #define GET_CR_XER(_lval_cr,_lval_xer) \
56 do { GET_CR(_lval_cr); GET_XER(_lval_xer); } while (0)
58 #define SET_CR_ZERO \
59 SET_CR(0)
61 #define SET_XER_ZERO \
62 SET_XER(0)
64 #define SET_CR_XER_ZERO \
65 do { SET_CR_ZERO; SET_XER_ZERO; } while (0)
67 #define SET_FPSCR_ZERO \
68 do { double _d = 0.0; \
69 __asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \
70 } while (0)
72 #define GET_FPSCR(_arg) \
73 __asm__ __volatile__ ("mffs %0" : "=f"(_arg) )
75 #define SET_FPSCR_DRN \
76 __asm__ __volatile__ ("mtfsf 1, %0, 0, 1" : : "f"(f14) )
79 // The assembly-level instructions being tested
80 static void _test_drintx(int R, int RMC)
82 if (RMC < 0 || RMC > 3 || R < 0 || R > 1) {
83 fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", R, RMC);
84 return;
86 switch (RMC) {
87 case 0:
88 if (R)
89 __asm__ __volatile__ ("drintx 1, %0, %1, 0" : "=f" (f18) : "f" (f16));
90 else
91 __asm__ __volatile__ ("drintx 0, %0, %1, 0" : "=f" (f18) : "f" (f16));
92 break;
93 case 1:
94 if (R)
95 __asm__ __volatile__ ("drintx 1, %0, %1, 1" : "=f" (f18) : "f" (f16));
96 else
97 __asm__ __volatile__ ("drintx 0, %0, %1, 1" : "=f" (f18) : "f" (f16));
98 break;
99 case 2:
100 if (R)
101 __asm__ __volatile__ ("drintx 1, %0, %1, 2" : "=f" (f18) : "f" (f16));
102 else
103 __asm__ __volatile__ ("drintx 0, %0, %1, 2" : "=f" (f18) : "f" (f16));
104 break;
105 case 3:
106 if (R)
107 __asm__ __volatile__ ("drintx 1, %0, %1, 3" : "=f" (f18) : "f" (f16));
108 else
109 __asm__ __volatile__ ("drintx 0, %0, %1, 3" : "=f" (f18) : "f" (f16));
110 break;
111 default:
112 break;
116 static void _test_drintn(int R, int RMC)
118 if (RMC < 0 || RMC > 3 || R < 0 || R > 1) {
119 fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", R, RMC);
120 return;
122 switch (RMC) {
123 case 0:
124 if (R)
125 __asm__ __volatile__ ("drintn 1, %0, %1, 0" : "=f" (f18) : "f" (f16));
126 else
127 __asm__ __volatile__ ("drintn 0, %0, %1, 0" : "=f" (f18) : "f" (f16));
128 break;
129 case 1:
130 if (R)
131 __asm__ __volatile__ ("drintn 1, %0, %1, 1" : "=f" (f18) : "f" (f16));
132 else
133 __asm__ __volatile__ ("drintn 0, %0, %1, 1" : "=f" (f18) : "f" (f16));
134 break;
135 case 2:
136 if (R)
137 __asm__ __volatile__ ("drintn 1, %0, %1, 2" : "=f" (f18) : "f" (f16));
138 else
139 __asm__ __volatile__ ("drintn 0, %0, %1, 2" : "=f" (f18) : "f" (f16));
140 break;
141 case 3:
142 if (R)
143 __asm__ __volatile__ ("drintn 1, %0, %1, 3" : "=f" (f18) : "f" (f16));
144 else
145 __asm__ __volatile__ ("drintn 0, %0, %1, 3" : "=f" (f18) : "f" (f16));
146 break;
147 default:
148 break;
153 static void _test_diex(int a __attribute__((unused)), int b __attribute__((unused)))
155 __asm__ __volatile__ ("diex %0, %1, %2" : "=f" (f18) : "f" (f14),"f" (f16));
158 static void _test_dxex(int a __attribute__((unused)), int b __attribute__((unused)))
160 __asm__ __volatile__ ("dxex %0, %1" : "=f" (f18) : "f" (f16));
163 static void _test_dcmpo(int BF, int x __attribute__((unused)))
165 if (BF < 0 || BF > 7) {
166 fprintf(stderr, "Invalid input to asm test: a=%d\n", BF);
167 return;
169 switch (BF) {
170 case 0:
171 __asm__ __volatile__ ("dcmpo 0, %0, %1" : : "f" (f14),"f" (f16));
172 break;
173 case 1:
174 __asm__ __volatile__ ("dcmpo 1, %0, %1" : : "f" (f14),"f" (f16));
175 break;
176 case 2:
177 __asm__ __volatile__ ("dcmpo 2, %0, %1" : : "f" (f14),"f" (f16));
178 break;
179 case 3:
180 __asm__ __volatile__ ("dcmpo 3, %0, %1" : : "f" (f14),"f" (f16));
181 break;
182 case 4:
183 __asm__ __volatile__ ("dcmpo 4, %0, %1" : : "f" (f14),"f" (f16));
184 break;
185 case 5:
186 __asm__ __volatile__ ("dcmpo 5, %0, %1" : : "f" (f14),"f" (f16));
187 break;
188 case 6:
189 __asm__ __volatile__ ("dcmpo 6, %0, %1" : : "f" (f14),"f" (f16));
190 break;
191 case 7:
192 __asm__ __volatile__ ("dcmpo 7, %0, %1" : : "f" (f14),"f" (f16));
193 break;
194 default:
195 break;
199 static void _test_dcmpu(int BF, int x __attribute__((unused)))
201 if (BF < 0 || BF > 7) {
202 fprintf(stderr, "Invalid input to asm test: a=%d\n", BF);
203 return;
205 switch (BF) {
206 case 0:
207 __asm__ __volatile__ ("dcmpu 0, %0, %1" : : "f" (f14),"f" (f16));
208 break;
209 case 1:
210 __asm__ __volatile__ ("dcmpu 1, %0, %1" : : "f" (f14),"f" (f16));
211 break;
212 case 2:
213 __asm__ __volatile__ ("dcmpu 2, %0, %1" : : "f" (f14),"f" (f16));
214 break;
215 case 3:
216 __asm__ __volatile__ ("dcmpu 3, %0, %1" : : "f" (f14),"f" (f16));
217 break;
218 case 4:
219 __asm__ __volatile__ ("dcmpu 4, %0, %1" : : "f" (f14),"f" (f16));
220 break;
221 case 5:
222 __asm__ __volatile__ ("dcmpu 5, %0, %1" : : "f" (f14),"f" (f16));
223 break;
224 case 6:
225 __asm__ __volatile__ ("dcmpu 6, %0, %1" : : "f" (f14),"f" (f16));
226 break;
227 case 7:
228 __asm__ __volatile__ ("dcmpu 7, %0, %1" : : "f" (f14),"f" (f16));
229 break;
230 default:
231 break;
235 // Quad instruction testing
236 static void _test_drintxq(int R, int RMC)
238 if (RMC < 0 || RMC > 3 || R < 0 || R > 1) {
239 fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", R, RMC);
240 return;
242 switch (RMC) {
243 case 0:
244 if (R)
245 __asm__ __volatile__ ("drintxq 1, %0, %1, 0" : "=f" (f18) : "f" (f16));
246 else
247 __asm__ __volatile__ ("drintxq 0, %0, %1, 0" : "=f" (f18) : "f" (f16));
248 break;
249 case 1:
250 if (R)
251 __asm__ __volatile__ ("drintxq 1, %0, %1, 1" : "=f" (f18) : "f" (f16));
252 else
253 __asm__ __volatile__ ("drintxq 0, %0, %1, 1" : "=f" (f18) : "f" (f16));
254 break;
255 case 2:
256 if (R)
257 __asm__ __volatile__ ("drintxq 1, %0, %1, 2" : "=f" (f18) : "f" (f16));
258 else
259 __asm__ __volatile__ ("drintxq 0, %0, %1, 2" : "=f" (f18) : "f" (f16));
260 break;
261 case 3:
262 if (R)
263 __asm__ __volatile__ ("drintxq 1, %0, %1, 3" : "=f" (f18) : "f" (f16));
264 else
265 __asm__ __volatile__ ("drintxq 0, %0, %1, 3" : "=f" (f18) : "f" (f16));
266 break;
267 default:
268 break;
272 static void _test_drintnq(int R, int RMC)
274 if (RMC < 0 || RMC > 3 || R < 0 || R > 1) {
275 fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", R, RMC);
276 return;
278 switch (RMC) {
279 case 0:
280 if (R)
281 __asm__ __volatile__ ("drintnq 1, %0, %1, 0" : "=f" (f18) : "f" (f16));
282 else
283 __asm__ __volatile__ ("drintnq 0, %0, %1, 0" : "=f" (f18) : "f" (f16));
284 break;
285 case 1:
286 if (R)
287 __asm__ __volatile__ ("drintnq 1, %0, %1, 1" : "=f" (f18) : "f" (f16));
288 else
289 __asm__ __volatile__ ("drintnq 0, %0, %1, 1" : "=f" (f18) : "f" (f16));
290 break;
291 case 2:
292 if (R)
293 __asm__ __volatile__ ("drintnq 1, %0, %1, 2" : "=f" (f18) : "f" (f16));
294 else
295 __asm__ __volatile__ ("drintnq 0, %0, %1, 2" : "=f" (f18) : "f" (f16));
296 break;
297 case 3:
298 if (R)
299 __asm__ __volatile__ ("drintnq 1, %0, %1, 3" : "=f" (f18) : "f" (f16));
300 else
301 __asm__ __volatile__ ("drintnq 0, %0, %1, 3" : "=f" (f18) : "f" (f16));
302 break;
303 default:
304 break;
308 static void _test_diexq(int a __attribute__((unused)), int b __attribute__((unused)))
310 __asm__ __volatile__ ("diexq %0, %1, %2" : "=f" (f18) : "f" (f14),"f" (f16));
313 static void _test_dxexq(int a __attribute__((unused)), int b __attribute__((unused)))
315 __asm__ __volatile__ ("dxexq %0, %1" : "=f" (f18) : "f" (f16));
318 static void _test_dcmpoq(int BF, int x __attribute__((unused)))
320 if (BF < 0 || BF > 7) {
321 fprintf(stderr, "Invalid input to asm test: a=%d\n", BF );
322 return;
324 switch (BF) {
325 case 0:
326 __asm__ __volatile__ ("dcmpoq 0, %0, %1" : : "f" (f14),"f" (f16));
327 break;
328 case 1:
329 __asm__ __volatile__ ("dcmpoq 1, %0, %1" : : "f" (f14),"f" (f16));
330 break;
331 case 2:
332 __asm__ __volatile__ ("dcmpoq 2, %0, %1" : : "f" (f14),"f" (f16));
333 break;
334 case 3:
335 __asm__ __volatile__ ("dcmpoq 3, %0, %1" : : "f" (f14),"f" (f16));
336 break;
337 case 4:
338 __asm__ __volatile__ ("dcmpoq 4, %0, %1" : : "f" (f14),"f" (f16));
339 break;
340 case 5:
341 __asm__ __volatile__ ("dcmpoq 5, %0, %1" : : "f" (f14),"f" (f16));
342 break;
343 case 6:
344 __asm__ __volatile__ ("dcmpoq 6, %0, %1" : : "f" (f14),"f" (f16));
345 break;
346 case 7:
347 __asm__ __volatile__ ("dcmpoq 7, %0, %1" : : "f" (f14),"f" (f16));
348 break;
349 default:
350 break;
354 static void _test_dcmpuq(int BF, int x __attribute__((unused)))
356 if (BF < 0 || BF > 7) {
357 fprintf(stderr, "Invalid input to asm test: a=%d\n", BF);
358 return;
360 switch (BF) {
361 case 0:
362 __asm__ __volatile__ ("dcmpuq 0, %0, %1" : : "f" (f14),"f" (f16));
363 break;
364 case 1:
365 __asm__ __volatile__ ("dcmpuq 1, %0, %1" : : "f" (f14),"f" (f16));
366 break;
367 case 2:
368 __asm__ __volatile__ ("dcmpuq 2, %0, %1" : : "f" (f14),"f" (f16));
369 break;
370 case 3:
371 __asm__ __volatile__ ("dcmpuq 3, %0, %1" : : "f" (f14),"f" (f16));
372 break;
373 case 4:
374 __asm__ __volatile__ ("dcmpuq 4, %0, %1" : : "f" (f14),"f" (f16));
375 break;
376 case 5:
377 __asm__ __volatile__ ("dcmpuq 5, %0, %1" : : "f" (f14),"f" (f16));
378 break;
379 case 6:
380 __asm__ __volatile__ ("dcmpuq 6, %0, %1" : : "f" (f14),"f" (f16));
381 break;
382 case 7:
383 __asm__ __volatile__ ("dcmpuq 7, %0, %1" : : "f" (f14),"f" (f16));
384 break;
385 default:
386 break;
390 static void _test_drrnd(int x __attribute__((unused)), int RMC)
392 if (RMC < 0 || RMC > 31) {
393 fprintf(stderr, "Invalid input to asm test: a=%d\n", RMC);
394 return;
396 switch (RMC) {
397 case 0:
398 __asm__ __volatile__ ("drrnd %0, %1, %2, 0" : "=f" (f18) : "f" (f14), "f" (f16));
399 break;
400 case 1:
401 __asm__ __volatile__ ("drrnd %0, %1, %2, 1" : "=f" (f18) : "f" (f14), "f" (f16));
402 break;
403 case 2:
404 __asm__ __volatile__ ("drrnd %0, %1, %2, 2" : "=f" (f18) : "f" (f14), "f" (f16));
405 break;
406 case 3:
407 __asm__ __volatile__ ("drrnd %0, %1, %2, 3" : "=f" (f18) : "f" (f14), "f" (f16));
408 break;
409 default:
410 break;
414 static void _test_drrndq(int x __attribute__((unused)), int RMC)
416 if (RMC < 0 || RMC > 3) {
417 fprintf(stderr, "Invalid input to asm test: a=%dn", RMC);
418 return;
420 switch (RMC) {
421 case 0:
422 __asm__ __volatile__ ("drrndq %0, %1, %2, 0" : "=f" (f18) : "f" (f14), "f" (f16));
423 break;
424 case 1:
425 __asm__ __volatile__ ("drrndq %0, %1, %2, 1" : "=f" (f18) : "f" (f14), "f" (f16));
426 break;
427 case 2:
428 __asm__ __volatile__ ("drrndq %0, %1, %2, 2" : "=f" (f18) : "f" (f14), "f" (f16));
429 break;
430 case 3:
431 __asm__ __volatile__ ("drrndq %0, %1, %2, 3" : "=f" (f18) : "f" (f14), "f" (f16));
432 break;
433 default:
434 break;
438 static void _test_dqua(int x __attribute__((unused)), int RMC)
440 if (RMC < 0 || RMC > 3) {
441 fprintf(stderr, "Invalid input to asm test: a=%d\n", RMC);
442 return;
444 switch (RMC) {
445 case 0:
446 __asm__ __volatile__ ("dqua %0, %1, %2, 0" : "=f" (f18) : "f" (f14), "f" (f16));
447 break;
448 case 1:
449 __asm__ __volatile__ ("dqua %0, %1, %2, 1" : "=f" (f18) : "f" (f14), "f" (f16));
450 break;
451 case 2:
452 __asm__ __volatile__ ("dqua %0, %1, %2, 2" : "=f" (f18) : "f" (f14), "f" (f16));
453 break;
454 case 3:
455 __asm__ __volatile__ ("dqua %0, %1, %2, 3" : "=f" (f18) : "f" (f14), "f" (f16));
456 break;
457 default:
458 break;
462 static void _test_dquaq(int x __attribute__((unused)), int RMC)
464 if (RMC < 0 || RMC > 3) {
465 fprintf(stderr, "Invalid input to asm test: a=%d\n", RMC);
466 return;
468 switch (RMC) {
469 case 0:
470 __asm__ __volatile__ ("dquaq %0, %1, %2, 0" : "=f" (f18) : "f" (f14), "f" (f16));
471 break;
472 case 1:
473 __asm__ __volatile__ ("dquaq %0, %1, %2, 1" : "=f" (f18) : "f" (f14), "f" (f16));
474 break;
475 case 2:
476 __asm__ __volatile__ ("dquaq %0, %1, %2, 2" : "=f" (f18) : "f" (f14), "f" (f16));
477 break;
478 case 3:
479 __asm__ __volatile__ ("dquaq %0, %1, %2, 3" : "=f" (f18) : "f" (f14), "f" (f16));
480 break;
481 default:
482 break;
486 static int TE_vals[] = { -16, -2, 0, 5};
487 #define TE_VAL_LEN sizeof(TE_vals)/sizeof(int)
488 static Bool __is_TE_val(int x)
490 int i;
491 for (i = 0; i < TE_VAL_LEN; i++) {
492 if (x==TE_vals[i])
493 return True;
495 return False;
498 static void _test_dquai(int TE, int RMC)
500 if (RMC < 0 || RMC > 3 || !__is_TE_val(TE)) {
501 fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", TE, RMC);
502 return;
504 switch (RMC) {
505 case 0:
506 switch (TE) {
507 case -16:
508 __asm__ __volatile__ ("dquai -16, %0, %1, 0" : "=f" (f18) : "f" (f16));
509 break;
510 case -2:
511 __asm__ __volatile__ ("dquai -2, %0, %1, 0" : "=f" (f18) : "f" (f16));
512 break;
513 case 0:
514 __asm__ __volatile__ ("dquai 0, %0, %1, 0" : "=f" (f18) : "f" (f16));
515 break;
516 case 5:
517 __asm__ __volatile__ ("dquai 5, %0, %1, 0" : "=f" (f18) : "f" (f16));
518 break;
519 default:
520 break;
522 break;
523 case 1:
524 switch (TE) {
525 case -16:
526 __asm__ __volatile__ ("dquai -16, %0, %1, 1" : "=f" (f18) : "f" (f16));
527 break;
528 case -2:
529 __asm__ __volatile__ ("dquai -2, %0, %1, 1" : "=f" (f18) : "f" (f16));
530 break;
531 case 0:
532 __asm__ __volatile__ ("dquai 0, %0, %1, 1" : "=f" (f18) : "f" (f16));
533 break;
534 case 5:
535 __asm__ __volatile__ ("dquai 5, %0, %1, 1" : "=f" (f18) : "f" (f16));
536 break;
537 default:
538 break;
540 break;
541 case 2:
542 switch (TE) {
543 case -16:
544 __asm__ __volatile__ ("dquai -16, %0, %1, 2" : "=f" (f18) : "f" (f16));
545 break;
546 case -2:
547 __asm__ __volatile__ ("dquai -2, %0, %1, 2" : "=f" (f18) : "f" (f16));
548 break;
549 case 0:
550 __asm__ __volatile__ ("dquai 0, %0, %1, 2" : "=f" (f18) : "f" (f16));
551 break;
552 case 5:
553 __asm__ __volatile__ ("dquai 5, %0, %1, 2" : "=f" (f18) : "f" (f16));
554 break;
555 default:
556 break;
558 break;
559 case 3:
560 switch (TE) {
561 case -16:
562 __asm__ __volatile__ ("dquai -16, %0, %1, 3" : "=f" (f18) : "f" (f16));
563 break;
564 case -2:
565 __asm__ __volatile__ ("dquai -2, %0, %1, 3" : "=f" (f18) : "f" (f16));
566 break;
567 case 0:
568 __asm__ __volatile__ ("dquai 0, %0, %1, 3" : "=f" (f18) : "f" (f16));
569 break;
570 case 5:
571 __asm__ __volatile__ ("dquai 5, %0, %1, 3" : "=f" (f18) : "f" (f16));
572 break;
573 default:
574 break;
576 break;
577 default:
578 break;
582 static void _test_dquaiq(int TE, int RMC)
584 if (RMC < 0 || RMC > 3 || !__is_TE_val(TE)) {
585 fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", TE, RMC);
586 return;
588 switch (RMC) {
589 case 0:
590 switch (TE) {
591 case -16:
592 __asm__ __volatile__ ("dquaiq -16, %0, %1, 0" : "=f" (f18) : "f" (f16));
593 break;
594 case -2:
595 __asm__ __volatile__ ("dquaiq -2, %0, %1, 0" : "=f" (f18) : "f" (f16));
596 break;
597 case 0:
598 __asm__ __volatile__ ("dquaiq 0, %0, %1, 0" : "=f" (f18) : "f" (f16));
599 break;
600 case 5:
601 __asm__ __volatile__ ("dquaiq 5, %0, %1, 0" : "=f" (f18) : "f" (f16));
602 break;
603 default:
604 break;
606 break;
607 case 1:
608 switch (TE) {
609 case -16:
610 __asm__ __volatile__ ("dquaiq -16, %0, %1, 1" : "=f" (f18) : "f" (f16));
611 break;
612 case -2:
613 __asm__ __volatile__ ("dquaiq -2, %0, %1, 1" : "=f" (f18) : "f" (f16));
614 break;
615 case 0:
616 __asm__ __volatile__ ("dquaiq 0, %0, %1, 1" : "=f" (f18) : "f" (f16));
617 break;
618 case 5:
619 __asm__ __volatile__ ("dquaiq 5, %0, %1, 1" : "=f" (f18) : "f" (f16));
620 break;
621 default:
622 break;
624 break;
625 case 2:
626 switch (TE) {
627 case -16:
628 __asm__ __volatile__ ("dquaiq -16, %0, %1, 2" : "=f" (f18) : "f" (f16));
629 break;
630 case -2:
631 __asm__ __volatile__ ("dquaiq -2, %0, %1, 2" : "=f" (f18) : "f" (f16));
632 break;
633 case 0:
634 __asm__ __volatile__ ("dquaiq 0, %0, %1, 2" : "=f" (f18) : "f" (f16));
635 break;
636 case 5:
637 __asm__ __volatile__ ("dquaiq 5, %0, %1, 2" : "=f" (f18) : "f" (f16));
638 break;
639 default:
640 break;
642 break;
643 case 3:
644 switch (TE) {
645 case -16:
646 __asm__ __volatile__ ("dquaiq -16, %0, %1, 3" : "=f" (f18) : "f" (f16));
647 break;
648 case -2:
649 __asm__ __volatile__ ("dquaiq -2, %0, %1, 3" : "=f" (f18) : "f" (f16));
650 break;
651 case 0:
652 __asm__ __volatile__ ("dquaiq 0, %0, %1, 3" : "=f" (f18) : "f" (f16));
653 break;
654 case 5:
655 __asm__ __volatile__ ("dquaiq 5, %0, %1, 3" : "=f" (f18) : "f" (f16));
656 break;
657 default:
658 break;
660 break;
661 default:
662 break;
667 typedef void (*test_func_t)(int a, int b);
668 typedef void (*test_driver_func_t)(void);
669 typedef struct test_table
671 test_driver_func_t test_category;
672 char * name;
673 } test_table_t;
676 * 345.0DD (0x2207c00000000000 0xe50)
677 * 1.2300e+5DD (0x2207c00000000000 0x14c000)
678 * -16.0DD (0xa207c00000000000 0xe0)
679 * 0.00189DD (0x2206c00000000000 0xcf)
680 * -4.1235DD (0xa205c00000000000 0x10a395bcf)
681 * 9.8399e+20DD (0x2209400000000000 0x253f1f534acdd4)
682 * 0DD (0x2208000000000000 0x0)
683 * 0DD (0x2208000000000000 0x0)
684 * infDD (0x7800000000000000 0x0)
685 * nanDD (0x7c00000000000000 0x0
687 static unsigned long long dfp128_vals[] = {
688 // Some finite numbers
689 0x2207c00000000000ULL, 0x0000000000000e50ULL,
690 0x2207c00000000000ULL, 0x000000000014c000ULL,
691 0xa207c00000000000ULL, 0x00000000000000e0ULL,
692 0x2206c00000000000ULL, 0x00000000000000cfULL,
693 0xa205c00000000000ULL, 0x000000010a395bcfULL,
694 0x6209400000fd0000ULL, 0x00253f1f534acdd4ULL, // huge number
695 0x000400000089b000ULL, 0x0a6000d000000049ULL, // very small number
696 // flavors of zero
697 0x2208000000000000ULL, 0x0000000000000000ULL,
698 0xa208000000000000ULL, 0x0000000000000000ULL, // negative
699 0xa248000000000000ULL, 0x0000000000000000ULL,
700 // flavors of NAN
701 0x7c00000000000000ULL, 0x0000000000000000ULL, // quiet
702 0xfc00000000000000ULL, 0xc00100035b007700ULL,
703 0x7e00000000000000ULL, 0xfe000000d0e0a0d0ULL, // signaling
704 // flavors of Infinity
705 0x7800000000000000ULL, 0x0000000000000000ULL,
706 0xf800000000000000ULL, 0x0000000000000000ULL, // negative
707 0xf900000000000000ULL, 0x0000000000000000ULL
710 static unsigned long long dfp64_vals[] = {
711 // various finite numbers
712 0x2234000000000e50ULL,
713 0x223400000014c000ULL,
714 0xa2340000000000e0ULL,// negative
715 0x22240000000000cfULL,
716 0xa21400010a395bcfULL,// negative
717 0x6e4d3f1f534acdd4ULL,// huge number
718 0x000400000089b000ULL,// very small number
719 // flavors of zero
720 0x2238000000000000ULL,
721 0xa238000000000000ULL,
722 0x4248000000000000ULL,
723 // flavors of NAN
724 0x7e34000000000111ULL,
725 0xfe000000d0e0a0d0ULL,//signaling
726 0xfc00000000000000ULL,//quiet
727 // flavors of Infinity
728 0x7800000000000000ULL,
729 0xf800000000000000ULL,//negative
730 0x7a34000000000000ULL,
733 // Both Long and Quad arrays of DFP values should have the same length.
734 // If that length is changed, t
735 #define NUM_DFP_VALS (sizeof(dfp64_vals)/8)
737 typedef struct dfp_test_args {
738 int fra_idx;
739 int frb_idx;
740 } dfp_test_args_t;
743 // Index pairs from dfp64_vals array to be used with dfp_two_arg_tests
744 static dfp_test_args_t dfp_2args_x1[] = {
745 {0, 1},
746 {2, 1},
747 {3, 4},
748 {0, 6},
749 {2, 4},
750 {5, 1},
751 {5, 2},
752 {7, 1},
753 {7, 2},
754 {8, 0},
755 {8, 1},
756 {8, 2},
757 {7, 8},
758 {12, 14},
759 {12, 1},
760 {12, 13},
761 {12, 12},
762 {12, 11},
763 {11, 14},
764 {11, 0},
765 {11, 13},
766 {11, 11},
767 {14, 14},
768 {14, 3},
769 {14, 15},
772 typedef enum {
773 LONG_TEST,
774 QUAD_TEST
775 } precision_type_t;
777 typedef struct dfp_test
779 test_func_t test_func;
780 const char * name;
781 dfp_test_args_t * targs;
782 int num_tests;
783 precision_type_t precision;
784 const char * op;
785 } dfp_test_t;
787 typedef struct dfp_one_arg_test
789 test_func_t test_func;
790 const char * name;
791 precision_type_t precision;
792 const char * op;
793 } dfp_one_arg_test_t;
796 static dfp_one_arg_test_t
797 dfp_quai_tests[] = {
798 { &_test_dquai, "dquai", LONG_TEST, "[QI]"},
799 { &_test_dquaiq, "dquaiq", QUAD_TEST, "[QI]"},
800 { NULL, NULL, 0, NULL}
803 static void test_dfp_quai_ops(void)
805 test_func_t func;
806 unsigned long long u0, u0x;
807 double res, d0, *d0p, d0x, *d0xp;
809 int k = 0;
810 u0 = u0x = 0;
811 d0p = &d0;
812 d0xp = &d0x;
814 while ((func = dfp_quai_tests[k].test_func)) {
815 int i;
816 dfp_one_arg_test_t test_def = dfp_quai_tests[k];
818 for (i = 0; i < NUM_DFP_VALS; i++) {
819 int TE, RMC;
821 if (test_def.precision == LONG_TEST) {
822 u0 = dfp64_vals[i];
823 } else {
824 u0 = dfp128_vals[i * 2];
825 u0x = dfp128_vals[(i * 2) + 1];
827 *(unsigned long long *)d0p = u0;
828 f16 = d0;
829 if (test_def.precision == QUAD_TEST) {
830 *(unsigned long long *)d0xp = u0x;
831 f17 = d0x;
834 for (TE = 0; TE < TE_VAL_LEN; TE++) {
835 for (RMC = 0; RMC < 4; RMC++) {
836 (*func)(TE_vals[TE], RMC);
837 res = f18;
838 printf("%s (RMC=%2d, TE=%3d) %s %016llx", test_def.name, RMC,
839 TE_vals[TE], test_def.op, u0);
840 if (test_def.precision == LONG_TEST) {
841 printf(" => %016llx\n",
842 *((unsigned long long *)(&res)));
843 } else {
844 double resx = f19;
845 printf(" %016llx ==> %016llx %016llx\n",
846 u0x, *((unsigned long long *)(&res)), *((unsigned long long *)(&resx)));
851 k++;
852 printf( "\n" );
857 static dfp_test_t
858 dfp_qua_tests[] = {
859 { &_test_dqua, "dqua", dfp_2args_x1, 25, LONG_TEST, "[Q]"},
860 { &_test_dquaq, "dquaq", dfp_2args_x1, 25, QUAD_TEST, "[Q]"},
861 { NULL, NULL, NULL, 0, 0, NULL}
864 static void test_dfp_qua_ops(void)
866 test_func_t func;
867 unsigned long long u0, u0x, u1, u1x;
868 double res, d0, d1, *d0p, *d1p;
869 double d0x, d1x, *d0xp, *d1xp;
870 int k = 0;
871 u0x = u1x = 0;
872 d0p = &d0;
873 d0xp = &d0x;
874 d1p = &d1;
875 d1xp = &d1x;
877 while ((func = dfp_qua_tests[k].test_func)) {
878 int i, RMC;
879 dfp_test_t test_def = dfp_qua_tests[k];
881 for (i = 0; i < test_def.num_tests; i++) {
882 if (test_def.precision == LONG_TEST) {
883 u0 = dfp64_vals[test_def.targs[i].fra_idx];
884 u1 = dfp64_vals[test_def.targs[i].frb_idx];
885 } else {
886 u0 = dfp128_vals[test_def.targs[i].fra_idx * 2];
887 u0x = dfp128_vals[(test_def.targs[i].fra_idx * 2) + 1];
888 u1 = dfp128_vals[test_def.targs[i].frb_idx * 2];
889 u1x = dfp128_vals[(test_def.targs[i].frb_idx * 2) + 1];
891 *(unsigned long long *)d0p = u0;
892 *(unsigned long long *)d1p = u1;
893 f14 = d0;
894 f16 = d1;
895 if (test_def.precision == QUAD_TEST) {
896 *(unsigned long long *)d0xp = u0x;
897 *(unsigned long long *)d1xp = u1x;
898 f15 = d0x;
899 f17 = d1x;
901 for (RMC = 0; RMC < 4; RMC++) {
902 (*func)(-1, RMC);
903 res = f18;
904 printf("%s (RMC=%2d) %s %016llx", test_def.name, RMC, test_def.op, u0);
905 if (test_def.precision == LONG_TEST) {
906 printf(", %016llx => %016llx\n", u1, *((unsigned long long *)(&res)));
907 } else {
908 double resx = f19;
909 printf(" %016llx, %016llx %016llx ==> %016llx %016llx\n",u0x, u1, u1x,
910 *((unsigned long long *)(&res)), *((unsigned long long *)(&resx)));
914 k++;
915 printf( "\n" );
920 static dfp_one_arg_test_t
921 dfp_rrnd_tests[] = {
922 { &_test_drrnd, "drrnd", LONG_TEST, "[RR]"},
923 { &_test_drrndq, "drrndq", QUAD_TEST, "[RR]"},
924 { NULL, NULL, 0, NULL}
927 static void test_dfp_rrnd_ops(void)
929 test_func_t func;
930 unsigned long long u0, u0x;
931 double res, d0, *d0p, d0x, *d0xp, reference_sig, *reference_sig_p;
932 long long reference_sig_vals[] = {0ULL, 2ULL, 6ULL, 63ULL};
933 int num_reference_sig_vals = sizeof(reference_sig_vals)/sizeof(long long);
935 int k = 0;
936 u0 = u0x = 0;
937 d0p = &d0;
938 d0xp = &d0x;
939 reference_sig_p = &reference_sig;
941 while ((func = dfp_rrnd_tests[k].test_func)) {
942 int i, j;
943 dfp_one_arg_test_t test_def = dfp_rrnd_tests[k];
945 for (i = 0; i < NUM_DFP_VALS; i++) {
946 int RMC;
948 if (test_def.precision == LONG_TEST) {
949 u0 = dfp64_vals[i];
950 } else {
951 u0 = dfp128_vals[i * 2];
952 u0x = dfp128_vals[(i * 2) + 1];
954 *(unsigned long long *)d0p = u0;
955 f16 = d0;
956 if (test_def.precision == QUAD_TEST) {
957 *(unsigned long long *)d0xp = u0x;
958 f17 = d0x;
961 for (j = 0; j < num_reference_sig_vals; j++) {
962 *(long long *)reference_sig_p = reference_sig_vals[j];
963 f14 = reference_sig;
964 for (RMC = 0; RMC < 4; RMC++) {
965 (*func)(-1, RMC);
966 res = f18;
967 printf("%s (RMC=%d, ref sig=%d) %s%016llx", test_def.name, RMC,
968 (int)reference_sig_vals[j], test_def.op, u0);
969 if (test_def.precision == LONG_TEST) {
970 printf(" => %016llx\n",
971 *((unsigned long long *)(&res)));
972 } else {
973 double resx = f19;
974 printf(" %016llx ==> %016llx %016llx\n",
975 u0x, *((unsigned long long *)(&res)), *((unsigned long long *)(&resx)));
980 k++;
981 printf( "\n" );
986 static dfp_one_arg_test_t
987 dfp_xiex_tests[] = {
988 { &_test_diex, "diex", LONG_TEST, ">>"},
989 { &_test_diexq, "diexq", QUAD_TEST, ">>"},
990 { &_test_dxex, "dxex", LONG_TEST, "<<"},
991 { &_test_dxexq, "dxexq", QUAD_TEST, "<<"},
992 { NULL, NULL, 0, NULL}
995 static void test_dfp_xiex_ops(void)
997 test_func_t func;
998 unsigned long long u0, u0x;
999 double res, d0, *d0p, d0x, *d0xp, target_exp, *target_exp_p;
1000 /* The first two positions are placeholders and will be filled in later,
1001 * based on the precision of the DFP argument.
1003 long long target_exp_vals[] = {0ULL, 0ULL, 0ULL, -1ULL, -2ULL, -3ULL, -4ULL, -5ULL};
1004 int num_exp_vals = sizeof(target_exp_vals)/sizeof(long long);
1005 int k = 0;
1006 u0 = u0x = 0;
1007 d0p = &d0;
1008 d0xp = &d0x;
1009 target_exp_p = &target_exp;
1011 while ((func = dfp_xiex_tests[k].test_func)) {
1012 int i;
1013 Bool insert_insn = False;
1014 dfp_one_arg_test_t test_def = dfp_xiex_tests[k];
1016 if (!strncmp(test_def.name, "di", 2))
1017 insert_insn = True;
1019 if (test_def.precision == QUAD_TEST) {
1020 target_exp_vals[0] = 12288ULL; // > max biased exponent
1021 target_exp_vals[1] = 5235ULL;
1022 } else {
1023 target_exp_vals[0] = 768ULL; // > max biased exponent
1024 target_exp_vals[1] = 355ULL;
1027 for (i = 0; i < NUM_DFP_VALS; i++) {
1028 unsigned int j;
1030 if (test_def.precision == QUAD_TEST) {
1031 u0 = dfp128_vals[i * 2];
1032 u0x = dfp128_vals[(i * 2) + 1];
1033 } else {
1034 u0 = dfp64_vals[i];
1036 *(unsigned long long *)d0p = u0;
1037 f16 = d0;
1038 if (test_def.precision == QUAD_TEST) {
1039 *(unsigned long long *)d0xp = u0x;
1040 f17 = d0x;
1043 if (!insert_insn) {
1044 // This is just for extract insns (dexex[q])
1045 (*func)(0, 0);
1046 res = f18;
1047 printf("%s %s ", test_def.name, test_def.op);
1048 if (test_def.precision == LONG_TEST) {
1049 printf("%016llx => %016llx\n", u0,
1050 *((unsigned long long *)(&res)));
1051 } else {
1052 double resx = f19;
1053 printf("%016llx %016llx ==> %016llx %016llx\n", u0, u0x,
1054 *((unsigned long long *)(&res)), *((unsigned long long *)(&resx)));
1056 continue;
1058 // The following for-loop is just for insert insns (diex[q])
1059 for (j = 0; j < num_exp_vals; j++) {
1060 *(long long *)target_exp_p = target_exp_vals[j];
1061 f14 = target_exp;
1062 (*func)(0, 0);
1063 res = f18;
1064 printf("%s %s %5d, ", test_def.name, test_def.op, (int)target_exp_vals[j]);
1066 if (test_def.precision == LONG_TEST) {
1067 printf("%016llx => %016llx\n", u0,
1068 *((unsigned long long *)(&res)));
1069 } else {
1070 double resx = f19;
1071 printf("%016llx %016llx ==> %016llx %016llx\n", u0, u0x,
1072 *((unsigned long long *)(&res)), *((unsigned long long *)(&resx)));
1076 k++;
1077 printf( "\n" );
1081 static dfp_one_arg_test_t
1082 dfp_rint_tests[] = {
1083 { &_test_drintn, "drintn", LONG_TEST, "~"},
1084 { &_test_drintnq, "drintnq", QUAD_TEST, "~"},
1085 { &_test_drintx, "drintx", LONG_TEST, "~"},
1086 { &_test_drintxq, "drintxq", QUAD_TEST, "~"},
1087 { NULL, NULL, 0, NULL}
1090 static void test_dfp_rint_ops(void)
1092 test_func_t func;
1093 unsigned long long u0, u0x;
1094 double res, d0, *d0p, d0x, *d0xp;
1095 int k = 0;
1096 u0 = u0x = 0;
1097 d0p = &d0;
1098 d0xp = &d0x;
1100 while ((func = dfp_rint_tests[k].test_func)) {
1101 int i;
1102 dfp_one_arg_test_t test_def = dfp_rint_tests[k];
1104 for (i = 0; i < NUM_DFP_VALS; i++) {
1105 int R, RMC;
1107 if (test_def.precision == LONG_TEST) {
1108 u0 = dfp64_vals[i];
1109 } else {
1110 u0 = dfp128_vals[i * 2];
1111 u0x = dfp128_vals[(i * 2) + 1];
1113 *(unsigned long long *)d0p = u0;
1114 f16 = d0;
1115 if (test_def.precision == QUAD_TEST) {
1116 *(unsigned long long *)d0xp = u0x;
1117 f17 = d0x;
1120 for (R = 0; R < 2; R++) {
1121 for (RMC = 0; RMC < 4; RMC++) {
1122 (*func)(R, RMC);
1123 res = f18;
1124 printf("%s (RM=%d) %s%016llx", test_def.name, (RMC + (R << 2)), test_def.op, u0);
1125 if (test_def.precision == LONG_TEST) {
1126 printf(" => %016llx\n",
1127 *((unsigned long long *)(&res)));
1128 } else {
1129 double resx = f19;
1130 printf(" %016llx ==> %016llx %016llx\n",
1131 u0x, *((unsigned long long *)(&res)), *((unsigned long long *)(&resx)));
1136 k++;
1137 printf( "\n" );
1141 static dfp_test_t
1142 dfp_cmp_tests[] = {
1143 { &_test_dcmpo, "dcmpo", dfp_2args_x1, 25, LONG_TEST, "<>"},
1144 { &_test_dcmpoq, "dcmpoq", dfp_2args_x1, 25, QUAD_TEST, "<>"},
1145 { &_test_dcmpu, "dcmpu", dfp_2args_x1, 25, LONG_TEST, "<>"},
1146 { &_test_dcmpuq, "dcmpuq", dfp_2args_x1, 25, QUAD_TEST, "<>"},
1147 { NULL, NULL, NULL, 0, 0, NULL}
1150 static void test_dfp_cmp_ops(void)
1152 test_func_t func;
1153 unsigned long long u0, u0x, u1, u1x;
1154 double d0, d1, *d0p, *d1p;
1155 double d0x, d1x, *d0xp, *d1xp;
1156 /* BF is a 3-bit instruction field that indicates the CR field in which the
1157 * result of the compare should be placed. We won't iterate through all
1158 * 8 possible BF values since storing compare results to a given field is
1159 * a well-tested mechanism in VEX. But we will test two BF values, just as
1160 * a sniff-test.
1162 int k = 0, BF;
1163 u0x = u1x = 0;
1164 d0p = &d0;
1165 d0xp = &d0x;
1166 d1p = &d1;
1167 d1xp = &d1x;
1169 while ((func = dfp_cmp_tests[k].test_func)) {
1170 int i, repeat = 1;
1171 dfp_test_t test_def = dfp_cmp_tests[k];
1172 BF = 0;
1174 again:
1175 for (i = 0; i < test_def.num_tests; i++) {
1176 unsigned int condreg;
1177 unsigned int flags;
1179 if (test_def.precision == LONG_TEST) {
1180 u0 = dfp64_vals[test_def.targs[i].fra_idx];
1181 u1 = dfp64_vals[test_def.targs[i].frb_idx];
1182 } else {
1183 u0 = dfp128_vals[test_def.targs[i].fra_idx * 2];
1184 u0x = dfp128_vals[(test_def.targs[i].fra_idx * 2) + 1];
1185 u1 = dfp128_vals[test_def.targs[i].frb_idx * 2];
1186 u1x = dfp128_vals[(test_def.targs[i].frb_idx * 2) + 1];
1188 *(unsigned long long *)d0p = u0;
1189 *(unsigned long long *)d1p = u1;
1190 f14 = d0;
1191 f16 = d1;
1192 if (test_def.precision == QUAD_TEST) {
1193 *(unsigned long long *)d0xp = u0x;
1194 *(unsigned long long *)d1xp = u1x;
1195 f15 = d0x;
1196 f17 = d1x;
1199 SET_FPSCR_ZERO;
1200 SET_CR_XER_ZERO;
1201 (*func)(BF, 0);
1202 GET_CR(flags);
1204 condreg = ((flags >> (4 * (7-BF)))) & 0xf;
1205 printf("%s %016llx", test_def.name, u0);
1206 if (test_def.precision == LONG_TEST) {
1207 printf(" %s %016llx => %x (BF=%d)\n",
1208 test_def.op, u1, condreg, BF);
1209 } else {
1210 printf(" %016llx %s %016llx %016llx ==> %x (BF=%d)\n",
1211 u0x, test_def.op, u1, u1x,
1212 condreg, BF);
1215 if (repeat) {
1216 repeat = 0;
1217 BF = 5;
1218 goto again;
1220 k++;
1221 printf( "\n" );
1226 static test_table_t
1227 all_tests[] =
1229 { &test_dfp_cmp_ops,
1230 "Test DFP compare instructions"},
1231 { &test_dfp_rint_ops,
1232 "Test DFP round instructions"},
1233 { &test_dfp_xiex_ops,
1234 "Test DFP insert/extract instructions"},
1235 { &test_dfp_rrnd_ops,
1236 "Test DFP reround instructions"},
1237 { &test_dfp_qua_ops,
1238 "Test DFP quantize instructions"},
1239 { &test_dfp_quai_ops,
1240 "Test DFP quantize immediate instructions"},
1241 { NULL, NULL }
1243 #endif // HAS_DFP
1245 int main() {
1246 #if defined(HAS_DFP)
1248 test_table_t aTest;
1249 test_driver_func_t func;
1250 int i = 0;
1252 while ((func = all_tests[i].test_category)) {
1253 aTest = all_tests[i];
1254 printf( "%s\n", aTest.name );
1255 (*func)();
1256 i++;
1259 #endif // HAS_DFP
1260 return 0;