x86: fold narrowing VCVT* templates
[external/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 #include "sim-main.h"
15 #include "sim-fpu.h"
16
17 /* SF mode support */
18
19 static SF
20 addsf (CGEN_FPU* fpu, SF x, SF y)
21 {
22   sim_fpu op1;
23   sim_fpu op2;
24   sim_fpu ans;
25   unsigned32 res;
26   sim_fpu_status status;
27
28   sim_fpu_32to (&op1, x);
29   sim_fpu_32to (&op2, y);
30   status = sim_fpu_add (&ans, &op1, &op2);
31   if (status != 0)
32     (*fpu->ops->error) (fpu, status);
33   sim_fpu_to32 (&res, &ans);
34
35   return res;
36 }
37
38 static SF
39 subsf (CGEN_FPU* fpu, SF x, SF y)
40 {
41   sim_fpu op1;
42   sim_fpu op2;
43   sim_fpu ans;
44   unsigned32 res;
45   sim_fpu_status status;
46
47   sim_fpu_32to (&op1, x);
48   sim_fpu_32to (&op2, y);
49   status = sim_fpu_sub (&ans, &op1, &op2);
50   if (status != 0)
51     (*fpu->ops->error) (fpu, status);
52   sim_fpu_to32 (&res, &ans);
53
54   return res;
55 }
56
57 static SF
58 mulsf (CGEN_FPU* fpu, SF x, SF y)
59 {
60   sim_fpu op1;
61   sim_fpu op2;
62   sim_fpu ans;
63   unsigned32 res;
64   sim_fpu_status status;
65
66   sim_fpu_32to (&op1, x);
67   sim_fpu_32to (&op2, y);
68   status = sim_fpu_mul (&ans, &op1, &op2);
69   if (status != 0)
70     (*fpu->ops->error) (fpu, status);
71   sim_fpu_to32 (&res, &ans);
72
73   return res;
74 }
75
76 static SF
77 divsf (CGEN_FPU* fpu, SF x, SF y)
78 {
79   sim_fpu op1;
80   sim_fpu op2;
81   sim_fpu ans;
82   unsigned32 res;
83   sim_fpu_status status;
84
85   sim_fpu_32to (&op1, x);
86   sim_fpu_32to (&op2, y);
87   status = sim_fpu_div (&ans, &op1, &op2);
88   if (status != 0)
89     (*fpu->ops->error) (fpu, status);
90   sim_fpu_to32 (&res, &ans);
91
92   return res;
93 }
94
95 static SF
96 remsf (CGEN_FPU* fpu, SF x, SF y)
97 {
98   sim_fpu op1;
99   sim_fpu op2;
100   sim_fpu ans;
101   unsigned32 res;
102   sim_fpu_status status;
103
104   sim_fpu_32to (&op1, x);
105   sim_fpu_32to (&op2, y);
106   status = sim_fpu_rem (&ans, &op1, &op2);
107   if (status != 0)
108     (*fpu->ops->error) (fpu, status);
109   sim_fpu_to32 (&res, &ans);
110
111   return res;
112 }
113
114 static SF
115 negsf (CGEN_FPU* fpu, SF x)
116 {
117   sim_fpu op1;
118   sim_fpu ans;
119   unsigned32 res;
120   sim_fpu_status status;
121
122   sim_fpu_32to (&op1, x);
123   status = sim_fpu_neg (&ans, &op1);
124   if (status != 0)
125     (*fpu->ops->error) (fpu, status);
126   sim_fpu_to32 (&res, &ans);
127
128   return res;
129 }
130
131 static SF
132 abssf (CGEN_FPU* fpu, SF x)
133 {
134   sim_fpu op1;
135   sim_fpu ans;
136   unsigned32 res;
137   sim_fpu_status status;
138
139   sim_fpu_32to (&op1, x);
140   status = sim_fpu_abs (&ans, &op1);
141   if (status != 0)
142     (*fpu->ops->error) (fpu, status);
143   sim_fpu_to32 (&res, &ans);
144
145   return res;
146 }
147
148 static SF
149 sqrtsf (CGEN_FPU* fpu, SF x)
150 {
151   sim_fpu op1;
152   sim_fpu ans;
153   unsigned32 res;
154   sim_fpu_status status;
155
156   sim_fpu_32to (&op1, x);
157   status = sim_fpu_sqrt (&ans, &op1);
158   if (status != 0)
159     (*fpu->ops->error) (fpu, status);
160   sim_fpu_to32 (&res, &ans);
161
162   return res;
163 }
164
165 static SF
166 invsf (CGEN_FPU* fpu, SF x)
167 {
168   sim_fpu op1;
169   sim_fpu ans;
170   unsigned32 res;
171   sim_fpu_status status;
172
173   sim_fpu_32to (&op1, x);
174   status = sim_fpu_inv (&ans, &op1);
175   if (status != 0)
176     (*fpu->ops->error) (fpu, status);
177   sim_fpu_to32 (&res, &ans);
178
179   return res;
180 }
181
182 static SF
183 minsf (CGEN_FPU* fpu, SF x, SF y)
184 {
185   sim_fpu op1;
186   sim_fpu op2;
187   sim_fpu ans;
188   unsigned32 res;
189   sim_fpu_status status;
190
191   sim_fpu_32to (&op1, x);
192   sim_fpu_32to (&op2, y);
193   status = sim_fpu_min (&ans, &op1, &op2);
194   if (status != 0)
195     (*fpu->ops->error) (fpu, status);
196   sim_fpu_to32 (&res, &ans);
197
198   return res;
199 }
200
201 static SF
202 maxsf (CGEN_FPU* fpu, SF x, SF y)
203 {
204   sim_fpu op1;
205   sim_fpu op2;
206   sim_fpu ans;
207   unsigned32 res;
208   sim_fpu_status status;
209
210   sim_fpu_32to (&op1, x);
211   sim_fpu_32to (&op2, y);
212   status = sim_fpu_max (&ans, &op1, &op2);
213   if (status != 0)
214     (*fpu->ops->error) (fpu, status);
215   sim_fpu_to32 (&res, &ans);
216
217   return res;
218 }
219
220 static CGEN_FP_CMP
221 cmpsf (CGEN_FPU* fpu, SF x, SF y)
222 {
223   sim_fpu op1;
224   sim_fpu op2;
225
226   sim_fpu_32to (&op1, x);
227   sim_fpu_32to (&op2, y);
228
229   if (sim_fpu_is_nan (&op1)
230       || sim_fpu_is_nan (&op2))
231     return FP_CMP_NAN;
232
233   if (x < y)
234     return FP_CMP_LT;
235   if (x > y)
236     return FP_CMP_GT;
237   return FP_CMP_EQ;
238 }
239
240 static int
241 eqsf (CGEN_FPU* fpu, SF x, SF y)
242 {
243   sim_fpu op1;
244   sim_fpu op2;
245
246   sim_fpu_32to (&op1, x);
247   sim_fpu_32to (&op2, y);
248   return sim_fpu_is_eq (&op1, &op2);
249 }
250
251 static int
252 nesf (CGEN_FPU* fpu, SF x, SF y)
253 {
254   sim_fpu op1;
255   sim_fpu op2;
256
257   sim_fpu_32to (&op1, x);
258   sim_fpu_32to (&op2, y);
259   return sim_fpu_is_ne (&op1, &op2);
260 }
261
262 static int
263 ltsf (CGEN_FPU* fpu, SF x, SF y)
264 {
265   sim_fpu op1;
266   sim_fpu op2;
267
268   sim_fpu_32to (&op1, x);
269   sim_fpu_32to (&op2, y);
270   return sim_fpu_is_lt (&op1, &op2);
271 }
272
273 static int
274 lesf (CGEN_FPU* fpu, SF x, SF y)
275 {
276   sim_fpu op1;
277   sim_fpu op2;
278
279   sim_fpu_32to (&op1, x);
280   sim_fpu_32to (&op2, y);
281   return sim_fpu_is_le (&op1, &op2);
282 }
283
284 static int
285 gtsf (CGEN_FPU* fpu, SF x, SF y)
286 {
287   sim_fpu op1;
288   sim_fpu op2;
289
290   sim_fpu_32to (&op1, x);
291   sim_fpu_32to (&op2, y);
292   return sim_fpu_is_gt (&op1, &op2);
293 }
294
295 static int
296 gesf (CGEN_FPU* fpu, SF x, SF y)
297 {
298   sim_fpu op1;
299   sim_fpu op2;
300
301   sim_fpu_32to (&op1, x);
302   sim_fpu_32to (&op2, y);
303   return sim_fpu_is_ge (&op1, &op2);
304 }
305
306 static DF
307 fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x)
308 {
309   sim_fpu op1;
310   unsigned64 res;
311
312   sim_fpu_32to (&op1, x);
313   sim_fpu_to64 (&res, &op1);
314
315   return res;
316 }
317
318 static SF
319 ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x)
320 {
321   sim_fpu op1;
322   unsigned32 res;
323
324   sim_fpu_64to (&op1, x);
325   sim_fpu_to32 (&res, &op1);
326
327   return res;
328 }
329
330 static SF
331 floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x)
332 {
333   sim_fpu ans;
334   unsigned32 res;
335
336   sim_fpu_i32to (&ans, x, sim_fpu_round_near);
337   sim_fpu_to32 (&res, &ans);
338   return res;
339 }
340
341 static DF
342 floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x)
343 {
344   sim_fpu ans;
345   unsigned64 res;
346
347   sim_fpu_i32to (&ans, x, sim_fpu_round_near);
348   sim_fpu_to64 (&res, &ans);
349   return res;
350 }
351
352 static SF
353 ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x)
354 {
355   sim_fpu ans;
356   unsigned32 res;
357
358   sim_fpu_u32to (&ans, x, sim_fpu_round_near);
359   sim_fpu_to32 (&res, &ans);
360   return res;
361 }
362
363 static SI
364 fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
365 {
366   sim_fpu op1;
367   unsigned32 res;
368
369   sim_fpu_32to (&op1, x);
370   sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
371   return res;
372 }
373
374 static SI
375 fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x)
376 {
377   sim_fpu op1;
378   unsigned32 res;
379
380   sim_fpu_64to (&op1, x);
381   sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
382   return res;
383 }
384
385 static USI
386 ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
387 {
388   sim_fpu op1;
389   unsigned32 res;
390
391   sim_fpu_32to (&op1, x);
392   sim_fpu_to32u (&res, &op1, sim_fpu_round_near);
393   return res;
394 }
395 \f
396 /* DF mode support */
397
398 static DF
399 adddf (CGEN_FPU* fpu, DF x, DF y)
400 {
401   sim_fpu op1;
402   sim_fpu op2;
403   sim_fpu ans;
404   unsigned64 res;
405   sim_fpu_status status;
406
407   sim_fpu_64to (&op1, x);
408   sim_fpu_64to (&op2, y);
409   status = sim_fpu_add (&ans, &op1, &op2);
410   if (status != 0)
411     (*fpu->ops->error) (fpu, status);
412   sim_fpu_to64 (&res, &ans);
413
414   return res;
415 }
416
417 static DF
418 subdf (CGEN_FPU* fpu, DF x, DF y)
419 {
420   sim_fpu op1;
421   sim_fpu op2;
422   sim_fpu ans;
423   unsigned64 res;
424   sim_fpu_status status;
425
426   sim_fpu_64to (&op1, x);
427   sim_fpu_64to (&op2, y);
428   status = sim_fpu_sub (&ans, &op1, &op2);
429   if (status != 0)
430     (*fpu->ops->error) (fpu, status);
431   sim_fpu_to64 (&res, &ans);
432
433   return res;
434 }
435
436 static DF
437 muldf (CGEN_FPU* fpu, DF x, DF y)
438 {
439   sim_fpu op1;
440   sim_fpu op2;
441   sim_fpu ans;
442   unsigned64 res;
443   sim_fpu_status status;
444
445   sim_fpu_64to (&op1, x);
446   sim_fpu_64to (&op2, y);
447   status = sim_fpu_mul (&ans, &op1, &op2);
448   if (status != 0)
449     (*fpu->ops->error) (fpu, status);
450   sim_fpu_to64 (&res, &ans);
451
452   return res;
453 }
454
455 static DF
456 divdf (CGEN_FPU* fpu, DF x, DF y)
457 {
458   sim_fpu op1;
459   sim_fpu op2;
460   sim_fpu ans;
461   unsigned64 res;
462   sim_fpu_status status;
463
464   sim_fpu_64to (&op1, x);
465   sim_fpu_64to (&op2, y);
466   status = sim_fpu_div (&ans, &op1, &op2);
467   if (status != 0)
468     (*fpu->ops->error) (fpu, status);
469   sim_fpu_to64 (&res, &ans);
470
471   return res;
472 }
473
474 static DF
475 remdf (CGEN_FPU* fpu, DF x, DF y)
476 {
477   sim_fpu op1;
478   sim_fpu op2;
479   sim_fpu ans;
480   unsigned64 res;
481   sim_fpu_status status;
482
483   sim_fpu_64to (&op1, x);
484   sim_fpu_64to (&op2, y);
485   status = sim_fpu_rem (&ans, &op1, &op2);
486   if (status != 0)
487     (*fpu->ops->error) (fpu, status);
488   sim_fpu_to64(&res, &ans);
489
490   return res;
491 }
492
493 static DF
494 negdf (CGEN_FPU* fpu, DF x)
495 {
496   sim_fpu op1;
497   sim_fpu ans;
498   unsigned64 res;
499   sim_fpu_status status;
500
501   sim_fpu_64to (&op1, x);
502   status = sim_fpu_neg (&ans, &op1);
503   if (status != 0)
504     (*fpu->ops->error) (fpu, status);
505   sim_fpu_to64 (&res, &ans);
506
507   return res;
508 }
509
510 static DF
511 absdf (CGEN_FPU* fpu, DF x)
512 {
513   sim_fpu op1;
514   sim_fpu ans;
515   unsigned64 res;
516   sim_fpu_status status;
517
518   sim_fpu_64to (&op1, x);
519   status = sim_fpu_abs (&ans, &op1);
520   if (status != 0)
521     (*fpu->ops->error) (fpu, status);
522   sim_fpu_to64 (&res, &ans);
523
524   return res;
525 }
526
527 static DF
528 sqrtdf (CGEN_FPU* fpu, DF x)
529 {
530   sim_fpu op1;
531   sim_fpu ans;
532   unsigned64 res;
533   sim_fpu_status status;
534
535   sim_fpu_64to (&op1, x);
536   status = sim_fpu_sqrt (&ans, &op1);
537   if (status != 0)
538     (*fpu->ops->error) (fpu, status);
539   sim_fpu_to64 (&res, &ans);
540
541   return res;
542 }
543
544 static DF
545 invdf (CGEN_FPU* fpu, DF x)
546 {
547   sim_fpu op1;
548   sim_fpu ans;
549   unsigned64 res;
550   sim_fpu_status status;
551
552   sim_fpu_64to (&op1, x);
553   status = sim_fpu_inv (&ans, &op1);
554   if (status != 0)
555     (*fpu->ops->error) (fpu, status);
556   sim_fpu_to64 (&res, &ans);
557
558   return res;
559 }
560
561 static DF
562 mindf (CGEN_FPU* fpu, DF x, DF y)
563 {
564   sim_fpu op1;
565   sim_fpu op2;
566   sim_fpu ans;
567   unsigned64 res;
568   sim_fpu_status status;
569
570   sim_fpu_64to (&op1, x);
571   sim_fpu_64to (&op2, y);
572   status = sim_fpu_min (&ans, &op1, &op2);
573   if (status != 0)
574     (*fpu->ops->error) (fpu, status);
575   sim_fpu_to64 (&res, &ans);
576
577   return res;
578 }
579
580 static DF
581 maxdf (CGEN_FPU* fpu, DF x, DF y)
582 {
583   sim_fpu op1;
584   sim_fpu op2;
585   sim_fpu ans;
586   unsigned64 res;
587   sim_fpu_status status;
588
589   sim_fpu_64to (&op1, x);
590   sim_fpu_64to (&op2, y);
591   status = sim_fpu_max (&ans, &op1, &op2);
592   if (status != 0)
593     (*fpu->ops->error) (fpu, status);
594   sim_fpu_to64 (&res, &ans);
595
596   return res;
597 }
598
599 static CGEN_FP_CMP
600 cmpdf (CGEN_FPU* fpu, DF x, DF y)
601 {
602   sim_fpu op1;
603   sim_fpu op2;
604
605   sim_fpu_64to (&op1, x);
606   sim_fpu_64to (&op2, y);
607
608   if (sim_fpu_is_nan (&op1)
609       || sim_fpu_is_nan (&op2))
610     return FP_CMP_NAN;
611
612   if (x < y)
613     return FP_CMP_LT;
614   if (x > y)
615     return FP_CMP_GT;
616   return FP_CMP_EQ;
617 }
618
619 static int
620 eqdf (CGEN_FPU* fpu, DF x, DF y)
621 {
622   sim_fpu op1;
623   sim_fpu op2;
624
625   sim_fpu_64to (&op1, x);
626   sim_fpu_64to (&op2, y);
627   return sim_fpu_is_eq (&op1, &op2);
628 }
629
630 static int
631 nedf (CGEN_FPU* fpu, DF x, DF y)
632 {
633   sim_fpu op1;
634   sim_fpu op2;
635
636   sim_fpu_64to (&op1, x);
637   sim_fpu_64to (&op2, y);
638   return sim_fpu_is_ne (&op1, &op2);
639 }
640
641 static int
642 ltdf (CGEN_FPU* fpu, DF x, DF y)
643 {
644   sim_fpu op1;
645   sim_fpu op2;
646
647   sim_fpu_64to (&op1, x);
648   sim_fpu_64to (&op2, y);
649   return sim_fpu_is_lt (&op1, &op2);
650 }
651
652 static int
653 ledf (CGEN_FPU* fpu, DF x, DF y)
654 {
655   sim_fpu op1;
656   sim_fpu op2;
657
658   sim_fpu_64to (&op1, x);
659   sim_fpu_64to (&op2, y);
660   return sim_fpu_is_le (&op1, &op2);
661 }
662
663 static int
664 gtdf (CGEN_FPU* fpu, DF x, DF y)
665 {
666   sim_fpu op1;
667   sim_fpu op2;
668
669   sim_fpu_64to (&op1, x);
670   sim_fpu_64to (&op2, y);
671   return sim_fpu_is_gt (&op1, &op2);
672 }
673
674 static int
675 gedf (CGEN_FPU* fpu, DF x, DF y)
676 {
677   sim_fpu op1;
678   sim_fpu op2;
679
680   sim_fpu_64to (&op1, x);
681   sim_fpu_64to (&op2, y);
682   return sim_fpu_is_ge (&op1, &op2);
683 }
684 \f
685 /* Initialize FP_OPS to use accurate library.  */
686
687 void
688 cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
689 {
690   CGEN_FP_OPS* o;
691
692   fpu->owner = cpu;
693   /* ??? small memory leak, not freed by sim_close */
694   fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS));
695
696   o = fpu->ops;
697   memset (o, 0, sizeof (*o));
698
699   o->error = error;
700
701   o->addsf = addsf;
702   o->subsf = subsf;
703   o->mulsf = mulsf;
704   o->divsf = divsf;
705   o->remsf = remsf;
706   o->negsf = negsf;
707   o->abssf = abssf;
708   o->sqrtsf = sqrtsf;
709   o->invsf = invsf;
710   o->minsf = minsf;
711   o->maxsf = maxsf;
712   o->cmpsf = cmpsf;
713   o->eqsf = eqsf;
714   o->nesf = nesf;
715   o->ltsf = ltsf;
716   o->lesf = lesf;
717   o->gtsf = gtsf;
718   o->gesf = gesf;
719
720   o->adddf = adddf;
721   o->subdf = subdf;
722   o->muldf = muldf;
723   o->divdf = divdf;
724   o->remdf = remdf;
725   o->negdf = negdf;
726   o->absdf = absdf;
727   o->sqrtdf = sqrtdf;
728   o->invdf = invdf;
729   o->mindf = mindf;
730   o->maxdf = maxdf;
731   o->cmpdf = cmpdf;
732   o->eqdf = eqdf;
733   o->nedf = nedf;
734   o->ltdf = ltdf;
735   o->ledf = ledf;
736   o->gtdf = gtdf;
737   o->gedf = gedf;
738   o->fextsfdf = fextsfdf;
739   o->ftruncdfsf = ftruncdfsf;
740   o->floatsisf = floatsisf;
741   o->floatsidf = floatsidf;
742   o->ufloatsisf = ufloatsisf;
743   o->fixsfsi = fixsfsi;
744   o->fixdfsi = fixdfsi;
745   o->ufixsfsi = ufixsfsi;
746 }