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