Automatic date update in version.in
[binutils-gdb.git] / sim / common / cgen-accfp.c
blobe19b09ba7f0a50fbc7cd1403f1374c6fdf851db1
1 /* Accurate fp support for CGEN-based simulators.
2 Copyright (C) 1999 Cygnus Solutions.
4 This implemention assumes:
5 typedef USI SF;
6 typedef UDI DF;
8 TODO:
9 - lazy encoding/decoding
10 - checking return code (say by callback)
11 - proper rounding
14 /* This must come before any other includes. */
15 #include "defs.h"
17 #include "sim-main.h"
18 #include "sim-fpu.h"
20 /* SF mode support */
22 static SF
23 addsf (CGEN_FPU* fpu, SF x, SF y)
25 sim_fpu op1;
26 sim_fpu op2;
27 sim_fpu ans;
28 uint32_t res;
29 sim_fpu_status status;
31 sim_fpu_32to (&op1, x);
32 sim_fpu_32to (&op2, y);
33 status = sim_fpu_add (&ans, &op1, &op2);
34 if (status != 0)
35 (*fpu->ops->error) (fpu, status);
36 sim_fpu_to32 (&res, &ans);
38 return res;
41 static SF
42 subsf (CGEN_FPU* fpu, SF x, SF y)
44 sim_fpu op1;
45 sim_fpu op2;
46 sim_fpu ans;
47 uint32_t res;
48 sim_fpu_status status;
50 sim_fpu_32to (&op1, x);
51 sim_fpu_32to (&op2, y);
52 status = sim_fpu_sub (&ans, &op1, &op2);
53 if (status != 0)
54 (*fpu->ops->error) (fpu, status);
55 sim_fpu_to32 (&res, &ans);
57 return res;
60 static SF
61 mulsf (CGEN_FPU* fpu, SF x, SF y)
63 sim_fpu op1;
64 sim_fpu op2;
65 sim_fpu ans;
66 uint32_t res;
67 sim_fpu_status status;
69 sim_fpu_32to (&op1, x);
70 sim_fpu_32to (&op2, y);
71 status = sim_fpu_mul (&ans, &op1, &op2);
72 if (status != 0)
73 (*fpu->ops->error) (fpu, status);
74 sim_fpu_to32 (&res, &ans);
76 return res;
79 static SF
80 divsf (CGEN_FPU* fpu, SF x, SF y)
82 sim_fpu op1;
83 sim_fpu op2;
84 sim_fpu ans;
85 uint32_t res;
86 sim_fpu_status status;
88 sim_fpu_32to (&op1, x);
89 sim_fpu_32to (&op2, y);
90 status = sim_fpu_div (&ans, &op1, &op2);
91 if (status != 0)
92 (*fpu->ops->error) (fpu, status);
93 sim_fpu_to32 (&res, &ans);
95 return res;
98 static SF
99 remsf (CGEN_FPU* fpu, SF x, SF y)
101 sim_fpu op1;
102 sim_fpu op2;
103 sim_fpu ans;
104 uint32_t res;
105 sim_fpu_status status;
107 sim_fpu_32to (&op1, x);
108 sim_fpu_32to (&op2, y);
109 status = sim_fpu_rem (&ans, &op1, &op2);
110 if (status != 0)
111 (*fpu->ops->error) (fpu, status);
112 sim_fpu_to32 (&res, &ans);
114 return res;
117 static SF
118 negsf (CGEN_FPU* fpu, SF x)
120 sim_fpu op1;
121 sim_fpu ans;
122 uint32_t res;
123 sim_fpu_status status;
125 sim_fpu_32to (&op1, x);
126 status = sim_fpu_neg (&ans, &op1);
127 if (status != 0)
128 (*fpu->ops->error) (fpu, status);
129 sim_fpu_to32 (&res, &ans);
131 return res;
134 static SF
135 abssf (CGEN_FPU* fpu, SF x)
137 sim_fpu op1;
138 sim_fpu ans;
139 uint32_t res;
140 sim_fpu_status status;
142 sim_fpu_32to (&op1, x);
143 status = sim_fpu_abs (&ans, &op1);
144 if (status != 0)
145 (*fpu->ops->error) (fpu, status);
146 sim_fpu_to32 (&res, &ans);
148 return res;
151 static SF
152 sqrtsf (CGEN_FPU* fpu, SF x)
154 sim_fpu op1;
155 sim_fpu ans;
156 uint32_t res;
157 sim_fpu_status status;
159 sim_fpu_32to (&op1, x);
160 status = sim_fpu_sqrt (&ans, &op1);
161 if (status != 0)
162 (*fpu->ops->error) (fpu, status);
163 sim_fpu_to32 (&res, &ans);
165 return res;
168 static SF
169 invsf (CGEN_FPU* fpu, SF x)
171 sim_fpu op1;
172 sim_fpu ans;
173 uint32_t res;
174 sim_fpu_status status;
176 sim_fpu_32to (&op1, x);
177 status = sim_fpu_inv (&ans, &op1);
178 if (status != 0)
179 (*fpu->ops->error) (fpu, status);
180 sim_fpu_to32 (&res, &ans);
182 return res;
185 static SF
186 minsf (CGEN_FPU* fpu, SF x, SF y)
188 sim_fpu op1;
189 sim_fpu op2;
190 sim_fpu ans;
191 uint32_t res;
192 sim_fpu_status status;
194 sim_fpu_32to (&op1, x);
195 sim_fpu_32to (&op2, y);
196 status = sim_fpu_min (&ans, &op1, &op2);
197 if (status != 0)
198 (*fpu->ops->error) (fpu, status);
199 sim_fpu_to32 (&res, &ans);
201 return res;
204 static SF
205 maxsf (CGEN_FPU* fpu, SF x, SF y)
207 sim_fpu op1;
208 sim_fpu op2;
209 sim_fpu ans;
210 uint32_t res;
211 sim_fpu_status status;
213 sim_fpu_32to (&op1, x);
214 sim_fpu_32to (&op2, y);
215 status = sim_fpu_max (&ans, &op1, &op2);
216 if (status != 0)
217 (*fpu->ops->error) (fpu, status);
218 sim_fpu_to32 (&res, &ans);
220 return res;
223 static CGEN_FP_CMP
224 cmpsf (CGEN_FPU* fpu, SF x, SF y)
226 sim_fpu op1;
227 sim_fpu op2;
229 sim_fpu_32to (&op1, x);
230 sim_fpu_32to (&op2, y);
232 if (sim_fpu_is_nan (&op1)
233 || sim_fpu_is_nan (&op2))
234 return FP_CMP_NAN;
236 if (x < y)
237 return FP_CMP_LT;
238 if (x > y)
239 return FP_CMP_GT;
240 return FP_CMP_EQ;
243 static int
244 eqsf (CGEN_FPU* fpu, SF x, SF y)
246 sim_fpu op1;
247 sim_fpu op2;
249 sim_fpu_32to (&op1, x);
250 sim_fpu_32to (&op2, y);
251 return sim_fpu_is_eq (&op1, &op2);
254 static int
255 nesf (CGEN_FPU* fpu, SF x, SF y)
257 sim_fpu op1;
258 sim_fpu op2;
260 sim_fpu_32to (&op1, x);
261 sim_fpu_32to (&op2, y);
262 return sim_fpu_is_ne (&op1, &op2);
265 static int
266 ltsf (CGEN_FPU* fpu, SF x, SF y)
268 sim_fpu op1;
269 sim_fpu op2;
271 sim_fpu_32to (&op1, x);
272 sim_fpu_32to (&op2, y);
273 return sim_fpu_is_lt (&op1, &op2);
276 static int
277 lesf (CGEN_FPU* fpu, SF x, SF y)
279 sim_fpu op1;
280 sim_fpu op2;
282 sim_fpu_32to (&op1, x);
283 sim_fpu_32to (&op2, y);
284 return sim_fpu_is_le (&op1, &op2);
287 static int
288 gtsf (CGEN_FPU* fpu, SF x, SF y)
290 sim_fpu op1;
291 sim_fpu op2;
293 sim_fpu_32to (&op1, x);
294 sim_fpu_32to (&op2, y);
295 return sim_fpu_is_gt (&op1, &op2);
298 static int
299 gesf (CGEN_FPU* fpu, SF x, SF y)
301 sim_fpu op1;
302 sim_fpu op2;
304 sim_fpu_32to (&op1, x);
305 sim_fpu_32to (&op2, y);
306 return sim_fpu_is_ge (&op1, &op2);
309 static int
310 unorderedsf (CGEN_FPU* fpu, SF x, SF y)
312 sim_fpu op1;
313 sim_fpu op2;
315 sim_fpu_32to (&op1, x);
316 sim_fpu_32to (&op2, y);
317 return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2);
321 static DF
322 fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x)
324 sim_fpu op1;
325 uint64_t res;
327 sim_fpu_32to (&op1, x);
328 sim_fpu_to64 (&res, &op1);
330 return res;
333 static SF
334 ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x)
336 sim_fpu op1;
337 uint32_t res;
339 sim_fpu_64to (&op1, x);
340 sim_fpu_to32 (&res, &op1);
342 return res;
345 static SF
346 floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x)
348 sim_fpu ans;
349 uint32_t res;
351 sim_fpu_i32to (&ans, x, sim_fpu_round_near);
352 sim_fpu_to32 (&res, &ans);
353 return res;
356 static DF
357 floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x)
359 sim_fpu ans;
360 uint64_t res;
362 sim_fpu_i32to (&ans, x, sim_fpu_round_near);
363 sim_fpu_to64 (&res, &ans);
364 return res;
367 static DF
368 floatdidf (CGEN_FPU* fpu, int how UNUSED, DI x)
370 sim_fpu ans;
371 uint64_t res;
373 sim_fpu_i64to (&ans, x, sim_fpu_round_near);
374 sim_fpu_to64 (&res, &ans);
375 return res;
378 static SF
379 ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x)
381 sim_fpu ans;
382 uint32_t res;
384 sim_fpu_u32to (&ans, x, sim_fpu_round_near);
385 sim_fpu_to32 (&res, &ans);
386 return res;
389 static SI
390 fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
392 sim_fpu op1;
393 int32_t res;
395 sim_fpu_32to (&op1, x);
396 sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
397 return res;
400 static SI
401 fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x)
403 sim_fpu op1;
404 int32_t res;
406 sim_fpu_64to (&op1, x);
407 sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
408 return res;
411 static DI
412 fixdfdi (CGEN_FPU* fpu, int how UNUSED, DF x)
414 sim_fpu op1;
415 int64_t res;
417 sim_fpu_64to (&op1, x);
418 sim_fpu_to64i (&res, &op1, sim_fpu_round_near);
419 return res;
422 static USI
423 ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
425 sim_fpu op1;
426 uint32_t res;
428 sim_fpu_32to (&op1, x);
429 sim_fpu_to32u (&res, &op1, sim_fpu_round_near);
430 return res;
433 /* DF mode support */
435 static DF
436 adddf (CGEN_FPU* fpu, DF x, DF y)
438 sim_fpu op1;
439 sim_fpu op2;
440 sim_fpu ans;
441 uint64_t res;
442 sim_fpu_status status;
444 sim_fpu_64to (&op1, x);
445 sim_fpu_64to (&op2, y);
446 status = sim_fpu_add (&ans, &op1, &op2);
447 if (status != 0)
448 (*fpu->ops->error) (fpu, status);
449 sim_fpu_to64 (&res, &ans);
451 return res;
454 static DF
455 subdf (CGEN_FPU* fpu, DF x, DF y)
457 sim_fpu op1;
458 sim_fpu op2;
459 sim_fpu ans;
460 uint64_t res;
461 sim_fpu_status status;
463 sim_fpu_64to (&op1, x);
464 sim_fpu_64to (&op2, y);
465 status = sim_fpu_sub (&ans, &op1, &op2);
466 if (status != 0)
467 (*fpu->ops->error) (fpu, status);
468 sim_fpu_to64 (&res, &ans);
470 return res;
473 static DF
474 muldf (CGEN_FPU* fpu, DF x, DF y)
476 sim_fpu op1;
477 sim_fpu op2;
478 sim_fpu ans;
479 uint64_t res;
480 sim_fpu_status status;
482 sim_fpu_64to (&op1, x);
483 sim_fpu_64to (&op2, y);
484 status = sim_fpu_mul (&ans, &op1, &op2);
485 if (status != 0)
486 (*fpu->ops->error) (fpu, status);
487 sim_fpu_to64 (&res, &ans);
489 return res;
492 static DF
493 divdf (CGEN_FPU* fpu, DF x, DF y)
495 sim_fpu op1;
496 sim_fpu op2;
497 sim_fpu ans;
498 uint64_t res;
499 sim_fpu_status status;
501 sim_fpu_64to (&op1, x);
502 sim_fpu_64to (&op2, y);
503 status = sim_fpu_div (&ans, &op1, &op2);
504 if (status != 0)
505 (*fpu->ops->error) (fpu, status);
506 sim_fpu_to64 (&res, &ans);
508 return res;
511 static DF
512 remdf (CGEN_FPU* fpu, DF x, DF y)
514 sim_fpu op1;
515 sim_fpu op2;
516 sim_fpu ans;
517 uint64_t res;
518 sim_fpu_status status;
520 sim_fpu_64to (&op1, x);
521 sim_fpu_64to (&op2, y);
522 status = sim_fpu_rem (&ans, &op1, &op2);
523 if (status != 0)
524 (*fpu->ops->error) (fpu, status);
525 sim_fpu_to64(&res, &ans);
527 return res;
530 static DF
531 negdf (CGEN_FPU* fpu, DF x)
533 sim_fpu op1;
534 sim_fpu ans;
535 uint64_t res;
536 sim_fpu_status status;
538 sim_fpu_64to (&op1, x);
539 status = sim_fpu_neg (&ans, &op1);
540 if (status != 0)
541 (*fpu->ops->error) (fpu, status);
542 sim_fpu_to64 (&res, &ans);
544 return res;
547 static DF
548 absdf (CGEN_FPU* fpu, DF x)
550 sim_fpu op1;
551 sim_fpu ans;
552 uint64_t res;
553 sim_fpu_status status;
555 sim_fpu_64to (&op1, x);
556 status = sim_fpu_abs (&ans, &op1);
557 if (status != 0)
558 (*fpu->ops->error) (fpu, status);
559 sim_fpu_to64 (&res, &ans);
561 return res;
564 static DF
565 sqrtdf (CGEN_FPU* fpu, DF x)
567 sim_fpu op1;
568 sim_fpu ans;
569 uint64_t res;
570 sim_fpu_status status;
572 sim_fpu_64to (&op1, x);
573 status = sim_fpu_sqrt (&ans, &op1);
574 if (status != 0)
575 (*fpu->ops->error) (fpu, status);
576 sim_fpu_to64 (&res, &ans);
578 return res;
581 static DF
582 invdf (CGEN_FPU* fpu, DF x)
584 sim_fpu op1;
585 sim_fpu ans;
586 uint64_t res;
587 sim_fpu_status status;
589 sim_fpu_64to (&op1, x);
590 status = sim_fpu_inv (&ans, &op1);
591 if (status != 0)
592 (*fpu->ops->error) (fpu, status);
593 sim_fpu_to64 (&res, &ans);
595 return res;
598 static DF
599 mindf (CGEN_FPU* fpu, DF x, DF y)
601 sim_fpu op1;
602 sim_fpu op2;
603 sim_fpu ans;
604 uint64_t res;
605 sim_fpu_status status;
607 sim_fpu_64to (&op1, x);
608 sim_fpu_64to (&op2, y);
609 status = sim_fpu_min (&ans, &op1, &op2);
610 if (status != 0)
611 (*fpu->ops->error) (fpu, status);
612 sim_fpu_to64 (&res, &ans);
614 return res;
617 static DF
618 maxdf (CGEN_FPU* fpu, DF x, DF y)
620 sim_fpu op1;
621 sim_fpu op2;
622 sim_fpu ans;
623 uint64_t res;
624 sim_fpu_status status;
626 sim_fpu_64to (&op1, x);
627 sim_fpu_64to (&op2, y);
628 status = sim_fpu_max (&ans, &op1, &op2);
629 if (status != 0)
630 (*fpu->ops->error) (fpu, status);
631 sim_fpu_to64 (&res, &ans);
633 return res;
636 static CGEN_FP_CMP
637 cmpdf (CGEN_FPU* fpu, DF x, DF y)
639 sim_fpu op1;
640 sim_fpu op2;
642 sim_fpu_64to (&op1, x);
643 sim_fpu_64to (&op2, y);
645 if (sim_fpu_is_nan (&op1)
646 || sim_fpu_is_nan (&op2))
647 return FP_CMP_NAN;
649 if (x < y)
650 return FP_CMP_LT;
651 if (x > y)
652 return FP_CMP_GT;
653 return FP_CMP_EQ;
656 static int
657 eqdf (CGEN_FPU* fpu, DF x, DF y)
659 sim_fpu op1;
660 sim_fpu op2;
662 sim_fpu_64to (&op1, x);
663 sim_fpu_64to (&op2, y);
664 return sim_fpu_is_eq (&op1, &op2);
667 static int
668 nedf (CGEN_FPU* fpu, DF x, DF y)
670 sim_fpu op1;
671 sim_fpu op2;
673 sim_fpu_64to (&op1, x);
674 sim_fpu_64to (&op2, y);
675 return sim_fpu_is_ne (&op1, &op2);
678 static int
679 ltdf (CGEN_FPU* fpu, DF x, DF y)
681 sim_fpu op1;
682 sim_fpu op2;
684 sim_fpu_64to (&op1, x);
685 sim_fpu_64to (&op2, y);
686 return sim_fpu_is_lt (&op1, &op2);
689 static int
690 ledf (CGEN_FPU* fpu, DF x, DF y)
692 sim_fpu op1;
693 sim_fpu op2;
695 sim_fpu_64to (&op1, x);
696 sim_fpu_64to (&op2, y);
697 return sim_fpu_is_le (&op1, &op2);
700 static int
701 gtdf (CGEN_FPU* fpu, DF x, DF y)
703 sim_fpu op1;
704 sim_fpu op2;
706 sim_fpu_64to (&op1, x);
707 sim_fpu_64to (&op2, y);
708 return sim_fpu_is_gt (&op1, &op2);
711 static int
712 gedf (CGEN_FPU* fpu, DF x, DF y)
714 sim_fpu op1;
715 sim_fpu op2;
717 sim_fpu_64to (&op1, x);
718 sim_fpu_64to (&op2, y);
719 return sim_fpu_is_ge (&op1, &op2);
722 static int
723 unordereddf (CGEN_FPU* fpu, DF x, DF y)
725 sim_fpu op1;
726 sim_fpu op2;
728 sim_fpu_64to (&op1, x);
729 sim_fpu_64to (&op2, y);
730 return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2);
733 /* Initialize FP_OPS to use accurate library. */
735 void
736 cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
738 CGEN_FP_OPS* o;
740 fpu->owner = cpu;
741 /* ??? small memory leak, not freed by sim_close */
742 fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS));
744 o = fpu->ops;
745 memset (o, 0, sizeof (*o));
747 o->error = error;
749 o->addsf = addsf;
750 o->subsf = subsf;
751 o->mulsf = mulsf;
752 o->divsf = divsf;
753 o->remsf = remsf;
754 o->negsf = negsf;
755 o->abssf = abssf;
756 o->sqrtsf = sqrtsf;
757 o->invsf = invsf;
758 o->minsf = minsf;
759 o->maxsf = maxsf;
760 o->cmpsf = cmpsf;
761 o->eqsf = eqsf;
762 o->nesf = nesf;
763 o->ltsf = ltsf;
764 o->lesf = lesf;
765 o->gtsf = gtsf;
766 o->gesf = gesf;
767 o->unorderedsf = unorderedsf;
769 o->adddf = adddf;
770 o->subdf = subdf;
771 o->muldf = muldf;
772 o->divdf = divdf;
773 o->remdf = remdf;
774 o->negdf = negdf;
775 o->absdf = absdf;
776 o->sqrtdf = sqrtdf;
777 o->invdf = invdf;
778 o->mindf = mindf;
779 o->maxdf = maxdf;
780 o->cmpdf = cmpdf;
781 o->eqdf = eqdf;
782 o->nedf = nedf;
783 o->ltdf = ltdf;
784 o->ledf = ledf;
785 o->gtdf = gtdf;
786 o->gedf = gedf;
787 o->unordereddf = unordereddf;
788 o->fextsfdf = fextsfdf;
789 o->ftruncdfsf = ftruncdfsf;
790 o->floatsisf = floatsisf;
791 o->floatsidf = floatsidf;
792 o->floatdidf = floatdidf;
793 o->ufloatsisf = ufloatsisf;
794 o->fixsfsi = fixsfsi;
795 o->fixdfsi = fixdfsi;
796 o->fixdfdi = fixdfdi;
797 o->ufixsfsi = ufixsfsi;