]> Git Repo - binutils.git/blob - sim/common/cgen-accfp.c
Automatic date update in version.in
[binutils.git] / sim / common / cgen-accfp.c
1 /* Accurate fp support for CGEN-based simulators.
2    Copyright (C) 1999 Cygnus Solutions.
3
4    This implemention assumes:
5    typedef USI SF;
6    typedef UDI DF;
7
8    TODO:
9    - lazy encoding/decoding
10    - checking return code (say by callback)
11    - proper rounding
12 */
13
14 /* This must come before any other includes.  */
15 #include "defs.h"
16
17 #include "sim-main.h"
18 #include "sim-fpu.h"
19
20 /* SF mode support */
21
22 static SF
23 addsf (CGEN_FPU* fpu, SF x, SF y)
24 {
25   sim_fpu op1;
26   sim_fpu op2;
27   sim_fpu ans;
28   uint32_t res;
29   sim_fpu_status status;
30
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);
37
38   return res;
39 }
40
41 static SF
42 subsf (CGEN_FPU* fpu, SF x, SF y)
43 {
44   sim_fpu op1;
45   sim_fpu op2;
46   sim_fpu ans;
47   uint32_t res;
48   sim_fpu_status status;
49
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);
56
57   return res;
58 }
59
60 static SF
61 mulsf (CGEN_FPU* fpu, SF x, SF y)
62 {
63   sim_fpu op1;
64   sim_fpu op2;
65   sim_fpu ans;
66   uint32_t res;
67   sim_fpu_status status;
68
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);
75
76   return res;
77 }
78
79 static SF
80 divsf (CGEN_FPU* fpu, SF x, SF y)
81 {
82   sim_fpu op1;
83   sim_fpu op2;
84   sim_fpu ans;
85   uint32_t res;
86   sim_fpu_status status;
87
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);
94
95   return res;
96 }
97
98 static SF
99 remsf (CGEN_FPU* fpu, SF x, SF y)
100 {
101   sim_fpu op1;
102   sim_fpu op2;
103   sim_fpu ans;
104   uint32_t res;
105   sim_fpu_status status;
106
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);
113
114   return res;
115 }
116
117 static SF
118 negsf (CGEN_FPU* fpu, SF x)
119 {
120   sim_fpu op1;
121   sim_fpu ans;
122   uint32_t res;
123   sim_fpu_status status;
124
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);
130
131   return res;
132 }
133
134 static SF
135 abssf (CGEN_FPU* fpu, SF x)
136 {
137   sim_fpu op1;
138   sim_fpu ans;
139   uint32_t res;
140   sim_fpu_status status;
141
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);
147
148   return res;
149 }
150
151 static SF
152 sqrtsf (CGEN_FPU* fpu, SF x)
153 {
154   sim_fpu op1;
155   sim_fpu ans;
156   uint32_t res;
157   sim_fpu_status status;
158
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);
164
165   return res;
166 }
167
168 static SF
169 invsf (CGEN_FPU* fpu, SF x)
170 {
171   sim_fpu op1;
172   sim_fpu ans;
173   uint32_t res;
174   sim_fpu_status status;
175
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);
181
182   return res;
183 }
184
185 static SF
186 minsf (CGEN_FPU* fpu, SF x, SF y)
187 {
188   sim_fpu op1;
189   sim_fpu op2;
190   sim_fpu ans;
191   uint32_t res;
192   sim_fpu_status status;
193
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);
200
201   return res;
202 }
203
204 static SF
205 maxsf (CGEN_FPU* fpu, SF x, SF y)
206 {
207   sim_fpu op1;
208   sim_fpu op2;
209   sim_fpu ans;
210   uint32_t res;
211   sim_fpu_status status;
212
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);
219
220   return res;
221 }
222
223 static CGEN_FP_CMP
224 cmpsf (CGEN_FPU* fpu, SF x, SF y)
225 {
226   sim_fpu op1;
227   sim_fpu op2;
228
229   sim_fpu_32to (&op1, x);
230   sim_fpu_32to (&op2, y);
231
232   if (sim_fpu_is_nan (&op1)
233       || sim_fpu_is_nan (&op2))
234     return FP_CMP_NAN;
235
236   if (x < y)
237     return FP_CMP_LT;
238   if (x > y)
239     return FP_CMP_GT;
240   return FP_CMP_EQ;
241 }
242
243 static int
244 eqsf (CGEN_FPU* fpu, SF x, SF y)
245 {
246   sim_fpu op1;
247   sim_fpu op2;
248
249   sim_fpu_32to (&op1, x);
250   sim_fpu_32to (&op2, y);
251   return sim_fpu_is_eq (&op1, &op2);
252 }
253
254 static int
255 nesf (CGEN_FPU* fpu, SF x, SF y)
256 {
257   sim_fpu op1;
258   sim_fpu op2;
259
260   sim_fpu_32to (&op1, x);
261   sim_fpu_32to (&op2, y);
262   return sim_fpu_is_ne (&op1, &op2);
263 }
264
265 static int
266 ltsf (CGEN_FPU* fpu, SF x, SF y)
267 {
268   sim_fpu op1;
269   sim_fpu op2;
270
271   sim_fpu_32to (&op1, x);
272   sim_fpu_32to (&op2, y);
273   return sim_fpu_is_lt (&op1, &op2);
274 }
275
276 static int
277 lesf (CGEN_FPU* fpu, SF x, SF y)
278 {
279   sim_fpu op1;
280   sim_fpu op2;
281
282   sim_fpu_32to (&op1, x);
283   sim_fpu_32to (&op2, y);
284   return sim_fpu_is_le (&op1, &op2);
285 }
286
287 static int
288 gtsf (CGEN_FPU* fpu, SF x, SF y)
289 {
290   sim_fpu op1;
291   sim_fpu op2;
292
293   sim_fpu_32to (&op1, x);
294   sim_fpu_32to (&op2, y);
295   return sim_fpu_is_gt (&op1, &op2);
296 }
297
298 static int
299 gesf (CGEN_FPU* fpu, SF x, SF y)
300 {
301   sim_fpu op1;
302   sim_fpu op2;
303
304   sim_fpu_32to (&op1, x);
305   sim_fpu_32to (&op2, y);
306   return sim_fpu_is_ge (&op1, &op2);
307 }
308
309 static int
310 unorderedsf (CGEN_FPU* fpu, SF x, SF y)
311 {
312   sim_fpu op1;
313   sim_fpu op2;
314
315   sim_fpu_32to (&op1, x);
316   sim_fpu_32to (&op2, y);
317   return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2);
318 }
319
320
321 static DF
322 fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x)
323 {
324   sim_fpu op1;
325   uint64_t res;
326
327   sim_fpu_32to (&op1, x);
328   sim_fpu_to64 (&res, &op1);
329
330   return res;
331 }
332
333 static SF
334 ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x)
335 {
336   sim_fpu op1;
337   uint32_t res;
338
339   sim_fpu_64to (&op1, x);
340   sim_fpu_to32 (&res, &op1);
341
342   return res;
343 }
344
345 static SF
346 floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x)
347 {
348   sim_fpu ans;
349   uint32_t res;
350
351   sim_fpu_i32to (&ans, x, sim_fpu_round_near);
352   sim_fpu_to32 (&res, &ans);
353   return res;
354 }
355
356 static DF
357 floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x)
358 {
359   sim_fpu ans;
360   uint64_t res;
361
362   sim_fpu_i32to (&ans, x, sim_fpu_round_near);
363   sim_fpu_to64 (&res, &ans);
364   return res;
365 }
366
367 static DF
368 floatdidf (CGEN_FPU* fpu, int how UNUSED, DI x)
369 {
370   sim_fpu ans;
371   uint64_t res;
372
373   sim_fpu_i64to (&ans, x, sim_fpu_round_near);
374   sim_fpu_to64 (&res, &ans);
375   return res;
376 }
377
378 static SF
379 ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x)
380 {
381   sim_fpu ans;
382   uint32_t res;
383
384   sim_fpu_u32to (&ans, x, sim_fpu_round_near);
385   sim_fpu_to32 (&res, &ans);
386   return res;
387 }
388
389 static SI
390 fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
391 {
392   sim_fpu op1;
393   int32_t res;
394
395   sim_fpu_32to (&op1, x);
396   sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
397   return res;
398 }
399
400 static SI
401 fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x)
402 {
403   sim_fpu op1;
404   int32_t res;
405
406   sim_fpu_64to (&op1, x);
407   sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
408   return res;
409 }
410
411 static DI
412 fixdfdi (CGEN_FPU* fpu, int how UNUSED, DF x)
413 {
414   sim_fpu op1;
415   int64_t res;
416
417   sim_fpu_64to (&op1, x);
418   sim_fpu_to64i (&res, &op1, sim_fpu_round_near);
419   return res;
420 }
421
422 static USI
423 ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
424 {
425   sim_fpu op1;
426   uint32_t res;
427
428   sim_fpu_32to (&op1, x);
429   sim_fpu_to32u (&res, &op1, sim_fpu_round_near);
430   return res;
431 }
432 \f
433 /* DF mode support */
434
435 static DF
436 adddf (CGEN_FPU* fpu, DF x, DF y)
437 {
438   sim_fpu op1;
439   sim_fpu op2;
440   sim_fpu ans;
441   uint64_t res;
442   sim_fpu_status status;
443
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);
450
451   return res;
452 }
453
454 static DF
455 subdf (CGEN_FPU* fpu, DF x, DF y)
456 {
457   sim_fpu op1;
458   sim_fpu op2;
459   sim_fpu ans;
460   uint64_t res;
461   sim_fpu_status status;
462
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);
469
470   return res;
471 }
472
473 static DF
474 muldf (CGEN_FPU* fpu, DF x, DF y)
475 {
476   sim_fpu op1;
477   sim_fpu op2;
478   sim_fpu ans;
479   uint64_t res;
480   sim_fpu_status status;
481
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);
488
489   return res;
490 }
491
492 static DF
493 divdf (CGEN_FPU* fpu, DF x, DF y)
494 {
495   sim_fpu op1;
496   sim_fpu op2;
497   sim_fpu ans;
498   uint64_t res;
499   sim_fpu_status status;
500
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);
507
508   return res;
509 }
510
511 static DF
512 remdf (CGEN_FPU* fpu, DF x, DF y)
513 {
514   sim_fpu op1;
515   sim_fpu op2;
516   sim_fpu ans;
517   uint64_t res;
518   sim_fpu_status status;
519
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);
526
527   return res;
528 }
529
530 static DF
531 negdf (CGEN_FPU* fpu, DF x)
532 {
533   sim_fpu op1;
534   sim_fpu ans;
535   uint64_t res;
536   sim_fpu_status status;
537
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);
543
544   return res;
545 }
546
547 static DF
548 absdf (CGEN_FPU* fpu, DF x)
549 {
550   sim_fpu op1;
551   sim_fpu ans;
552   uint64_t res;
553   sim_fpu_status status;
554
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);
560
561   return res;
562 }
563
564 static DF
565 sqrtdf (CGEN_FPU* fpu, DF x)
566 {
567   sim_fpu op1;
568   sim_fpu ans;
569   uint64_t res;
570   sim_fpu_status status;
571
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);
577
578   return res;
579 }
580
581 static DF
582 invdf (CGEN_FPU* fpu, DF x)
583 {
584   sim_fpu op1;
585   sim_fpu ans;
586   uint64_t res;
587   sim_fpu_status status;
588
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);
594
595   return res;
596 }
597
598 static DF
599 mindf (CGEN_FPU* fpu, DF x, DF y)
600 {
601   sim_fpu op1;
602   sim_fpu op2;
603   sim_fpu ans;
604   uint64_t res;
605   sim_fpu_status status;
606
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);
613
614   return res;
615 }
616
617 static DF
618 maxdf (CGEN_FPU* fpu, DF x, DF y)
619 {
620   sim_fpu op1;
621   sim_fpu op2;
622   sim_fpu ans;
623   uint64_t res;
624   sim_fpu_status status;
625
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);
632
633   return res;
634 }
635
636 static CGEN_FP_CMP
637 cmpdf (CGEN_FPU* fpu, DF x, DF y)
638 {
639   sim_fpu op1;
640   sim_fpu op2;
641
642   sim_fpu_64to (&op1, x);
643   sim_fpu_64to (&op2, y);
644
645   if (sim_fpu_is_nan (&op1)
646       || sim_fpu_is_nan (&op2))
647     return FP_CMP_NAN;
648
649   if (x < y)
650     return FP_CMP_LT;
651   if (x > y)
652     return FP_CMP_GT;
653   return FP_CMP_EQ;
654 }
655
656 static int
657 eqdf (CGEN_FPU* fpu, DF x, DF y)
658 {
659   sim_fpu op1;
660   sim_fpu op2;
661
662   sim_fpu_64to (&op1, x);
663   sim_fpu_64to (&op2, y);
664   return sim_fpu_is_eq (&op1, &op2);
665 }
666
667 static int
668 nedf (CGEN_FPU* fpu, DF x, DF y)
669 {
670   sim_fpu op1;
671   sim_fpu op2;
672
673   sim_fpu_64to (&op1, x);
674   sim_fpu_64to (&op2, y);
675   return sim_fpu_is_ne (&op1, &op2);
676 }
677
678 static int
679 ltdf (CGEN_FPU* fpu, DF x, DF y)
680 {
681   sim_fpu op1;
682   sim_fpu op2;
683
684   sim_fpu_64to (&op1, x);
685   sim_fpu_64to (&op2, y);
686   return sim_fpu_is_lt (&op1, &op2);
687 }
688
689 static int
690 ledf (CGEN_FPU* fpu, DF x, DF y)
691 {
692   sim_fpu op1;
693   sim_fpu op2;
694
695   sim_fpu_64to (&op1, x);
696   sim_fpu_64to (&op2, y);
697   return sim_fpu_is_le (&op1, &op2);
698 }
699
700 static int
701 gtdf (CGEN_FPU* fpu, DF x, DF y)
702 {
703   sim_fpu op1;
704   sim_fpu op2;
705
706   sim_fpu_64to (&op1, x);
707   sim_fpu_64to (&op2, y);
708   return sim_fpu_is_gt (&op1, &op2);
709 }
710
711 static int
712 gedf (CGEN_FPU* fpu, DF x, DF y)
713 {
714   sim_fpu op1;
715   sim_fpu op2;
716
717   sim_fpu_64to (&op1, x);
718   sim_fpu_64to (&op2, y);
719   return sim_fpu_is_ge (&op1, &op2);
720 }
721
722 static int
723 unordereddf (CGEN_FPU* fpu, DF x, DF y)
724 {
725   sim_fpu op1;
726   sim_fpu op2;
727
728   sim_fpu_64to (&op1, x);
729   sim_fpu_64to (&op2, y);
730   return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2);
731 }
732 \f
733 /* Initialize FP_OPS to use accurate library.  */
734
735 void
736 cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
737 {
738   CGEN_FP_OPS* o;
739
740   fpu->owner = cpu;
741   /* ??? small memory leak, not freed by sim_close */
742   fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS));
743
744   o = fpu->ops;
745   memset (o, 0, sizeof (*o));
746
747   o->error = error;
748
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;
768
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;
798 }
This page took 0.105739 seconds and 4 git commands to generate.