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
addsf(CGEN_FPU * fpu,SF x,SF y)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
subsf(CGEN_FPU * fpu,SF x,SF y)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
mulsf(CGEN_FPU * fpu,SF x,SF y)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
divsf(CGEN_FPU * fpu,SF x,SF y)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
negsf(CGEN_FPU * fpu,SF x)96 negsf (CGEN_FPU* fpu, SF x)
97 {
98   sim_fpu op1;
99   sim_fpu ans;
100   unsigned32 res;
101   sim_fpu_status status;
102 
103   sim_fpu_32to (&op1, x);
104   status = sim_fpu_neg (&ans, &op1);
105   if (status != 0)
106     (*fpu->ops->error) (fpu, status);
107   sim_fpu_to32 (&res, &ans);
108 
109   return res;
110 }
111 
112 static SF
abssf(CGEN_FPU * fpu,SF x)113 abssf (CGEN_FPU* fpu, SF x)
114 {
115   sim_fpu op1;
116   sim_fpu ans;
117   unsigned32 res;
118   sim_fpu_status status;
119 
120   sim_fpu_32to (&op1, x);
121   status = sim_fpu_abs (&ans, &op1);
122   if (status != 0)
123     (*fpu->ops->error) (fpu, status);
124   sim_fpu_to32 (&res, &ans);
125 
126   return res;
127 }
128 
129 static SF
sqrtsf(CGEN_FPU * fpu,SF x)130 sqrtsf (CGEN_FPU* fpu, SF x)
131 {
132   sim_fpu op1;
133   sim_fpu ans;
134   unsigned32 res;
135   sim_fpu_status status;
136 
137   sim_fpu_32to (&op1, x);
138   status = sim_fpu_sqrt (&ans, &op1);
139   if (status != 0)
140     (*fpu->ops->error) (fpu, status);
141   sim_fpu_to32 (&res, &ans);
142 
143   return res;
144 }
145 
146 static SF
invsf(CGEN_FPU * fpu,SF x)147 invsf (CGEN_FPU* fpu, SF x)
148 {
149   sim_fpu op1;
150   sim_fpu ans;
151   unsigned32 res;
152   sim_fpu_status status;
153 
154   sim_fpu_32to (&op1, x);
155   status = sim_fpu_inv (&ans, &op1);
156   if (status != 0)
157     (*fpu->ops->error) (fpu, status);
158   sim_fpu_to32 (&res, &ans);
159 
160   return res;
161 }
162 
163 static SF
minsf(CGEN_FPU * fpu,SF x,SF y)164 minsf (CGEN_FPU* fpu, SF x, SF y)
165 {
166   sim_fpu op1;
167   sim_fpu op2;
168   sim_fpu ans;
169   unsigned32 res;
170   sim_fpu_status status;
171 
172   sim_fpu_32to (&op1, x);
173   sim_fpu_32to (&op2, y);
174   status = sim_fpu_min (&ans, &op1, &op2);
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
maxsf(CGEN_FPU * fpu,SF x,SF y)183 maxsf (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_max (&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 CGEN_FP_CMP
cmpsf(CGEN_FPU * fpu,SF x,SF y)202 cmpsf (CGEN_FPU* fpu, SF x, SF y)
203 {
204   sim_fpu op1;
205   sim_fpu op2;
206 
207   sim_fpu_32to (&op1, x);
208   sim_fpu_32to (&op2, y);
209 
210   if (sim_fpu_is_nan (&op1)
211       || sim_fpu_is_nan (&op2))
212     return FP_CMP_NAN;
213 
214   if (x < y)
215     return FP_CMP_LT;
216   if (x > y)
217     return FP_CMP_GT;
218   return FP_CMP_EQ;
219 }
220 
221 static int
eqsf(CGEN_FPU * fpu,SF x,SF y)222 eqsf (CGEN_FPU* fpu, SF x, SF y)
223 {
224   sim_fpu op1;
225   sim_fpu op2;
226 
227   sim_fpu_32to (&op1, x);
228   sim_fpu_32to (&op2, y);
229   return sim_fpu_is_eq (&op1, &op2);
230 }
231 
232 static int
nesf(CGEN_FPU * fpu,SF x,SF y)233 nesf (CGEN_FPU* fpu, SF x, SF y)
234 {
235   sim_fpu op1;
236   sim_fpu op2;
237 
238   sim_fpu_32to (&op1, x);
239   sim_fpu_32to (&op2, y);
240   return sim_fpu_is_ne (&op1, &op2);
241 }
242 
243 static int
ltsf(CGEN_FPU * fpu,SF x,SF y)244 ltsf (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_lt (&op1, &op2);
252 }
253 
254 static int
lesf(CGEN_FPU * fpu,SF x,SF y)255 lesf (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_le (&op1, &op2);
263 }
264 
265 static int
gtsf(CGEN_FPU * fpu,SF x,SF y)266 gtsf (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_gt (&op1, &op2);
274 }
275 
276 static int
gesf(CGEN_FPU * fpu,SF x,SF y)277 gesf (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_ge (&op1, &op2);
285 }
286 
287 static DF
fextsfdf(CGEN_FPU * fpu,int how UNUSED,SF x)288 fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x)
289 {
290   sim_fpu op1;
291   unsigned64 res;
292 
293   sim_fpu_32to (&op1, x);
294   sim_fpu_to64 (&res, &op1);
295 
296   return res;
297 }
298 
299 static SF
ftruncdfsf(CGEN_FPU * fpu,int how UNUSED,DF x)300 ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x)
301 {
302   sim_fpu op1;
303   unsigned32 res;
304 
305   sim_fpu_64to (&op1, x);
306   sim_fpu_to32 (&res, &op1);
307 
308   return res;
309 }
310 
311 static SF
floatsisf(CGEN_FPU * fpu,int how UNUSED,SI x)312 floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x)
313 {
314   sim_fpu ans;
315   unsigned32 res;
316 
317   sim_fpu_i32to (&ans, x, sim_fpu_round_near);
318   sim_fpu_to32 (&res, &ans);
319   return res;
320 }
321 
322 static DF
floatsidf(CGEN_FPU * fpu,int how UNUSED,SI x)323 floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x)
324 {
325   sim_fpu ans;
326   unsigned64 res;
327 
328   sim_fpu_i32to (&ans, x, sim_fpu_round_near);
329   sim_fpu_to64 (&res, &ans);
330   return res;
331 }
332 
333 static SF
ufloatsisf(CGEN_FPU * fpu,int how UNUSED,USI x)334 ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x)
335 {
336   sim_fpu ans;
337   unsigned32 res;
338 
339   sim_fpu_u32to (&ans, x, sim_fpu_round_near);
340   sim_fpu_to32 (&res, &ans);
341   return res;
342 }
343 
344 static SI
fixsfsi(CGEN_FPU * fpu,int how UNUSED,SF x)345 fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
346 {
347   sim_fpu op1;
348   unsigned32 res;
349 
350   sim_fpu_32to (&op1, x);
351   sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
352   return res;
353 }
354 
355 static SI
fixdfsi(CGEN_FPU * fpu,int how UNUSED,DF x)356 fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x)
357 {
358   sim_fpu op1;
359   unsigned32 res;
360 
361   sim_fpu_64to (&op1, x);
362   sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
363   return res;
364 }
365 
366 static USI
ufixsfsi(CGEN_FPU * fpu,int how UNUSED,SF x)367 ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
368 {
369   sim_fpu op1;
370   unsigned32 res;
371 
372   sim_fpu_32to (&op1, x);
373   sim_fpu_to32u (&res, &op1, sim_fpu_round_near);
374   return res;
375 }
376 
377 /* DF mode support */
378 
379 static DF
adddf(CGEN_FPU * fpu,DF x,DF y)380 adddf (CGEN_FPU* fpu, DF x, DF y)
381 {
382   sim_fpu op1;
383   sim_fpu op2;
384   sim_fpu ans;
385   unsigned64 res;
386   sim_fpu_status status;
387 
388   sim_fpu_64to (&op1, x);
389   sim_fpu_64to (&op2, y);
390   status = sim_fpu_add (&ans, &op1, &op2);
391   if (status != 0)
392     (*fpu->ops->error) (fpu, status);
393   sim_fpu_to64 (&res, &ans);
394 
395   return res;
396 }
397 
398 static DF
subdf(CGEN_FPU * fpu,DF x,DF y)399 subdf (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_sub (&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
muldf(CGEN_FPU * fpu,DF x,DF y)418 muldf (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_mul (&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
divdf(CGEN_FPU * fpu,DF x,DF y)437 divdf (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_div (&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
negdf(CGEN_FPU * fpu,DF x)456 negdf (CGEN_FPU* fpu, DF x)
457 {
458   sim_fpu op1;
459   sim_fpu ans;
460   unsigned64 res;
461   sim_fpu_status status;
462 
463   sim_fpu_64to (&op1, x);
464   status = sim_fpu_neg (&ans, &op1);
465   if (status != 0)
466     (*fpu->ops->error) (fpu, status);
467   sim_fpu_to64 (&res, &ans);
468 
469   return res;
470 }
471 
472 static DF
absdf(CGEN_FPU * fpu,DF x)473 absdf (CGEN_FPU* fpu, DF x)
474 {
475   sim_fpu op1;
476   sim_fpu ans;
477   unsigned64 res;
478   sim_fpu_status status;
479 
480   sim_fpu_64to (&op1, x);
481   status = sim_fpu_abs (&ans, &op1);
482   if (status != 0)
483     (*fpu->ops->error) (fpu, status);
484   sim_fpu_to64 (&res, &ans);
485 
486   return res;
487 }
488 
489 static DF
sqrtdf(CGEN_FPU * fpu,DF x)490 sqrtdf (CGEN_FPU* fpu, DF x)
491 {
492   sim_fpu op1;
493   sim_fpu ans;
494   unsigned64 res;
495   sim_fpu_status status;
496 
497   sim_fpu_64to (&op1, x);
498   status = sim_fpu_sqrt (&ans, &op1);
499   if (status != 0)
500     (*fpu->ops->error) (fpu, status);
501   sim_fpu_to64 (&res, &ans);
502 
503   return res;
504 }
505 
506 static DF
invdf(CGEN_FPU * fpu,DF x)507 invdf (CGEN_FPU* fpu, DF x)
508 {
509   sim_fpu op1;
510   sim_fpu ans;
511   unsigned64 res;
512   sim_fpu_status status;
513 
514   sim_fpu_64to (&op1, x);
515   status = sim_fpu_inv (&ans, &op1);
516   if (status != 0)
517     (*fpu->ops->error) (fpu, status);
518   sim_fpu_to64 (&res, &ans);
519 
520   return res;
521 }
522 
523 static DF
mindf(CGEN_FPU * fpu,DF x,DF y)524 mindf (CGEN_FPU* fpu, DF x, DF y)
525 {
526   sim_fpu op1;
527   sim_fpu op2;
528   sim_fpu ans;
529   unsigned64 res;
530   sim_fpu_status status;
531 
532   sim_fpu_64to (&op1, x);
533   sim_fpu_64to (&op2, y);
534   status = sim_fpu_min (&ans, &op1, &op2);
535   if (status != 0)
536     (*fpu->ops->error) (fpu, status);
537   sim_fpu_to64 (&res, &ans);
538 
539   return res;
540 }
541 
542 static DF
maxdf(CGEN_FPU * fpu,DF x,DF y)543 maxdf (CGEN_FPU* fpu, DF x, DF y)
544 {
545   sim_fpu op1;
546   sim_fpu op2;
547   sim_fpu ans;
548   unsigned64 res;
549   sim_fpu_status status;
550 
551   sim_fpu_64to (&op1, x);
552   sim_fpu_64to (&op2, y);
553   status = sim_fpu_max (&ans, &op1, &op2);
554   if (status != 0)
555     (*fpu->ops->error) (fpu, status);
556   sim_fpu_to64 (&res, &ans);
557 
558   return res;
559 }
560 
561 static CGEN_FP_CMP
cmpdf(CGEN_FPU * fpu,DF x,DF y)562 cmpdf (CGEN_FPU* fpu, DF x, DF y)
563 {
564   sim_fpu op1;
565   sim_fpu op2;
566 
567   sim_fpu_64to (&op1, x);
568   sim_fpu_64to (&op2, y);
569 
570   if (sim_fpu_is_nan (&op1)
571       || sim_fpu_is_nan (&op2))
572     return FP_CMP_NAN;
573 
574   if (x < y)
575     return FP_CMP_LT;
576   if (x > y)
577     return FP_CMP_GT;
578   return FP_CMP_EQ;
579 }
580 
581 static int
eqdf(CGEN_FPU * fpu,DF x,DF y)582 eqdf (CGEN_FPU* fpu, DF x, DF y)
583 {
584   sim_fpu op1;
585   sim_fpu op2;
586 
587   sim_fpu_64to (&op1, x);
588   sim_fpu_64to (&op2, y);
589   return sim_fpu_is_eq (&op1, &op2);
590 }
591 
592 static int
nedf(CGEN_FPU * fpu,DF x,DF y)593 nedf (CGEN_FPU* fpu, DF x, DF y)
594 {
595   sim_fpu op1;
596   sim_fpu op2;
597 
598   sim_fpu_64to (&op1, x);
599   sim_fpu_64to (&op2, y);
600   return sim_fpu_is_ne (&op1, &op2);
601 }
602 
603 static int
ltdf(CGEN_FPU * fpu,DF x,DF y)604 ltdf (CGEN_FPU* fpu, DF x, DF y)
605 {
606   sim_fpu op1;
607   sim_fpu op2;
608 
609   sim_fpu_64to (&op1, x);
610   sim_fpu_64to (&op2, y);
611   return sim_fpu_is_lt (&op1, &op2);
612 }
613 
614 static int
ledf(CGEN_FPU * fpu,DF x,DF y)615 ledf (CGEN_FPU* fpu, DF x, DF y)
616 {
617   sim_fpu op1;
618   sim_fpu op2;
619 
620   sim_fpu_64to (&op1, x);
621   sim_fpu_64to (&op2, y);
622   return sim_fpu_is_le (&op1, &op2);
623 }
624 
625 static int
gtdf(CGEN_FPU * fpu,DF x,DF y)626 gtdf (CGEN_FPU* fpu, DF x, DF y)
627 {
628   sim_fpu op1;
629   sim_fpu op2;
630 
631   sim_fpu_64to (&op1, x);
632   sim_fpu_64to (&op2, y);
633   return sim_fpu_is_gt (&op1, &op2);
634 }
635 
636 static int
gedf(CGEN_FPU * fpu,DF x,DF y)637 gedf (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   return sim_fpu_is_ge (&op1, &op2);
645 }
646 
647 /* Initialize FP_OPS to use accurate library.  */
648 
649 void
cgen_init_accurate_fpu(SIM_CPU * cpu,CGEN_FPU * fpu,CGEN_FPU_ERROR_FN * error)650 cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
651 {
652   CGEN_FP_OPS* o;
653 
654   fpu->owner = cpu;
655   /* ??? small memory leak, not freed by sim_close */
656   fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS));
657 
658   o = fpu->ops;
659   memset (o, 0, sizeof (*o));
660 
661   o->error = error;
662 
663   o->addsf = addsf;
664   o->subsf = subsf;
665   o->mulsf = mulsf;
666   o->divsf = divsf;
667   o->negsf = negsf;
668   o->abssf = abssf;
669   o->sqrtsf = sqrtsf;
670   o->invsf = invsf;
671   o->minsf = minsf;
672   o->maxsf = maxsf;
673   o->cmpsf = cmpsf;
674   o->eqsf = eqsf;
675   o->nesf = nesf;
676   o->ltsf = ltsf;
677   o->lesf = lesf;
678   o->gtsf = gtsf;
679   o->gesf = gesf;
680 
681   o->adddf = adddf;
682   o->subdf = subdf;
683   o->muldf = muldf;
684   o->divdf = divdf;
685   o->negdf = negdf;
686   o->absdf = absdf;
687   o->sqrtdf = sqrtdf;
688   o->invdf = invdf;
689   o->mindf = mindf;
690   o->maxdf = maxdf;
691   o->cmpdf = cmpdf;
692   o->eqdf = eqdf;
693   o->nedf = nedf;
694   o->ltdf = ltdf;
695   o->ledf = ledf;
696   o->gtdf = gtdf;
697   o->gedf = gedf;
698   o->fextsfdf = fextsfdf;
699   o->ftruncdfsf = ftruncdfsf;
700   o->floatsisf = floatsisf;
701   o->floatsidf = floatsidf;
702   o->ufloatsisf = ufloatsisf;
703   o->fixsfsi = fixsfsi;
704   o->fixdfsi = fixdfsi;
705   o->ufixsfsi = ufixsfsi;
706 }
707