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)
20 addsf (CGEN_FPU
* fpu
, SF x
, SF y
)
26 sim_fpu_status status
;
28 sim_fpu_32to (&op1
, x
);
29 sim_fpu_32to (&op2
, y
);
30 status
= sim_fpu_add (&ans
, &op1
, &op2
);
32 (*fpu
->ops
->error
) (fpu
, status
);
33 sim_fpu_to32 (&res
, &ans
);
39 subsf (CGEN_FPU
* fpu
, SF x
, SF y
)
45 sim_fpu_status status
;
47 sim_fpu_32to (&op1
, x
);
48 sim_fpu_32to (&op2
, y
);
49 status
= sim_fpu_sub (&ans
, &op1
, &op2
);
51 (*fpu
->ops
->error
) (fpu
, status
);
52 sim_fpu_to32 (&res
, &ans
);
58 mulsf (CGEN_FPU
* fpu
, SF x
, SF y
)
64 sim_fpu_status status
;
66 sim_fpu_32to (&op1
, x
);
67 sim_fpu_32to (&op2
, y
);
68 status
= sim_fpu_mul (&ans
, &op1
, &op2
);
70 (*fpu
->ops
->error
) (fpu
, status
);
71 sim_fpu_to32 (&res
, &ans
);
77 divsf (CGEN_FPU
* fpu
, SF x
, SF y
)
83 sim_fpu_status status
;
85 sim_fpu_32to (&op1
, x
);
86 sim_fpu_32to (&op2
, y
);
87 status
= sim_fpu_div (&ans
, &op1
, &op2
);
89 (*fpu
->ops
->error
) (fpu
, status
);
90 sim_fpu_to32 (&res
, &ans
);
96 remsf (CGEN_FPU
* fpu
, SF x
, SF y
)
102 sim_fpu_status status
;
104 sim_fpu_32to (&op1
, x
);
105 sim_fpu_32to (&op2
, y
);
106 status
= sim_fpu_rem (&ans
, &op1
, &op2
);
108 (*fpu
->ops
->error
) (fpu
, status
);
109 sim_fpu_to32 (&res
, &ans
);
115 negsf (CGEN_FPU
* fpu
, SF x
)
120 sim_fpu_status status
;
122 sim_fpu_32to (&op1
, x
);
123 status
= sim_fpu_neg (&ans
, &op1
);
125 (*fpu
->ops
->error
) (fpu
, status
);
126 sim_fpu_to32 (&res
, &ans
);
132 abssf (CGEN_FPU
* fpu
, SF x
)
137 sim_fpu_status status
;
139 sim_fpu_32to (&op1
, x
);
140 status
= sim_fpu_abs (&ans
, &op1
);
142 (*fpu
->ops
->error
) (fpu
, status
);
143 sim_fpu_to32 (&res
, &ans
);
149 sqrtsf (CGEN_FPU
* fpu
, SF x
)
154 sim_fpu_status status
;
156 sim_fpu_32to (&op1
, x
);
157 status
= sim_fpu_sqrt (&ans
, &op1
);
159 (*fpu
->ops
->error
) (fpu
, status
);
160 sim_fpu_to32 (&res
, &ans
);
166 invsf (CGEN_FPU
* fpu
, SF x
)
171 sim_fpu_status status
;
173 sim_fpu_32to (&op1
, x
);
174 status
= sim_fpu_inv (&ans
, &op1
);
176 (*fpu
->ops
->error
) (fpu
, status
);
177 sim_fpu_to32 (&res
, &ans
);
183 minsf (CGEN_FPU
* fpu
, SF x
, SF y
)
189 sim_fpu_status status
;
191 sim_fpu_32to (&op1
, x
);
192 sim_fpu_32to (&op2
, y
);
193 status
= sim_fpu_min (&ans
, &op1
, &op2
);
195 (*fpu
->ops
->error
) (fpu
, status
);
196 sim_fpu_to32 (&res
, &ans
);
202 maxsf (CGEN_FPU
* fpu
, SF x
, SF y
)
208 sim_fpu_status status
;
210 sim_fpu_32to (&op1
, x
);
211 sim_fpu_32to (&op2
, y
);
212 status
= sim_fpu_max (&ans
, &op1
, &op2
);
214 (*fpu
->ops
->error
) (fpu
, status
);
215 sim_fpu_to32 (&res
, &ans
);
221 cmpsf (CGEN_FPU
* fpu
, SF x
, SF y
)
226 sim_fpu_32to (&op1
, x
);
227 sim_fpu_32to (&op2
, y
);
229 if (sim_fpu_is_nan (&op1
)
230 || sim_fpu_is_nan (&op2
))
241 eqsf (CGEN_FPU
* fpu
, SF x
, SF y
)
246 sim_fpu_32to (&op1
, x
);
247 sim_fpu_32to (&op2
, y
);
248 return sim_fpu_is_eq (&op1
, &op2
);
252 nesf (CGEN_FPU
* fpu
, SF x
, SF y
)
257 sim_fpu_32to (&op1
, x
);
258 sim_fpu_32to (&op2
, y
);
259 return sim_fpu_is_ne (&op1
, &op2
);
263 ltsf (CGEN_FPU
* fpu
, SF x
, SF y
)
268 sim_fpu_32to (&op1
, x
);
269 sim_fpu_32to (&op2
, y
);
270 return sim_fpu_is_lt (&op1
, &op2
);
274 lesf (CGEN_FPU
* fpu
, SF x
, SF y
)
279 sim_fpu_32to (&op1
, x
);
280 sim_fpu_32to (&op2
, y
);
281 return sim_fpu_is_le (&op1
, &op2
);
285 gtsf (CGEN_FPU
* fpu
, SF x
, SF y
)
290 sim_fpu_32to (&op1
, x
);
291 sim_fpu_32to (&op2
, y
);
292 return sim_fpu_is_gt (&op1
, &op2
);
296 gesf (CGEN_FPU
* fpu
, SF x
, SF y
)
301 sim_fpu_32to (&op1
, x
);
302 sim_fpu_32to (&op2
, y
);
303 return sim_fpu_is_ge (&op1
, &op2
);
307 fextsfdf (CGEN_FPU
* fpu
, int how UNUSED
, SF x
)
312 sim_fpu_32to (&op1
, x
);
313 sim_fpu_to64 (&res
, &op1
);
319 ftruncdfsf (CGEN_FPU
* fpu
, int how UNUSED
, DF x
)
324 sim_fpu_64to (&op1
, x
);
325 sim_fpu_to32 (&res
, &op1
);
331 floatsisf (CGEN_FPU
* fpu
, int how UNUSED
, SI x
)
336 sim_fpu_i32to (&ans
, x
, sim_fpu_round_near
);
337 sim_fpu_to32 (&res
, &ans
);
342 floatsidf (CGEN_FPU
* fpu
, int how UNUSED
, SI x
)
347 sim_fpu_i32to (&ans
, x
, sim_fpu_round_near
);
348 sim_fpu_to64 (&res
, &ans
);
353 ufloatsisf (CGEN_FPU
* fpu
, int how UNUSED
, USI x
)
358 sim_fpu_u32to (&ans
, x
, sim_fpu_round_near
);
359 sim_fpu_to32 (&res
, &ans
);
364 fixsfsi (CGEN_FPU
* fpu
, int how UNUSED
, SF x
)
369 sim_fpu_32to (&op1
, x
);
370 sim_fpu_to32i (&res
, &op1
, sim_fpu_round_near
);
375 fixdfsi (CGEN_FPU
* fpu
, int how UNUSED
, DF x
)
380 sim_fpu_64to (&op1
, x
);
381 sim_fpu_to32i (&res
, &op1
, sim_fpu_round_near
);
386 ufixsfsi (CGEN_FPU
* fpu
, int how UNUSED
, SF x
)
391 sim_fpu_32to (&op1
, x
);
392 sim_fpu_to32u (&res
, &op1
, sim_fpu_round_near
);
396 /* DF mode support */
399 adddf (CGEN_FPU
* fpu
, DF x
, DF y
)
405 sim_fpu_status status
;
407 sim_fpu_64to (&op1
, x
);
408 sim_fpu_64to (&op2
, y
);
409 status
= sim_fpu_add (&ans
, &op1
, &op2
);
411 (*fpu
->ops
->error
) (fpu
, status
);
412 sim_fpu_to64 (&res
, &ans
);
418 subdf (CGEN_FPU
* fpu
, DF x
, DF y
)
424 sim_fpu_status status
;
426 sim_fpu_64to (&op1
, x
);
427 sim_fpu_64to (&op2
, y
);
428 status
= sim_fpu_sub (&ans
, &op1
, &op2
);
430 (*fpu
->ops
->error
) (fpu
, status
);
431 sim_fpu_to64 (&res
, &ans
);
437 muldf (CGEN_FPU
* fpu
, DF x
, DF y
)
443 sim_fpu_status status
;
445 sim_fpu_64to (&op1
, x
);
446 sim_fpu_64to (&op2
, y
);
447 status
= sim_fpu_mul (&ans
, &op1
, &op2
);
449 (*fpu
->ops
->error
) (fpu
, status
);
450 sim_fpu_to64 (&res
, &ans
);
456 divdf (CGEN_FPU
* fpu
, DF x
, DF y
)
462 sim_fpu_status status
;
464 sim_fpu_64to (&op1
, x
);
465 sim_fpu_64to (&op2
, y
);
466 status
= sim_fpu_div (&ans
, &op1
, &op2
);
468 (*fpu
->ops
->error
) (fpu
, status
);
469 sim_fpu_to64 (&res
, &ans
);
475 remdf (CGEN_FPU
* fpu
, DF x
, DF y
)
481 sim_fpu_status status
;
483 sim_fpu_64to (&op1
, x
);
484 sim_fpu_64to (&op2
, y
);
485 status
= sim_fpu_rem (&ans
, &op1
, &op2
);
487 (*fpu
->ops
->error
) (fpu
, status
);
488 sim_fpu_to64(&res
, &ans
);
494 negdf (CGEN_FPU
* fpu
, DF x
)
499 sim_fpu_status status
;
501 sim_fpu_64to (&op1
, x
);
502 status
= sim_fpu_neg (&ans
, &op1
);
504 (*fpu
->ops
->error
) (fpu
, status
);
505 sim_fpu_to64 (&res
, &ans
);
511 absdf (CGEN_FPU
* fpu
, DF x
)
516 sim_fpu_status status
;
518 sim_fpu_64to (&op1
, x
);
519 status
= sim_fpu_abs (&ans
, &op1
);
521 (*fpu
->ops
->error
) (fpu
, status
);
522 sim_fpu_to64 (&res
, &ans
);
528 sqrtdf (CGEN_FPU
* fpu
, DF x
)
533 sim_fpu_status status
;
535 sim_fpu_64to (&op1
, x
);
536 status
= sim_fpu_sqrt (&ans
, &op1
);
538 (*fpu
->ops
->error
) (fpu
, status
);
539 sim_fpu_to64 (&res
, &ans
);
545 invdf (CGEN_FPU
* fpu
, DF x
)
550 sim_fpu_status status
;
552 sim_fpu_64to (&op1
, x
);
553 status
= sim_fpu_inv (&ans
, &op1
);
555 (*fpu
->ops
->error
) (fpu
, status
);
556 sim_fpu_to64 (&res
, &ans
);
562 mindf (CGEN_FPU
* fpu
, DF x
, DF y
)
568 sim_fpu_status status
;
570 sim_fpu_64to (&op1
, x
);
571 sim_fpu_64to (&op2
, y
);
572 status
= sim_fpu_min (&ans
, &op1
, &op2
);
574 (*fpu
->ops
->error
) (fpu
, status
);
575 sim_fpu_to64 (&res
, &ans
);
581 maxdf (CGEN_FPU
* fpu
, DF x
, DF y
)
587 sim_fpu_status status
;
589 sim_fpu_64to (&op1
, x
);
590 sim_fpu_64to (&op2
, y
);
591 status
= sim_fpu_max (&ans
, &op1
, &op2
);
593 (*fpu
->ops
->error
) (fpu
, status
);
594 sim_fpu_to64 (&res
, &ans
);
600 cmpdf (CGEN_FPU
* fpu
, DF x
, DF y
)
605 sim_fpu_64to (&op1
, x
);
606 sim_fpu_64to (&op2
, y
);
608 if (sim_fpu_is_nan (&op1
)
609 || sim_fpu_is_nan (&op2
))
620 eqdf (CGEN_FPU
* fpu
, DF x
, DF y
)
625 sim_fpu_64to (&op1
, x
);
626 sim_fpu_64to (&op2
, y
);
627 return sim_fpu_is_eq (&op1
, &op2
);
631 nedf (CGEN_FPU
* fpu
, DF x
, DF y
)
636 sim_fpu_64to (&op1
, x
);
637 sim_fpu_64to (&op2
, y
);
638 return sim_fpu_is_ne (&op1
, &op2
);
642 ltdf (CGEN_FPU
* fpu
, DF x
, DF y
)
647 sim_fpu_64to (&op1
, x
);
648 sim_fpu_64to (&op2
, y
);
649 return sim_fpu_is_lt (&op1
, &op2
);
653 ledf (CGEN_FPU
* fpu
, DF x
, DF y
)
658 sim_fpu_64to (&op1
, x
);
659 sim_fpu_64to (&op2
, y
);
660 return sim_fpu_is_le (&op1
, &op2
);
664 gtdf (CGEN_FPU
* fpu
, DF x
, DF y
)
669 sim_fpu_64to (&op1
, x
);
670 sim_fpu_64to (&op2
, y
);
671 return sim_fpu_is_gt (&op1
, &op2
);
675 gedf (CGEN_FPU
* fpu
, DF x
, DF y
)
680 sim_fpu_64to (&op1
, x
);
681 sim_fpu_64to (&op2
, y
);
682 return sim_fpu_is_ge (&op1
, &op2
);
685 /* Initialize FP_OPS to use accurate library. */
688 cgen_init_accurate_fpu (SIM_CPU
* cpu
, CGEN_FPU
* fpu
, CGEN_FPU_ERROR_FN
* error
)
693 /* ??? small memory leak, not freed by sim_close */
694 fpu
->ops
= (CGEN_FP_OPS
*) xmalloc (sizeof (CGEN_FP_OPS
));
697 memset (o
, 0, sizeof (*o
));
738 o
->fextsfdf
= fextsfdf
;
739 o
->ftruncdfsf
= ftruncdfsf
;
740 o
->floatsisf
= floatsisf
;
741 o
->floatsidf
= floatsidf
;
742 o
->ufloatsisf
= ufloatsisf
;
743 o
->fixsfsi
= fixsfsi
;
744 o
->fixdfsi
= fixdfsi
;
745 o
->ufixsfsi
= ufixsfsi
;