import gdb-1999-12-06 snapshot
[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 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
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
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
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
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
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
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
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
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
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
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
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
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 SF
288 floatsisf (CGEN_FPU* fpu, SI x)
289 {
290   sim_fpu ans;
291   unsigned32 res;
292
293   sim_fpu_i32to (&ans, x, sim_fpu_round_near);
294   sim_fpu_to32 (&res, &ans);
295   return res;
296 }
297
298 static DF
299 floatsidf (CGEN_FPU* fpu, SI x)
300 {
301   sim_fpu ans;
302   unsigned64 res;
303
304   sim_fpu_i32to (&ans, x, sim_fpu_round_near);
305   sim_fpu_to64 (&res, &ans);
306   return res;
307 }
308
309 static SF
310 ufloatsisf (CGEN_FPU* fpu, USI x)
311 {
312   sim_fpu ans;
313   unsigned32 res;
314
315   sim_fpu_u32to (&ans, x, sim_fpu_round_near);
316   sim_fpu_to32 (&res, &ans);
317   return res;
318 }
319
320 static SI
321 fixsfsi (CGEN_FPU* fpu, SF x)
322 {
323   sim_fpu op1;
324   unsigned32 res;
325
326   sim_fpu_32to (&op1, x);
327   sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
328   return res;
329 }
330
331 static SI
332 fixdfsi (CGEN_FPU* fpu, DF x)
333 {
334   sim_fpu op1;
335   unsigned32 res;
336
337   sim_fpu_64to (&op1, x);
338   sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
339   return res;
340 }
341
342 static USI
343 ufixsfsi (CGEN_FPU* fpu, SF x)
344 {
345   sim_fpu op1;
346   unsigned32 res;
347
348   sim_fpu_32to (&op1, x);
349   sim_fpu_to32u (&res, &op1, sim_fpu_round_near);
350   return res;
351 }
352 \f
353 /* DF mode support */
354
355 static DF
356 adddf (CGEN_FPU* fpu, DF x, DF y)
357 {
358   sim_fpu op1;
359   sim_fpu op2;
360   sim_fpu ans;
361   unsigned64 res;
362   sim_fpu_status status;
363
364   sim_fpu_64to (&op1, x);
365   sim_fpu_64to (&op2, y);
366   status = sim_fpu_add (&ans, &op1, &op2);
367   if (status != 0)
368     (*fpu->ops->error) (fpu, status);
369   sim_fpu_to64 (&res, &ans);
370
371   return res;
372 }
373
374 static DF
375 subdf (CGEN_FPU* fpu, DF x, DF y)
376 {
377   sim_fpu op1;
378   sim_fpu op2;
379   sim_fpu ans;
380   unsigned64 res;
381   sim_fpu_status status;
382
383   sim_fpu_64to (&op1, x);
384   sim_fpu_64to (&op2, y);
385   status = sim_fpu_sub (&ans, &op1, &op2);
386   if (status != 0)
387     (*fpu->ops->error) (fpu, status);
388   sim_fpu_to64 (&res, &ans);
389
390   return res;
391 }
392
393 static DF
394 muldf (CGEN_FPU* fpu, DF x, DF y)
395 {
396   sim_fpu op1;
397   sim_fpu op2;
398   sim_fpu ans;
399   unsigned64 res;
400   sim_fpu_status status;
401
402   sim_fpu_64to (&op1, x);
403   sim_fpu_64to (&op2, y);
404   status = sim_fpu_mul (&ans, &op1, &op2);
405   if (status != 0)
406     (*fpu->ops->error) (fpu, status);
407   sim_fpu_to64 (&res, &ans);
408
409   return res;
410 }
411
412 static DF
413 divdf (CGEN_FPU* fpu, DF x, DF y)
414 {
415   sim_fpu op1;
416   sim_fpu op2;
417   sim_fpu ans;
418   unsigned64 res;
419   sim_fpu_status status;
420
421   sim_fpu_64to (&op1, x);
422   sim_fpu_64to (&op2, y);
423   status = sim_fpu_div (&ans, &op1, &op2);
424   if (status != 0)
425     (*fpu->ops->error) (fpu, status);
426   sim_fpu_to64 (&res, &ans);
427
428   return res;
429 }
430
431 static DF
432 negdf (CGEN_FPU* fpu, DF x)
433 {
434   sim_fpu op1;
435   sim_fpu ans;
436   unsigned64 res;
437   sim_fpu_status status;
438
439   sim_fpu_64to (&op1, x);
440   status = sim_fpu_neg (&ans, &op1);
441   if (status != 0)
442     (*fpu->ops->error) (fpu, status);
443   sim_fpu_to64 (&res, &ans);
444
445   return res;
446 }
447
448 static DF
449 absdf (CGEN_FPU* fpu, DF x)
450 {
451   sim_fpu op1;
452   sim_fpu ans;
453   unsigned64 res;
454   sim_fpu_status status;
455
456   sim_fpu_64to (&op1, x);
457   status = sim_fpu_abs (&ans, &op1);
458   if (status != 0)
459     (*fpu->ops->error) (fpu, status);
460   sim_fpu_to64 (&res, &ans);
461
462   return res;
463 }
464
465 static DF
466 sqrtdf (CGEN_FPU* fpu, DF x)
467 {
468   sim_fpu op1;
469   sim_fpu ans;
470   unsigned64 res;
471   sim_fpu_status status;
472
473   sim_fpu_64to (&op1, x);
474   status = sim_fpu_sqrt (&ans, &op1);
475   if (status != 0)
476     (*fpu->ops->error) (fpu, status);
477   sim_fpu_to64 (&res, &ans);
478
479   return res;
480 }
481
482 static DF
483 invdf (CGEN_FPU* fpu, DF x)
484 {
485   sim_fpu op1;
486   sim_fpu ans;
487   unsigned64 res;
488   sim_fpu_status status;
489
490   sim_fpu_64to (&op1, x);
491   status = sim_fpu_inv (&ans, &op1);
492   if (status != 0)
493     (*fpu->ops->error) (fpu, status);
494   sim_fpu_to64 (&res, &ans);
495
496   return res;
497 }
498
499 static DF
500 mindf (CGEN_FPU* fpu, DF x, DF y)
501 {
502   sim_fpu op1;
503   sim_fpu op2;
504   sim_fpu ans;
505   unsigned64 res;
506   sim_fpu_status status;
507
508   sim_fpu_64to (&op1, x);
509   sim_fpu_64to (&op2, y);
510   status = sim_fpu_min (&ans, &op1, &op2);
511   if (status != 0)
512     (*fpu->ops->error) (fpu, status);
513   sim_fpu_to64 (&res, &ans);
514
515   return res;
516 }
517
518 static DF
519 maxdf (CGEN_FPU* fpu, DF x, DF y)
520 {
521   sim_fpu op1;
522   sim_fpu op2;
523   sim_fpu ans;
524   unsigned64 res;
525   sim_fpu_status status;
526
527   sim_fpu_64to (&op1, x);
528   sim_fpu_64to (&op2, y);
529   status = sim_fpu_max (&ans, &op1, &op2);
530   if (status != 0)
531     (*fpu->ops->error) (fpu, status);
532   sim_fpu_to64 (&res, &ans);
533
534   return res;
535 }
536
537 static CGEN_FP_CMP
538 cmpdf (CGEN_FPU* fpu, DF x, DF y)
539 {
540   sim_fpu op1;
541   sim_fpu op2;
542
543   sim_fpu_64to (&op1, x);
544   sim_fpu_64to (&op2, y);
545
546   if (sim_fpu_is_nan (&op1)
547       || sim_fpu_is_nan (&op2))
548     return FP_CMP_NAN;
549
550   if (x < y)
551     return FP_CMP_LT;
552   if (x > y)
553     return FP_CMP_GT;
554   return FP_CMP_EQ;
555 }
556
557 static int
558 eqdf (CGEN_FPU* fpu, DF x, DF y)
559 {
560   sim_fpu op1;
561   sim_fpu op2;
562
563   sim_fpu_64to (&op1, x);
564   sim_fpu_64to (&op2, y);
565   return sim_fpu_is_eq (&op1, &op2);
566 }
567
568 static int
569 nedf (CGEN_FPU* fpu, DF x, DF y)
570 {
571   sim_fpu op1;
572   sim_fpu op2;
573
574   sim_fpu_64to (&op1, x);
575   sim_fpu_64to (&op2, y);
576   return sim_fpu_is_ne (&op1, &op2);
577 }
578
579 static int
580 ltdf (CGEN_FPU* fpu, DF x, DF y)
581 {
582   sim_fpu op1;
583   sim_fpu op2;
584
585   sim_fpu_64to (&op1, x);
586   sim_fpu_64to (&op2, y);
587   return sim_fpu_is_lt (&op1, &op2);
588 }
589
590 static int
591 ledf (CGEN_FPU* fpu, DF x, DF y)
592 {
593   sim_fpu op1;
594   sim_fpu op2;
595
596   sim_fpu_64to (&op1, x);
597   sim_fpu_64to (&op2, y);
598   return sim_fpu_is_le (&op1, &op2);
599 }
600
601 static int
602 gtdf (CGEN_FPU* fpu, DF x, DF y)
603 {
604   sim_fpu op1;
605   sim_fpu op2;
606
607   sim_fpu_64to (&op1, x);
608   sim_fpu_64to (&op2, y);
609   return sim_fpu_is_gt (&op1, &op2);
610 }
611
612 static int
613 gedf (CGEN_FPU* fpu, DF x, DF y)
614 {
615   sim_fpu op1;
616   sim_fpu op2;
617
618   sim_fpu_64to (&op1, x);
619   sim_fpu_64to (&op2, y);
620   return sim_fpu_is_ge (&op1, &op2);
621 }
622 \f
623 /* Initialize FP_OPS to use accurate library.  */
624
625 void
626 cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
627 {
628   CGEN_FP_OPS* o;
629
630   fpu->owner = cpu;
631   /* ??? small memory leak, not freed by sim_close */
632   fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS));
633
634   o = fpu->ops;
635   memset (o, 0, sizeof (*o));
636
637   o->error = error;
638
639   o->addsf = addsf;
640   o->subsf = subsf;
641   o->mulsf = mulsf;
642   o->divsf = divsf;
643   o->negsf = negsf;
644   o->abssf = abssf;
645   o->sqrtsf = sqrtsf;
646   o->invsf = invsf;
647   o->minsf = minsf;
648   o->maxsf = maxsf;
649   o->cmpsf = cmpsf;
650   o->eqsf = eqsf;
651   o->nesf = nesf;
652   o->ltsf = ltsf;
653   o->lesf = lesf;
654   o->gtsf = gtsf;
655   o->gesf = gesf;
656
657   o->adddf = adddf;
658   o->subdf = subdf;
659   o->muldf = muldf;
660   o->divdf = divdf;
661   o->negdf = negdf;
662   o->absdf = absdf;
663   o->sqrtdf = sqrtdf;
664   o->invdf = invdf;
665   o->mindf = mindf;
666   o->maxdf = maxdf;
667   o->cmpdf = cmpdf;
668   o->eqdf = eqdf;
669   o->nedf = nedf;
670   o->ltdf = ltdf;
671   o->ledf = ledf;
672   o->gtdf = gtdf;
673   o->gedf = gedf;
674   o->floatsisf = floatsisf;
675   o->floatsidf = floatsidf;
676   o->ufloatsisf = ufloatsisf;
677   o->fixsfsi = fixsfsi;
678   o->fixdfsi = fixdfsi;
679   o->ufixsfsi = ufixsfsi;
680 }