OSDN Git Service

2011-03-11 Michael Snyder <msnyder@vmware.com>
[pf3gnuchains/sourceware.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 DF
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
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
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
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
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
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
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
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 \f
377 /* DF mode support */
378
379 static DF
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 \f
647 /* Initialize FP_OPS to use accurate library.  */
648
649 void
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 }