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
22static SF
23addsf (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
41static SF
42subsf (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
60static SF
61mulsf (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
79static SF
80divsf (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
98static SF
99remsf (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
117static SF
118negsf (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
134static SF
135abssf (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
151static SF
152sqrtsf (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
168static SF
169invsf (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
185static SF
186minsf (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
204static SF
205maxsf (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
223static CGEN_FP_CMP
224cmpsf (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
243static int
244eqsf (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
254static int
255nesf (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
265static int
266ltsf (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
276static int
277lesf (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
287static int
288gtsf (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
298static int
299gesf (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
309static int
310unorderedsf (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
321static DF
322fextsfdf (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
333static SF
334ftruncdfsf (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
345static SF
346floatsisf (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
356static DF
357floatsidf (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
367static DF
368floatdidf (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
378static SF
379ufloatsisf (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
389static SI
390fixsfsi (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
400static SI
401fixdfsi (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
411static DI
412fixdfdi (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
422static USI
423ufixsfsi (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
433/* DF mode support */
434
435static DF
436adddf (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
454static DF
455subdf (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
473static DF
474muldf (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
492static DF
493divdf (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
511static DF
512remdf (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
530static DF
531negdf (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
547static DF
548absdf (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
564static DF
565sqrtdf (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
581static DF
582invdf (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
598static DF
599mindf (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
617static DF
618maxdf (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
636static CGEN_FP_CMP
637cmpdf (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
656static int
657eqdf (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
667static int
668nedf (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
678static int
679ltdf (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
689static int
690ledf (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
700static int
701gtdf (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
711static int
712gedf (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
722static int
723unordereddf (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
733/* Initialize FP_OPS to use accurate library.  */
734
735void
736cgen_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}
799