1 /* Accurate fp support for CGEN-based simulators.
2 Copyright (C) 1999 Cygnus Solutions.
4 This implemention assumes:
9 - lazy encoding/decoding
10 - checking return code (say by callback)
14 /* This must come before any other includes. */
23 addsf (CGEN_FPU
* fpu
, SF x
, SF y
)
29 sim_fpu_status status
;
31 sim_fpu_32to (&op1
, x
);
32 sim_fpu_32to (&op2
, y
);
33 status
= sim_fpu_add (&ans
, &op1
, &op2
);
35 (*fpu
->ops
->error
) (fpu
, status
);
36 sim_fpu_to32 (&res
, &ans
);
42 subsf (CGEN_FPU
* fpu
, SF x
, SF y
)
48 sim_fpu_status status
;
50 sim_fpu_32to (&op1
, x
);
51 sim_fpu_32to (&op2
, y
);
52 status
= sim_fpu_sub (&ans
, &op1
, &op2
);
54 (*fpu
->ops
->error
) (fpu
, status
);
55 sim_fpu_to32 (&res
, &ans
);
61 mulsf (CGEN_FPU
* fpu
, SF x
, SF y
)
67 sim_fpu_status status
;
69 sim_fpu_32to (&op1
, x
);
70 sim_fpu_32to (&op2
, y
);
71 status
= sim_fpu_mul (&ans
, &op1
, &op2
);
73 (*fpu
->ops
->error
) (fpu
, status
);
74 sim_fpu_to32 (&res
, &ans
);
80 divsf (CGEN_FPU
* fpu
, SF x
, SF y
)
86 sim_fpu_status status
;
88 sim_fpu_32to (&op1
, x
);
89 sim_fpu_32to (&op2
, y
);
90 status
= sim_fpu_div (&ans
, &op1
, &op2
);
92 (*fpu
->ops
->error
) (fpu
, status
);
93 sim_fpu_to32 (&res
, &ans
);
99 remsf (CGEN_FPU
* fpu
, SF x
, SF y
)
105 sim_fpu_status status
;
107 sim_fpu_32to (&op1
, x
);
108 sim_fpu_32to (&op2
, y
);
109 status
= sim_fpu_rem (&ans
, &op1
, &op2
);
111 (*fpu
->ops
->error
) (fpu
, status
);
112 sim_fpu_to32 (&res
, &ans
);
118 negsf (CGEN_FPU
* fpu
, SF x
)
123 sim_fpu_status status
;
125 sim_fpu_32to (&op1
, x
);
126 status
= sim_fpu_neg (&ans
, &op1
);
128 (*fpu
->ops
->error
) (fpu
, status
);
129 sim_fpu_to32 (&res
, &ans
);
135 abssf (CGEN_FPU
* fpu
, SF x
)
140 sim_fpu_status status
;
142 sim_fpu_32to (&op1
, x
);
143 status
= sim_fpu_abs (&ans
, &op1
);
145 (*fpu
->ops
->error
) (fpu
, status
);
146 sim_fpu_to32 (&res
, &ans
);
152 sqrtsf (CGEN_FPU
* fpu
, SF x
)
157 sim_fpu_status status
;
159 sim_fpu_32to (&op1
, x
);
160 status
= sim_fpu_sqrt (&ans
, &op1
);
162 (*fpu
->ops
->error
) (fpu
, status
);
163 sim_fpu_to32 (&res
, &ans
);
169 invsf (CGEN_FPU
* fpu
, SF x
)
174 sim_fpu_status status
;
176 sim_fpu_32to (&op1
, x
);
177 status
= sim_fpu_inv (&ans
, &op1
);
179 (*fpu
->ops
->error
) (fpu
, status
);
180 sim_fpu_to32 (&res
, &ans
);
186 minsf (CGEN_FPU
* fpu
, SF x
, SF y
)
192 sim_fpu_status status
;
194 sim_fpu_32to (&op1
, x
);
195 sim_fpu_32to (&op2
, y
);
196 status
= sim_fpu_min (&ans
, &op1
, &op2
);
198 (*fpu
->ops
->error
) (fpu
, status
);
199 sim_fpu_to32 (&res
, &ans
);
205 maxsf (CGEN_FPU
* fpu
, SF x
, SF y
)
211 sim_fpu_status status
;
213 sim_fpu_32to (&op1
, x
);
214 sim_fpu_32to (&op2
, y
);
215 status
= sim_fpu_max (&ans
, &op1
, &op2
);
217 (*fpu
->ops
->error
) (fpu
, status
);
218 sim_fpu_to32 (&res
, &ans
);
224 cmpsf (CGEN_FPU
* fpu
, SF x
, SF y
)
229 sim_fpu_32to (&op1
, x
);
230 sim_fpu_32to (&op2
, y
);
232 if (sim_fpu_is_nan (&op1
)
233 || sim_fpu_is_nan (&op2
))
244 eqsf (CGEN_FPU
* fpu
, SF x
, SF y
)
249 sim_fpu_32to (&op1
, x
);
250 sim_fpu_32to (&op2
, y
);
251 return sim_fpu_is_eq (&op1
, &op2
);
255 nesf (CGEN_FPU
* fpu
, SF x
, SF y
)
260 sim_fpu_32to (&op1
, x
);
261 sim_fpu_32to (&op2
, y
);
262 return sim_fpu_is_ne (&op1
, &op2
);
266 ltsf (CGEN_FPU
* fpu
, SF x
, SF y
)
271 sim_fpu_32to (&op1
, x
);
272 sim_fpu_32to (&op2
, y
);
273 return sim_fpu_is_lt (&op1
, &op2
);
277 lesf (CGEN_FPU
* fpu
, SF x
, SF y
)
282 sim_fpu_32to (&op1
, x
);
283 sim_fpu_32to (&op2
, y
);
284 return sim_fpu_is_le (&op1
, &op2
);
288 gtsf (CGEN_FPU
* fpu
, SF x
, SF y
)
293 sim_fpu_32to (&op1
, x
);
294 sim_fpu_32to (&op2
, y
);
295 return sim_fpu_is_gt (&op1
, &op2
);
299 gesf (CGEN_FPU
* fpu
, SF x
, SF y
)
304 sim_fpu_32to (&op1
, x
);
305 sim_fpu_32to (&op2
, y
);
306 return sim_fpu_is_ge (&op1
, &op2
);
310 unorderedsf (CGEN_FPU
* fpu
, SF x
, SF y
)
315 sim_fpu_32to (&op1
, x
);
316 sim_fpu_32to (&op2
, y
);
317 return sim_fpu_is_nan (&op1
) || sim_fpu_is_nan (&op2
);
322 fextsfdf (CGEN_FPU
* fpu
, int how UNUSED
, SF x
)
327 sim_fpu_32to (&op1
, x
);
328 sim_fpu_to64 (&res
, &op1
);
334 ftruncdfsf (CGEN_FPU
* fpu
, int how UNUSED
, DF x
)
339 sim_fpu_64to (&op1
, x
);
340 sim_fpu_to32 (&res
, &op1
);
346 floatsisf (CGEN_FPU
* fpu
, int how UNUSED
, SI x
)
351 sim_fpu_i32to (&ans
, x
, sim_fpu_round_near
);
352 sim_fpu_to32 (&res
, &ans
);
357 floatsidf (CGEN_FPU
* fpu
, int how UNUSED
, SI x
)
362 sim_fpu_i32to (&ans
, x
, sim_fpu_round_near
);
363 sim_fpu_to64 (&res
, &ans
);
368 floatdidf (CGEN_FPU
* fpu
, int how UNUSED
, DI x
)
373 sim_fpu_i64to (&ans
, x
, sim_fpu_round_near
);
374 sim_fpu_to64 (&res
, &ans
);
379 ufloatsisf (CGEN_FPU
* fpu
, int how UNUSED
, USI x
)
384 sim_fpu_u32to (&ans
, x
, sim_fpu_round_near
);
385 sim_fpu_to32 (&res
, &ans
);
390 fixsfsi (CGEN_FPU
* fpu
, int how UNUSED
, SF x
)
395 sim_fpu_32to (&op1
, x
);
396 sim_fpu_to32i (&res
, &op1
, sim_fpu_round_near
);
401 fixdfsi (CGEN_FPU
* fpu
, int how UNUSED
, DF x
)
406 sim_fpu_64to (&op1
, x
);
407 sim_fpu_to32i (&res
, &op1
, sim_fpu_round_near
);
412 fixdfdi (CGEN_FPU
* fpu
, int how UNUSED
, DF x
)
417 sim_fpu_64to (&op1
, x
);
418 sim_fpu_to64i (&res
, &op1
, sim_fpu_round_near
);
423 ufixsfsi (CGEN_FPU
* fpu
, int how UNUSED
, SF x
)
428 sim_fpu_32to (&op1
, x
);
429 sim_fpu_to32u (&res
, &op1
, sim_fpu_round_near
);
433 /* DF mode support */
436 adddf (CGEN_FPU
* fpu
, DF x
, DF y
)
442 sim_fpu_status status
;
444 sim_fpu_64to (&op1
, x
);
445 sim_fpu_64to (&op2
, y
);
446 status
= sim_fpu_add (&ans
, &op1
, &op2
);
448 (*fpu
->ops
->error
) (fpu
, status
);
449 sim_fpu_to64 (&res
, &ans
);
455 subdf (CGEN_FPU
* fpu
, DF x
, DF y
)
461 sim_fpu_status status
;
463 sim_fpu_64to (&op1
, x
);
464 sim_fpu_64to (&op2
, y
);
465 status
= sim_fpu_sub (&ans
, &op1
, &op2
);
467 (*fpu
->ops
->error
) (fpu
, status
);
468 sim_fpu_to64 (&res
, &ans
);
474 muldf (CGEN_FPU
* fpu
, DF x
, DF y
)
480 sim_fpu_status status
;
482 sim_fpu_64to (&op1
, x
);
483 sim_fpu_64to (&op2
, y
);
484 status
= sim_fpu_mul (&ans
, &op1
, &op2
);
486 (*fpu
->ops
->error
) (fpu
, status
);
487 sim_fpu_to64 (&res
, &ans
);
493 divdf (CGEN_FPU
* fpu
, DF x
, DF y
)
499 sim_fpu_status status
;
501 sim_fpu_64to (&op1
, x
);
502 sim_fpu_64to (&op2
, y
);
503 status
= sim_fpu_div (&ans
, &op1
, &op2
);
505 (*fpu
->ops
->error
) (fpu
, status
);
506 sim_fpu_to64 (&res
, &ans
);
512 remdf (CGEN_FPU
* fpu
, DF x
, DF y
)
518 sim_fpu_status status
;
520 sim_fpu_64to (&op1
, x
);
521 sim_fpu_64to (&op2
, y
);
522 status
= sim_fpu_rem (&ans
, &op1
, &op2
);
524 (*fpu
->ops
->error
) (fpu
, status
);
525 sim_fpu_to64(&res
, &ans
);
531 negdf (CGEN_FPU
* fpu
, DF x
)
536 sim_fpu_status status
;
538 sim_fpu_64to (&op1
, x
);
539 status
= sim_fpu_neg (&ans
, &op1
);
541 (*fpu
->ops
->error
) (fpu
, status
);
542 sim_fpu_to64 (&res
, &ans
);
548 absdf (CGEN_FPU
* fpu
, DF x
)
553 sim_fpu_status status
;
555 sim_fpu_64to (&op1
, x
);
556 status
= sim_fpu_abs (&ans
, &op1
);
558 (*fpu
->ops
->error
) (fpu
, status
);
559 sim_fpu_to64 (&res
, &ans
);
565 sqrtdf (CGEN_FPU
* fpu
, DF x
)
570 sim_fpu_status status
;
572 sim_fpu_64to (&op1
, x
);
573 status
= sim_fpu_sqrt (&ans
, &op1
);
575 (*fpu
->ops
->error
) (fpu
, status
);
576 sim_fpu_to64 (&res
, &ans
);
582 invdf (CGEN_FPU
* fpu
, DF x
)
587 sim_fpu_status status
;
589 sim_fpu_64to (&op1
, x
);
590 status
= sim_fpu_inv (&ans
, &op1
);
592 (*fpu
->ops
->error
) (fpu
, status
);
593 sim_fpu_to64 (&res
, &ans
);
599 mindf (CGEN_FPU
* fpu
, DF x
, DF y
)
605 sim_fpu_status status
;
607 sim_fpu_64to (&op1
, x
);
608 sim_fpu_64to (&op2
, y
);
609 status
= sim_fpu_min (&ans
, &op1
, &op2
);
611 (*fpu
->ops
->error
) (fpu
, status
);
612 sim_fpu_to64 (&res
, &ans
);
618 maxdf (CGEN_FPU
* fpu
, DF x
, DF y
)
624 sim_fpu_status status
;
626 sim_fpu_64to (&op1
, x
);
627 sim_fpu_64to (&op2
, y
);
628 status
= sim_fpu_max (&ans
, &op1
, &op2
);
630 (*fpu
->ops
->error
) (fpu
, status
);
631 sim_fpu_to64 (&res
, &ans
);
637 cmpdf (CGEN_FPU
* fpu
, DF x
, DF y
)
642 sim_fpu_64to (&op1
, x
);
643 sim_fpu_64to (&op2
, y
);
645 if (sim_fpu_is_nan (&op1
)
646 || sim_fpu_is_nan (&op2
))
657 eqdf (CGEN_FPU
* fpu
, DF x
, DF y
)
662 sim_fpu_64to (&op1
, x
);
663 sim_fpu_64to (&op2
, y
);
664 return sim_fpu_is_eq (&op1
, &op2
);
668 nedf (CGEN_FPU
* fpu
, DF x
, DF y
)
673 sim_fpu_64to (&op1
, x
);
674 sim_fpu_64to (&op2
, y
);
675 return sim_fpu_is_ne (&op1
, &op2
);
679 ltdf (CGEN_FPU
* fpu
, DF x
, DF y
)
684 sim_fpu_64to (&op1
, x
);
685 sim_fpu_64to (&op2
, y
);
686 return sim_fpu_is_lt (&op1
, &op2
);
690 ledf (CGEN_FPU
* fpu
, DF x
, DF y
)
695 sim_fpu_64to (&op1
, x
);
696 sim_fpu_64to (&op2
, y
);
697 return sim_fpu_is_le (&op1
, &op2
);
701 gtdf (CGEN_FPU
* fpu
, DF x
, DF y
)
706 sim_fpu_64to (&op1
, x
);
707 sim_fpu_64to (&op2
, y
);
708 return sim_fpu_is_gt (&op1
, &op2
);
712 gedf (CGEN_FPU
* fpu
, DF x
, DF y
)
717 sim_fpu_64to (&op1
, x
);
718 sim_fpu_64to (&op2
, y
);
719 return sim_fpu_is_ge (&op1
, &op2
);
723 unordereddf (CGEN_FPU
* fpu
, DF x
, DF y
)
728 sim_fpu_64to (&op1
, x
);
729 sim_fpu_64to (&op2
, y
);
730 return sim_fpu_is_nan (&op1
) || sim_fpu_is_nan (&op2
);
733 /* Initialize FP_OPS to use accurate library. */
736 cgen_init_accurate_fpu (SIM_CPU
* cpu
, CGEN_FPU
* fpu
, CGEN_FPU_ERROR_FN
* error
)
741 /* ??? small memory leak, not freed by sim_close */
742 fpu
->ops
= (CGEN_FP_OPS
*) xmalloc (sizeof (CGEN_FP_OPS
));
745 memset (o
, 0, sizeof (*o
));
767 o
->unorderedsf
= unorderedsf
;
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
;