blob: 1906ca963cfea640c996e0b37cce4e1c0ab9c31a [file] [log] [blame]
sewardjbe134452006-02-06 04:19:30 +00001
2#include <assert.h>
3#include <stdio.h>
4#include <malloc.h>
5
6typedef unsigned int UInt;
7typedef unsigned long long int ULong;
8
9typedef
10 struct {
11 double fres;
12 UInt cr;
13 UInt fpscr;
14 }
15 Result;
16
17
18static void set_NEAREST ( void ) {
19 __asm__ __volatile__("mtfsb0 30 ; mtfsb0 31");
20}
21static void set_ZERO ( void ) {
22 __asm__ __volatile__("mtfsb0 30 ; mtfsb1 31");
23}
24static void set_PosINF ( void ) {
25 __asm__ __volatile__("mtfsb1 30 ; mtfsb0 31");
26}
27static void set_NegINF ( void ) {
28 __asm__ __volatile__("mtfsb1 30 ; mtfsb1 31");
29}
30
31
32static ULong double_as_ULong ( double d )
33{
34 union { double dd; ULong ll; } u;
35 assert(sizeof(u) == 8);
36 u.dd = d;
37 return u.ll;
38}
39
40static ULong round_with_mask ( ULong x, ULong mask )
41{
42 if (mask == 1) {
43 switch (x & 1) {
44 case 0: return x;
45 case 1: return x+1;
46 }
47 assert(0);
48 }
49
50 if (mask == 3) {
51 switch (x & 3) {
52 case 0: return x;
53 case 1: return x-1;
54 case 2: return x+2;
55 case 3: return x+1;
56 }
57 assert(0);
58 }
59
60 if (mask == 7) {
61 switch (x & 7) {
62 case 0: return x;
63 case 1: return x-1;
64 case 2: return x-2;
65 case 3: return x-3;
66 case 4: return x+4;
67 case 5: return x+3;
68 case 6: return x+2;
69 case 7: return x+1;
70 }
71 assert(0);
72 }
73
74 if (mask == 15) {
75 switch (x & 15) {
76 case 0: return x;
77 case 1: return x-1;
78 case 2: return x-2;
79 case 3: return x-3;
80 case 4: return x-4;
81 case 5: return x-5;
82 case 6: return x-6;
83 case 7: return x-7;
84 case 8: return x+8;
85 case 9: return x+7;
86 case 10: return x+6;
87 case 11: return x+5;
88 case 12: return x+4;
89 case 13: return x+3;
90 case 14: return x+2;
91 case 15: return x+1;
92 }
93 assert(0);
94 }
95
96 assert(0);
97}
98
99static void showResult ( Result r, ULong hideMask )
100{
101 /* hidemask should have 1 for every result bit we **don't**
102 want to show. viz should be all zeroes normally. */
103#if 0
104 printf("(%016llx cr1 0x%01x fprf 0x%02x)",
105 double_as_ULong(r.fres) & ~hidemask,
106 (r.cr >> 24) & 0xF, (r.fpscr >> 12) & 0x1F);
107#else
108 printf("(%016llx cr1 ... fprf ...)",
109 (hideMask == 0x1 || hideMask == 0x3 || hideMask == 0x7)
110 ? round_with_mask( double_as_ULong(r.fres), hideMask )
111 : double_as_ULong(r.fres) & ~hideMask
112 );
113#endif
114}
115
116
117/* Give an insn string such as "fmadd %%f4, %%f1,%%f2,%%f3". Args are
118 in f1, f2, f3, and result should go in f4. */
119#define INSN(name,insn) \
120 \
121 static Result insn_##name ( double arg1, double arg2, double arg3 ) \
122 { \
123 struct { \
124 /* 0 */ double a1; \
125 /* 8 */ double a2; \
126 /* 16 */ double a3; \
127 /* 24 */ double res; \
128 /* 32 */ UInt fpscr_after; \
129 /* 36 */ UInt cr_after; \
130 } foo; \
131 assert(sizeof(foo) == 40); \
132 foo.a1 = foo.a2 = foo.a3 = foo.res = 0; \
133 foo.fpscr_after = foo.cr_after = 0; \
134 foo.a1 = arg1; \
135 foo.a2 = arg2; \
136 foo.a3 = arg3; \
137 __asm__ __volatile__( \
138 "lfd %%f1, 0(%0)\n\t" /* a1 */ \
139 "lfd %%f2, 8(%0)\n\t" /* a2 */ \
140 "lfd %%f3, 16(%0)\n\t" /* a3 */ \
141 insn "\n\t" \
142 "stfd %%f4, 24(%0)\n\t" /* res */ \
143 "mffs %%f4\n\t" \
144 "addi %0,%0,32\n\t" \
145 "stfiwx %%f4, %%r0,%0\n\t" /* fpscr_after. r0 reads as zero */ \
146 "addi %0,%0,-32\n\t" \
147 "mfcr %%r31\n\t" \
148 "stw %%r31, 36(%0)" /* cr_after */ \
149 : /*out*/ \
150 : /*in*/ "b" (&foo.a1) \
151 : /*trash*/ "memory","cc", "fr1","fr2","fr3","fr4", "r31" \
152 ); \
153 { Result result; \
154 result.fres = foo.res; \
155 result.cr = foo.cr_after; \
156 result.fpscr = foo.fpscr_after; \
157 return result; \
158 } \
159 }
160
161INSN(fabs, "fabs %%f4, %%f1");
162INSN(fabs_, "fabs. %%f4, %%f1");
163
164INSN(fnabs, "fnabs %%f4, %%f1");
165INSN(fnabs_, "fnabs. %%f4, %%f1");
166
167INSN(fadd, "fadd %%f4, %%f1,%%f2");
168INSN(fadd_, "fadd. %%f4, %%f1,%%f2");
169
170INSN(fadds, "fadds %%f4, %%f1,%%f2");
171INSN(fadds_, "fadds. %%f4, %%f1,%%f2");
172
173INSN(fcfid, "fcfid %%f4, %%f1");
174INSN(fcfid_, "fcfid. %%f4, %%f1");
175
176INSN(fctid, "fctid %%f4, %%f1");
177INSN(fctid_, "fctid. %%f4, %%f1");
178
179INSN(fctidz, "fctidz %%f4, %%f1");
180INSN(fctidz_, "fctidz. %%f4, %%f1");
181
182INSN(fctiw, "fctiw %%f4, %%f1");
183INSN(fctiw_, "fctiw. %%f4, %%f1");
184
185INSN(fctiwz, "fctiwz %%f4, %%f1");
186INSN(fctiwz_, "fctiwz. %%f4, %%f1");
187
188INSN(fdiv, "fdiv %%f4, %%f1,%%f2");
189INSN(fdiv_, "fdiv. %%f4, %%f1,%%f2");
190
191INSN(fdivs, "fdivs %%f4, %%f1,%%f2");
192INSN(fdivs_, "fdivs. %%f4, %%f1,%%f2");
193
194INSN(fmadd, "fmadd %%f4, %%f1,%%f2,%%f3");
195INSN(fmadd_, "fmadd. %%f4, %%f1,%%f2,%%f3");
196
197INSN(fmadds, "fmadds %%f4, %%f1,%%f2,%%f3");
198INSN(fmadds_, "fmadds. %%f4, %%f1,%%f2,%%f3");
199
200INSN(fmr, "fmr %%f4, %%f1");
201INSN(fmr_, "fmr. %%f4, %%f1");
202
203INSN(fmsub, "fmsub %%f4, %%f1,%%f2,%%f3");
204INSN(fmsub_, "fmsub. %%f4, %%f1,%%f2,%%f3");
205
206INSN(fmsubs, "fmsubs %%f4, %%f1,%%f2,%%f3");
207INSN(fmsubs_, "fmsubs. %%f4, %%f1,%%f2,%%f3");
208
209INSN(fmul, "fmul %%f4, %%f1,%%f2");
210INSN(fmul_, "fmul. %%f4, %%f1,%%f2");
211
212INSN(fmuls, "fmuls %%f4, %%f1,%%f2");
213INSN(fmuls_, "fmuls. %%f4, %%f1,%%f2");
214
215INSN(fneg, "fneg %%f4, %%f1");
216INSN(fneg_, "fneg. %%f4, %%f1");
217
218INSN(fnmadd, "fnmadd %%f4, %%f1,%%f2,%%f3");
219INSN(fnmadd_, "fnmadd. %%f4, %%f1,%%f2,%%f3");
220
221INSN(fnmadds, "fnmadds %%f4, %%f1,%%f2,%%f3");
222INSN(fnmadds_, "fnmadds. %%f4, %%f1,%%f2,%%f3");
223
224INSN(fnmsub, "fnmsub %%f4, %%f1,%%f2,%%f3");
225INSN(fnmsub_, "fnmsub. %%f4, %%f1,%%f2,%%f3");
226
227INSN(fnmsubs, "fnmsubs %%f4, %%f1,%%f2,%%f3");
228INSN(fnmsubs_, "fnmsubs. %%f4, %%f1,%%f2,%%f3");
229
230INSN(fre, "fre %%f4, %%f1");
231INSN(fre_, "fre. %%f4, %%f1");
232
233INSN(fres, "fres %%f4, %%f1");
234INSN(fres_, "fres. %%f4, %%f1");
235
236INSN(frsqrte, "frsqrte %%f4, %%f1");
237INSN(frsqrte_, "frsqrte. %%f4, %%f1");
238
239//INSN(frsqrtes, "frsqrtes %%f4, %%f1");
240//INSN(frsqrtes_, "frsqrtes. %%f4, %%f1");
241
242INSN(frsp, "frsp %%f4, %%f1");
243INSN(frsp_, "frsp. %%f4, %%f1");
244
245INSN(fsel, "fsel %%f4, %%f1,%%f2,%%f3");
246INSN(fsel_, "fsel. %%f4, %%f1,%%f2,%%f3");
247
248INSN(fsqrt, "fsqrt %%f4, %%f1");
249INSN(fsqrt_, "fsqrt. %%f4, %%f1");
250
251INSN(fsqrts, "fsqrts %%f4, %%f1");
252INSN(fsqrts_, "fsqrts. %%f4, %%f1");
253
254INSN(fsub, "fsub %%f4, %%f1,%%f2");
255INSN(fsub_, "fsub. %%f4, %%f1,%%f2");
256
257INSN(fsubs, "fsubs %%f4, %%f1,%%f2");
258INSN(fsubs_, "fsubs. %%f4, %%f1,%%f2");
259
260
261
262void do_1_unary ( char* name,
263 Result(*f)(double,double,double),
264 double a1,
265 ULong hideMask )
266{
267 Result r;
268 printf("%8s: %016llx (%e)\n", name, double_as_ULong(a1), a1);
269 set_NEAREST();
270 r = f(a1, 0.0,0.0);
271 printf(" near "); showResult(r,hideMask); printf("\n");
272 set_ZERO();
273 r = f(a1, 0.0,0.0);
274 printf(" zero "); showResult(r,hideMask); printf("\n");
275 set_PosINF();
276 r = f(a1, 0.0,0.0);
277 printf(" +inf "); showResult(r,hideMask); printf("\n");
278 set_NegINF();
279 r = f(a1, 0.0,0.0);
280 printf(" -inf "); showResult(r,hideMask); printf("\n");
281}
282
283void do_1_binary ( char* name,
284 Result(*f)(double,double,double),
285 double a1, double a2,
286 ULong hideMask )
287{
288 Result r;
289 printf("%8s: %016llx %016llx\n", name, double_as_ULong(a1),
290 double_as_ULong(a2));
291 set_NEAREST();
292 r = f(a1,a2, 0.0);
293 printf(" near "); showResult(r,hideMask); printf("\n");
294 set_ZERO();
295 r = f(a1,a2, 0.0);
296 printf(" zero "); showResult(r,hideMask); printf("\n");
297 set_PosINF();
298 r = f(a1,a2, 0.0);
299 printf(" +inf "); showResult(r,hideMask); printf("\n");
300 set_NegINF();
301 r = f(a1,a2, 0.0);
302 printf(" -inf "); showResult(r,hideMask); printf("\n");
303}
304
305void do_1_ternary ( char* name,
306 Result(*f)(double,double,double),
307 double a1, double a2, double a3,
308 ULong hideMask )
309{
310 Result r;
311 printf("%8s: %016llx %016llx %016llx\n",
312 name, double_as_ULong(a1),
313 double_as_ULong(a2), double_as_ULong(a3));
314 set_NEAREST();
315 r = f(a1,a2,a3);
316 printf(" near "); showResult(r,hideMask); printf("\n");
317 set_ZERO();
318 r = f(a1,a2,a3);
319 printf(" zero "); showResult(r,hideMask); printf("\n");
320 set_PosINF();
321 r = f(a1,a2,a3);
322 printf(" +inf "); showResult(r,hideMask); printf("\n");
323 set_NegINF();
324 r = f(a1,a2,a3);
325 printf(" -inf "); showResult(r,hideMask); printf("\n");
326}
327
328void do_N_unary ( char* name,
329 Result(*f)(double,double,double),
330 double* args,
331 int nargs,
332 ULong hideMask )
333{
334 int i;
335 for (i = 0; i < nargs; i++) {
336 do_1_unary( name, f, args[i], hideMask );
337 }
338}
339
340void do_N_binary ( char* name,
341 Result(*f)(double,double,double),
342 double* args,
343 int nargs,
344 ULong hideMask )
345{
346 int i, j;
347 for (i = 0; i < nargs; i++) {
348 for (j = 0; j < nargs; j++) {
349 do_1_binary( name, f, args[i], args[j], hideMask );
350 }
351 }
352}
353
354void do_N_ternary ( char* name,
355 Result(*f)(double,double,double),
356 double* args,
357 int nargs,
358 ULong hideMask )
359{
360 int i, j, k;
361 for (i = 0; i < nargs; i++) {
362 for (j = 0; j < nargs; j++) {
363 for (k = 0; k < nargs; k++) {
364 do_1_ternary( name, f, args[i], args[j], args[k], hideMask );
365 }
366 }
367 }
368}
369
370int main ( void )
371{
372 const ULong SHOW_ALL = 0;
373
374 int nargs = 21;
375 int nMacArgs = 11;
376
377 double* args = malloc(nargs * sizeof(double));
378 double* macArgs = malloc(nMacArgs * sizeof(double));
379
380 args[0] = 0.0;
381 args[1] = 1.0 / 0.0; // inf
382 args[2] = -args[1]; // -inf
383 args[3] = args[2]/args[2]; // nan
384 args[4] = -args[3]; // -nan
385 args[5] = -5e100;
386 args[6] = -5e20;
387 args[7] = -501.0;
388 args[8] = -6.0;
389 args[9] = -1.0;
390 args[10] = -2e-20;
391 args[11] = -2e-200;
392 args[12] = 2e-200;
393 args[13] = 2e-20;
394 args[14] = 1.0;
395 args[15] = 6.0;
396 args[16] = 501.0;
397 args[17] = 5e20;
398 args[18] = 5e100;
399 args[19] = 1.23e+5;
400 args[20] = 1.23e+14;
401
402#if 0
403 macArgs[0] = 0.0;
404 macArgs[1] = -5e100;
405 macArgs[2] = -5e20;
406 macArgs[3] = -501.0;
407 macArgs[4] = -6.0;
408 macArgs[5] = -1.0;
409 macArgs[6] = -2e-20;
410 macArgs[7] = -2e-200;
411 macArgs[8] = 2e-200;
412 macArgs[9] = 2e-20;
413 macArgs[10] = 1.0;
414 macArgs[11] = 6.0;
415 macArgs[12] = 501.0;
416 macArgs[13] = 5e20;
417 macArgs[14] = 5e100;
418 macArgs[15] = 1.23e+5;
419 macArgs[16] = 1.23e+14;
420
421 //macArgs[17] = args[3]; // nan
422 //macArgs[18] = -args[3]; // -nan
423#endif
424
425 macArgs[0] = 0.0;
426 macArgs[1] = 1.0;
427 macArgs[2] = 1.0 + (1.0/7.0);
428 macArgs[3] = 6.01;
429 macArgs[4] = 501.0;
430 macArgs[5] = 31415927.0;
431 macArgs[6] = - 1.0;
432 macArgs[7] = - (1.0 + (1.0/7.0));
433 macArgs[8] = - 6.01;
434 macArgs[9] = - 501.0;
435 macArgs[10] = - 31415927.0;
436
437
438 do_N_unary("fmr", insn_fmr, args, nargs, SHOW_ALL);
439 do_N_unary("fmr_", insn_fmr_, args, nargs, SHOW_ALL);
440
441 do_N_unary("fneg", insn_fneg, args, nargs, SHOW_ALL);
442 do_N_unary("fneg_", insn_fneg_, args, nargs, SHOW_ALL);
443
444 do_N_unary("fabs", insn_fabs, args, nargs, SHOW_ALL);
445 do_N_unary("fabs_", insn_fabs_, args, nargs, SHOW_ALL);
446
447 do_N_unary("fnabs", insn_fnabs, args, nargs, SHOW_ALL);
448 do_N_unary("fnabs_", insn_fnabs_, args, nargs, SHOW_ALL);
449
450
451 do_N_binary("fadd", insn_fadd, args, nargs, SHOW_ALL);
452 do_N_binary("fadd_", insn_fadd_, args, nargs, SHOW_ALL);
453
454 do_N_binary("fadds", insn_fadds, args, nargs, SHOW_ALL);
455 do_N_binary("fadds_", insn_fadds_, args, nargs, SHOW_ALL);
456
457 do_N_binary("fdiv", insn_fdiv, args, nargs, SHOW_ALL);
458 do_N_binary("fdiv_", insn_fdiv_, args, nargs, SHOW_ALL);
459
460 do_N_binary("fdivs", insn_fdivs, args, nargs, SHOW_ALL);
461 do_N_binary("fdivs_", insn_fdivs_, args, nargs, SHOW_ALL);
462
463 do_N_binary("fmul", insn_fmul, args, nargs, SHOW_ALL);
464 do_N_binary("fmul_", insn_fmul_, args, nargs, SHOW_ALL);
465
466 do_N_binary("fmuls", insn_fmuls, args, nargs, SHOW_ALL);
467 do_N_binary("fmuls_", insn_fmuls_, args, nargs, SHOW_ALL);
468
469 do_N_binary("fsub", insn_fsub, args, nargs, SHOW_ALL);
470 do_N_binary("fsub_", insn_fsub_, args, nargs, SHOW_ALL);
471
472 do_N_binary("fsubs", insn_fsubs, args, nargs, SHOW_ALL);
473 do_N_binary("fsubs_", insn_fsubs_, args, nargs, SHOW_ALL);
474
475 //do_N_unary(fcfid, SHOW_ALL);
476 //do_N_unary(fcfid_, SHOW_ALL);
477
478 //do_N_unary(fctid, SHOW_ALL);
479 //do_N_unary(fctid_, SHOW_ALL);
480
481 //do_N_unary(fctidz, SHOW_ALL);
482 //do_N_unary(fctidz_, SHOW_ALL);
483
484 do_N_unary("fctiw", insn_fctiw, args, nargs, 0xFFFFFFFF00000000ULL);
485 do_N_unary("fctiw_", insn_fctiw_, args, nargs, 0xFFFFFFFF00000000ULL);
486
487 do_N_unary("fctiwz", insn_fctiwz, args, nargs, 0xFFFFFFFF00000000ULL);
488 do_N_unary("fctiwz_", insn_fctiwz_, args, nargs, 0xFFFFFFFF00000000ULL);
489
sewardjbe134452006-02-06 04:19:30 +0000490 do_N_ternary("fmadd", insn_fmadd, macArgs, nMacArgs, SHOW_ALL);
491 do_N_ternary("fmadd_", insn_fmadd_, macArgs, nMacArgs, SHOW_ALL);
492
493 do_N_ternary("fmadds", insn_fmadds, macArgs, nMacArgs, SHOW_ALL);
494 do_N_ternary("fmadds_", insn_fmadds_, macArgs, nMacArgs, SHOW_ALL);
495
496 do_N_ternary("fmsub", insn_fmsub, macArgs, nMacArgs, SHOW_ALL);
497 do_N_ternary("fmsub_", insn_fmsub_, macArgs, nMacArgs, SHOW_ALL);
498
499 do_N_ternary("fmsubs", insn_fmsubs, macArgs, nMacArgs, SHOW_ALL);
500 do_N_ternary("fmsubs_", insn_fmsubs_, macArgs, nMacArgs, SHOW_ALL);
501
502 do_N_ternary("fnmadd", insn_fnmadd, macArgs, nMacArgs, SHOW_ALL);
503 do_N_ternary("fnmadd_", insn_fnmadd_, macArgs, nMacArgs, SHOW_ALL);
504
505 do_N_ternary("fnmadds", insn_fnmadds, macArgs, nMacArgs, SHOW_ALL);
506 do_N_ternary("fnmadds_", insn_fnmadds_, macArgs, nMacArgs, SHOW_ALL);
507
508 do_N_ternary("fnmsub", insn_fnmsub, macArgs, nMacArgs, SHOW_ALL);
509 do_N_ternary("fnmsub_", insn_fnmsub_, macArgs, nMacArgs, SHOW_ALL);
510
511 do_N_ternary("fnmsubs", insn_fnmsubs, macArgs, nMacArgs, SHOW_ALL);
512 do_N_ternary("fnmsubs_", insn_fnmsubs_, macArgs, nMacArgs, SHOW_ALL);
sewardjbe134452006-02-06 04:19:30 +0000513
514 //do_N_unary(fre, SHOW_ALL);
515 //do_N_unary(fre_, SHOW_ALL);
516
517 do_N_unary("fres", insn_fres, args, nargs, 0x000001FFFFFFFFFFULL);
518 do_N_unary("fres_", insn_fres_, args, nargs, 0x000001FFFFFFFFFFULL);
519
520 do_N_unary("frsqrte", insn_frsqrte, args, nargs, SHOW_ALL);
521 do_N_unary("frsqrte_", insn_frsqrte_, args, nargs, SHOW_ALL);
522
523 // do_N_unary("frsqrtes", insn_frsqrtes, args, nargs, SHOW_ALL);
524 // do_N_unary("frsqrtes_", insn_frsqrtes_, args, nargs, SHOW_ALL);
525
526 do_N_unary("frsp", insn_frsp, args, nargs, SHOW_ALL);
527 do_N_unary("frsp_", insn_frsp_, args, nargs, SHOW_ALL);
528
529 do_N_ternary("fsel", insn_fsel, args, nargs, SHOW_ALL);
530 do_N_ternary("fsel_", insn_fsel_, args, nargs, SHOW_ALL);
531
532 //do_N_unary(fsqrt, SHOW_ALL);
533 //do_N_unary(fsqrt_, SHOW_ALL);
534
535 //do_N_unary(fsqrts, SHOW_ALL);
536 //do_N_unary(fsqrts_, SHOW_ALL);
537
538 return 0;
539}