]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/cgen-accfp.c
sim/common: Wire in df/di conversion
[thirdparty/binutils-gdb.git] / sim / common / cgen-accfp.c
CommitLineData
3535ad49
JM
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
19static SF
20addsf (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
38static SF
39subsf (CGEN_FPU* fpu, SF x, SF y)
40{
41 sim_fpu op1;
42 sim_fpu op2;
43 sim_fpu ans;
44 unsigned32 res;
c2d11a7d 45 sim_fpu_status status;
3535ad49
JM
46
47 sim_fpu_32to (&op1, x);
48 sim_fpu_32to (&op2, y);
c2d11a7d
JM
49 status = sim_fpu_sub (&ans, &op1, &op2);
50 if (status != 0)
51 (*fpu->ops->error) (fpu, status);
3535ad49
JM
52 sim_fpu_to32 (&res, &ans);
53
54 return res;
55}
56
57static SF
58mulsf (CGEN_FPU* fpu, SF x, SF y)
59{
60 sim_fpu op1;
61 sim_fpu op2;
62 sim_fpu ans;
63 unsigned32 res;
c2d11a7d 64 sim_fpu_status status;
3535ad49
JM
65
66 sim_fpu_32to (&op1, x);
67 sim_fpu_32to (&op2, y);
c2d11a7d
JM
68 status = sim_fpu_mul (&ans, &op1, &op2);
69 if (status != 0)
70 (*fpu->ops->error) (fpu, status);
3535ad49
JM
71 sim_fpu_to32 (&res, &ans);
72
73 return res;
74}
75
76static SF
77divsf (CGEN_FPU* fpu, SF x, SF y)
78{
79 sim_fpu op1;
80 sim_fpu op2;
81 sim_fpu ans;
82 unsigned32 res;
917317f4 83 sim_fpu_status status;
3535ad49
JM
84
85 sim_fpu_32to (&op1, x);
86 sim_fpu_32to (&op2, y);
917317f4
JM
87 status = sim_fpu_div (&ans, &op1, &op2);
88 if (status != 0)
89 (*fpu->ops->error) (fpu, status);
3535ad49
JM
90 sim_fpu_to32 (&res, &ans);
91
92 return res;
93}
94
07b95864
PG
95static SF
96remsf (CGEN_FPU* fpu, SF x, SF y)
97{
98 sim_fpu op1;
99 sim_fpu op2;
100 sim_fpu ans;
101 unsigned32 res;
102 sim_fpu_status status;
103
104 sim_fpu_32to (&op1, x);
105 sim_fpu_32to (&op2, y);
106 status = sim_fpu_rem (&ans, &op1, &op2);
107 if (status != 0)
108 (*fpu->ops->error) (fpu, status);
109 sim_fpu_to32 (&res, &ans);
110
111 return res;
112}
113
3535ad49
JM
114static SF
115negsf (CGEN_FPU* fpu, SF x)
116{
117 sim_fpu op1;
118 sim_fpu ans;
119 unsigned32 res;
c2d11a7d 120 sim_fpu_status status;
3535ad49
JM
121
122 sim_fpu_32to (&op1, x);
c2d11a7d
JM
123 status = sim_fpu_neg (&ans, &op1);
124 if (status != 0)
125 (*fpu->ops->error) (fpu, status);
3535ad49
JM
126 sim_fpu_to32 (&res, &ans);
127
128 return res;
129}
130
131static SF
132abssf (CGEN_FPU* fpu, SF x)
133{
134 sim_fpu op1;
135 sim_fpu ans;
136 unsigned32 res;
c2d11a7d 137 sim_fpu_status status;
3535ad49
JM
138
139 sim_fpu_32to (&op1, x);
c2d11a7d
JM
140 status = sim_fpu_abs (&ans, &op1);
141 if (status != 0)
142 (*fpu->ops->error) (fpu, status);
3535ad49
JM
143 sim_fpu_to32 (&res, &ans);
144
145 return res;
146}
147
148static SF
149sqrtsf (CGEN_FPU* fpu, SF x)
150{
151 sim_fpu op1;
152 sim_fpu ans;
153 unsigned32 res;
c2d11a7d 154 sim_fpu_status status;
3535ad49
JM
155
156 sim_fpu_32to (&op1, x);
c2d11a7d
JM
157 status = sim_fpu_sqrt (&ans, &op1);
158 if (status != 0)
159 (*fpu->ops->error) (fpu, status);
3535ad49
JM
160 sim_fpu_to32 (&res, &ans);
161
162 return res;
163}
164
165static SF
166invsf (CGEN_FPU* fpu, SF x)
167{
168 sim_fpu op1;
169 sim_fpu ans;
170 unsigned32 res;
c2d11a7d 171 sim_fpu_status status;
3535ad49
JM
172
173 sim_fpu_32to (&op1, x);
c2d11a7d
JM
174 status = sim_fpu_inv (&ans, &op1);
175 if (status != 0)
176 (*fpu->ops->error) (fpu, status);
3535ad49
JM
177 sim_fpu_to32 (&res, &ans);
178
179 return res;
180}
181
182static SF
183minsf (CGEN_FPU* fpu, SF x, SF y)
184{
185 sim_fpu op1;
186 sim_fpu op2;
187 sim_fpu ans;
188 unsigned32 res;
c2d11a7d 189 sim_fpu_status status;
3535ad49
JM
190
191 sim_fpu_32to (&op1, x);
192 sim_fpu_32to (&op2, y);
c2d11a7d
JM
193 status = sim_fpu_min (&ans, &op1, &op2);
194 if (status != 0)
195 (*fpu->ops->error) (fpu, status);
3535ad49
JM
196 sim_fpu_to32 (&res, &ans);
197
198 return res;
199}
200
201static SF
202maxsf (CGEN_FPU* fpu, SF x, SF y)
203{
204 sim_fpu op1;
205 sim_fpu op2;
206 sim_fpu ans;
207 unsigned32 res;
c2d11a7d 208 sim_fpu_status status;
3535ad49
JM
209
210 sim_fpu_32to (&op1, x);
211 sim_fpu_32to (&op2, y);
c2d11a7d
JM
212 status = sim_fpu_max (&ans, &op1, &op2);
213 if (status != 0)
214 (*fpu->ops->error) (fpu, status);
3535ad49
JM
215 sim_fpu_to32 (&res, &ans);
216
217 return res;
218}
219
220static CGEN_FP_CMP
221cmpsf (CGEN_FPU* fpu, SF x, SF y)
222{
223 sim_fpu op1;
224 sim_fpu op2;
225
226 sim_fpu_32to (&op1, x);
227 sim_fpu_32to (&op2, y);
228
229 if (sim_fpu_is_nan (&op1)
230 || sim_fpu_is_nan (&op2))
231 return FP_CMP_NAN;
232
233 if (x < y)
234 return FP_CMP_LT;
235 if (x > y)
236 return FP_CMP_GT;
237 return FP_CMP_EQ;
238}
239
240static int
241eqsf (CGEN_FPU* fpu, SF x, SF y)
242{
243 sim_fpu op1;
244 sim_fpu op2;
245
246 sim_fpu_32to (&op1, x);
247 sim_fpu_32to (&op2, y);
248 return sim_fpu_is_eq (&op1, &op2);
249}
250
251static int
252nesf (CGEN_FPU* fpu, SF x, SF y)
253{
254 sim_fpu op1;
255 sim_fpu op2;
256
257 sim_fpu_32to (&op1, x);
258 sim_fpu_32to (&op2, y);
259 return sim_fpu_is_ne (&op1, &op2);
260}
261
262static int
263ltsf (CGEN_FPU* fpu, SF x, SF y)
264{
265 sim_fpu op1;
266 sim_fpu op2;
267
268 sim_fpu_32to (&op1, x);
269 sim_fpu_32to (&op2, y);
270 return sim_fpu_is_lt (&op1, &op2);
271}
272
273static int
274lesf (CGEN_FPU* fpu, SF x, SF y)
275{
276 sim_fpu op1;
277 sim_fpu op2;
278
279 sim_fpu_32to (&op1, x);
280 sim_fpu_32to (&op2, y);
281 return sim_fpu_is_le (&op1, &op2);
282}
283
284static int
285gtsf (CGEN_FPU* fpu, SF x, SF y)
286{
287 sim_fpu op1;
288 sim_fpu op2;
289
290 sim_fpu_32to (&op1, x);
291 sim_fpu_32to (&op2, y);
292 return sim_fpu_is_gt (&op1, &op2);
293}
294
295static int
296gesf (CGEN_FPU* fpu, SF x, SF y)
297{
298 sim_fpu op1;
299 sim_fpu op2;
300
301 sim_fpu_32to (&op1, x);
302 sim_fpu_32to (&op2, y);
303 return sim_fpu_is_ge (&op1, &op2);
304}
305
f8603f2f 306static DF
d2c7a1a6 307fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x)
f8603f2f
DB
308{
309 sim_fpu op1;
310 unsigned64 res;
311
312 sim_fpu_32to (&op1, x);
313 sim_fpu_to64 (&res, &op1);
314
315 return res;
316}
317
318static SF
d2c7a1a6 319ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x)
f8603f2f
DB
320{
321 sim_fpu op1;
322 unsigned32 res;
323
324 sim_fpu_64to (&op1, x);
325 sim_fpu_to32 (&res, &op1);
326
327 return res;
328}
329
3535ad49 330static SF
d2c7a1a6 331floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x)
3535ad49
JM
332{
333 sim_fpu ans;
334 unsigned32 res;
335
336 sim_fpu_i32to (&ans, x, sim_fpu_round_near);
337 sim_fpu_to32 (&res, &ans);
338 return res;
339}
340
9846de1b 341static DF
d2c7a1a6 342floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x)
9846de1b
JM
343{
344 sim_fpu ans;
345 unsigned64 res;
346
347 sim_fpu_i32to (&ans, x, sim_fpu_round_near);
348 sim_fpu_to64 (&res, &ans);
349 return res;
350}
351
688cea90
SH
352static DF
353floatdidf (CGEN_FPU* fpu, int how UNUSED, DI x)
354{
355 sim_fpu ans;
356 unsigned64 res;
357
358 sim_fpu_i64to (&ans, x, sim_fpu_round_near);
359 sim_fpu_to64 (&res, &ans);
360 return res;
361}
362
3535ad49 363static SF
d2c7a1a6 364ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x)
3535ad49
JM
365{
366 sim_fpu ans;
367 unsigned32 res;
368
369 sim_fpu_u32to (&ans, x, sim_fpu_round_near);
370 sim_fpu_to32 (&res, &ans);
371 return res;
372}
373
374static SI
d2c7a1a6 375fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
3535ad49
JM
376{
377 sim_fpu op1;
378 unsigned32 res;
379
380 sim_fpu_32to (&op1, x);
381 sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
382 return res;
383}
384
9846de1b 385static SI
d2c7a1a6 386fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x)
9846de1b
JM
387{
388 sim_fpu op1;
389 unsigned32 res;
390
391 sim_fpu_64to (&op1, x);
392 sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
393 return res;
394}
395
688cea90
SH
396static DI
397fixdfdi (CGEN_FPU* fpu, int how UNUSED, DF x)
398{
399 sim_fpu op1;
400 unsigned64 res;
401
402 sim_fpu_64to (&op1, x);
403 sim_fpu_to64i (&res, &op1, sim_fpu_round_near);
404 return res;
405}
406
3535ad49 407static USI
d2c7a1a6 408ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x)
3535ad49
JM
409{
410 sim_fpu op1;
411 unsigned32 res;
412
413 sim_fpu_32to (&op1, x);
414 sim_fpu_to32u (&res, &op1, sim_fpu_round_near);
415 return res;
416}
417\f
418/* DF mode support */
419
420static DF
421adddf (CGEN_FPU* fpu, DF x, DF y)
422{
423 sim_fpu op1;
424 sim_fpu op2;
425 sim_fpu ans;
426 unsigned64 res;
427 sim_fpu_status status;
428
429 sim_fpu_64to (&op1, x);
430 sim_fpu_64to (&op2, y);
431 status = sim_fpu_add (&ans, &op1, &op2);
432 if (status != 0)
433 (*fpu->ops->error) (fpu, status);
434 sim_fpu_to64 (&res, &ans);
435
436 return res;
437}
438
439static DF
440subdf (CGEN_FPU* fpu, DF x, DF y)
441{
442 sim_fpu op1;
443 sim_fpu op2;
444 sim_fpu ans;
445 unsigned64 res;
c2d11a7d 446 sim_fpu_status status;
3535ad49
JM
447
448 sim_fpu_64to (&op1, x);
449 sim_fpu_64to (&op2, y);
c2d11a7d
JM
450 status = sim_fpu_sub (&ans, &op1, &op2);
451 if (status != 0)
452 (*fpu->ops->error) (fpu, status);
3535ad49
JM
453 sim_fpu_to64 (&res, &ans);
454
455 return res;
456}
457
458static DF
459muldf (CGEN_FPU* fpu, DF x, DF y)
460{
461 sim_fpu op1;
462 sim_fpu op2;
463 sim_fpu ans;
464 unsigned64 res;
c2d11a7d 465 sim_fpu_status status;
3535ad49
JM
466
467 sim_fpu_64to (&op1, x);
468 sim_fpu_64to (&op2, y);
c2d11a7d
JM
469 status = sim_fpu_mul (&ans, &op1, &op2);
470 if (status != 0)
471 (*fpu->ops->error) (fpu, status);
3535ad49
JM
472 sim_fpu_to64 (&res, &ans);
473
474 return res;
475}
476
477static DF
478divdf (CGEN_FPU* fpu, DF x, DF y)
479{
480 sim_fpu op1;
481 sim_fpu op2;
482 sim_fpu ans;
483 unsigned64 res;
c2d11a7d 484 sim_fpu_status status;
3535ad49
JM
485
486 sim_fpu_64to (&op1, x);
487 sim_fpu_64to (&op2, y);
c2d11a7d
JM
488 status = sim_fpu_div (&ans, &op1, &op2);
489 if (status != 0)
490 (*fpu->ops->error) (fpu, status);
3535ad49
JM
491 sim_fpu_to64 (&res, &ans);
492
493 return res;
494}
495
07b95864
PG
496static DF
497remdf (CGEN_FPU* fpu, DF x, DF y)
498{
499 sim_fpu op1;
500 sim_fpu op2;
501 sim_fpu ans;
502 unsigned64 res;
503 sim_fpu_status status;
504
505 sim_fpu_64to (&op1, x);
506 sim_fpu_64to (&op2, y);
507 status = sim_fpu_rem (&ans, &op1, &op2);
508 if (status != 0)
509 (*fpu->ops->error) (fpu, status);
510 sim_fpu_to64(&res, &ans);
511
512 return res;
513}
514
3535ad49
JM
515static DF
516negdf (CGEN_FPU* fpu, DF x)
517{
518 sim_fpu op1;
519 sim_fpu ans;
520 unsigned64 res;
c2d11a7d 521 sim_fpu_status status;
3535ad49
JM
522
523 sim_fpu_64to (&op1, x);
c2d11a7d
JM
524 status = sim_fpu_neg (&ans, &op1);
525 if (status != 0)
526 (*fpu->ops->error) (fpu, status);
3535ad49
JM
527 sim_fpu_to64 (&res, &ans);
528
529 return res;
530}
531
532static DF
533absdf (CGEN_FPU* fpu, DF x)
534{
535 sim_fpu op1;
536 sim_fpu ans;
537 unsigned64 res;
c2d11a7d 538 sim_fpu_status status;
3535ad49
JM
539
540 sim_fpu_64to (&op1, x);
c2d11a7d
JM
541 status = sim_fpu_abs (&ans, &op1);
542 if (status != 0)
543 (*fpu->ops->error) (fpu, status);
3535ad49
JM
544 sim_fpu_to64 (&res, &ans);
545
546 return res;
547}
548
549static DF
550sqrtdf (CGEN_FPU* fpu, DF x)
551{
552 sim_fpu op1;
553 sim_fpu ans;
554 unsigned64 res;
c2d11a7d 555 sim_fpu_status status;
3535ad49
JM
556
557 sim_fpu_64to (&op1, x);
c2d11a7d
JM
558 status = sim_fpu_sqrt (&ans, &op1);
559 if (status != 0)
560 (*fpu->ops->error) (fpu, status);
3535ad49
JM
561 sim_fpu_to64 (&res, &ans);
562
563 return res;
564}
565
566static DF
567invdf (CGEN_FPU* fpu, DF x)
568{
569 sim_fpu op1;
570 sim_fpu ans;
571 unsigned64 res;
c2d11a7d 572 sim_fpu_status status;
3535ad49
JM
573
574 sim_fpu_64to (&op1, x);
c2d11a7d
JM
575 status = sim_fpu_inv (&ans, &op1);
576 if (status != 0)
577 (*fpu->ops->error) (fpu, status);
3535ad49
JM
578 sim_fpu_to64 (&res, &ans);
579
580 return res;
581}
582
583static DF
584mindf (CGEN_FPU* fpu, DF x, DF y)
585{
586 sim_fpu op1;
587 sim_fpu op2;
588 sim_fpu ans;
589 unsigned64 res;
c2d11a7d 590 sim_fpu_status status;
3535ad49
JM
591
592 sim_fpu_64to (&op1, x);
593 sim_fpu_64to (&op2, y);
c2d11a7d
JM
594 status = sim_fpu_min (&ans, &op1, &op2);
595 if (status != 0)
596 (*fpu->ops->error) (fpu, status);
3535ad49
JM
597 sim_fpu_to64 (&res, &ans);
598
599 return res;
600}
601
602static DF
603maxdf (CGEN_FPU* fpu, DF x, DF y)
604{
605 sim_fpu op1;
606 sim_fpu op2;
607 sim_fpu ans;
608 unsigned64 res;
c2d11a7d 609 sim_fpu_status status;
3535ad49
JM
610
611 sim_fpu_64to (&op1, x);
612 sim_fpu_64to (&op2, y);
c2d11a7d
JM
613 status = sim_fpu_max (&ans, &op1, &op2);
614 if (status != 0)
615 (*fpu->ops->error) (fpu, status);
3535ad49
JM
616 sim_fpu_to64 (&res, &ans);
617
618 return res;
619}
620
621static CGEN_FP_CMP
622cmpdf (CGEN_FPU* fpu, DF x, DF y)
623{
624 sim_fpu op1;
625 sim_fpu op2;
626
627 sim_fpu_64to (&op1, x);
628 sim_fpu_64to (&op2, y);
629
630 if (sim_fpu_is_nan (&op1)
631 || sim_fpu_is_nan (&op2))
632 return FP_CMP_NAN;
633
634 if (x < y)
635 return FP_CMP_LT;
636 if (x > y)
637 return FP_CMP_GT;
638 return FP_CMP_EQ;
639}
640
641static int
642eqdf (CGEN_FPU* fpu, DF x, DF y)
643{
644 sim_fpu op1;
645 sim_fpu op2;
646
647 sim_fpu_64to (&op1, x);
648 sim_fpu_64to (&op2, y);
649 return sim_fpu_is_eq (&op1, &op2);
650}
651
652static int
653nedf (CGEN_FPU* fpu, DF x, DF y)
654{
655 sim_fpu op1;
656 sim_fpu op2;
657
658 sim_fpu_64to (&op1, x);
659 sim_fpu_64to (&op2, y);
660 return sim_fpu_is_ne (&op1, &op2);
661}
662
663static int
664ltdf (CGEN_FPU* fpu, DF x, DF y)
665{
666 sim_fpu op1;
667 sim_fpu op2;
668
669 sim_fpu_64to (&op1, x);
670 sim_fpu_64to (&op2, y);
671 return sim_fpu_is_lt (&op1, &op2);
672}
673
674static int
675ledf (CGEN_FPU* fpu, DF x, DF y)
676{
677 sim_fpu op1;
678 sim_fpu op2;
679
680 sim_fpu_64to (&op1, x);
681 sim_fpu_64to (&op2, y);
682 return sim_fpu_is_le (&op1, &op2);
683}
684
685static int
686gtdf (CGEN_FPU* fpu, DF x, DF y)
687{
688 sim_fpu op1;
689 sim_fpu op2;
690
691 sim_fpu_64to (&op1, x);
692 sim_fpu_64to (&op2, y);
693 return sim_fpu_is_gt (&op1, &op2);
694}
695
696static int
697gedf (CGEN_FPU* fpu, DF x, DF y)
698{
699 sim_fpu op1;
700 sim_fpu op2;
701
702 sim_fpu_64to (&op1, x);
703 sim_fpu_64to (&op2, y);
704 return sim_fpu_is_ge (&op1, &op2);
705}
706\f
707/* Initialize FP_OPS to use accurate library. */
708
709void
710cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
711{
712 CGEN_FP_OPS* o;
713
714 fpu->owner = cpu;
715 /* ??? small memory leak, not freed by sim_close */
716 fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS));
717
718 o = fpu->ops;
719 memset (o, 0, sizeof (*o));
720
721 o->error = error;
722
723 o->addsf = addsf;
724 o->subsf = subsf;
725 o->mulsf = mulsf;
726 o->divsf = divsf;
07b95864 727 o->remsf = remsf;
3535ad49
JM
728 o->negsf = negsf;
729 o->abssf = abssf;
730 o->sqrtsf = sqrtsf;
731 o->invsf = invsf;
732 o->minsf = minsf;
733 o->maxsf = maxsf;
734 o->cmpsf = cmpsf;
735 o->eqsf = eqsf;
736 o->nesf = nesf;
737 o->ltsf = ltsf;
738 o->lesf = lesf;
739 o->gtsf = gtsf;
740 o->gesf = gesf;
741
742 o->adddf = adddf;
743 o->subdf = subdf;
744 o->muldf = muldf;
745 o->divdf = divdf;
07b95864 746 o->remdf = remdf;
3535ad49
JM
747 o->negdf = negdf;
748 o->absdf = absdf;
749 o->sqrtdf = sqrtdf;
750 o->invdf = invdf;
751 o->mindf = mindf;
752 o->maxdf = maxdf;
753 o->cmpdf = cmpdf;
754 o->eqdf = eqdf;
755 o->nedf = nedf;
756 o->ltdf = ltdf;
757 o->ledf = ledf;
758 o->gtdf = gtdf;
759 o->gedf = gedf;
f8603f2f
DB
760 o->fextsfdf = fextsfdf;
761 o->ftruncdfsf = ftruncdfsf;
3535ad49 762 o->floatsisf = floatsisf;
9846de1b 763 o->floatsidf = floatsidf;
688cea90 764 o->floatdidf = floatdidf;
3535ad49
JM
765 o->ufloatsisf = ufloatsisf;
766 o->fixsfsi = fixsfsi;
9846de1b 767 o->fixdfsi = fixdfsi;
688cea90 768 o->fixdfdi = fixdfdi;
3535ad49
JM
769 o->ufixsfsi = ufixsfsi;
770}