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 negsf (CGEN_FPU
* fpu
, SF x
)
101 sim_fpu_status status
;
103 sim_fpu_32to (&op1
, x
);
104 status
= sim_fpu_neg (&ans
, &op1
);
106 (*fpu
->ops
->error
) (fpu
, status
);
107 sim_fpu_to32 (&res
, &ans
);
113 abssf (CGEN_FPU
* fpu
, SF x
)
118 sim_fpu_status status
;
120 sim_fpu_32to (&op1
, x
);
121 status
= sim_fpu_abs (&ans
, &op1
);
123 (*fpu
->ops
->error
) (fpu
, status
);
124 sim_fpu_to32 (&res
, &ans
);
130 sqrtsf (CGEN_FPU
* fpu
, SF x
)
135 sim_fpu_status status
;
137 sim_fpu_32to (&op1
, x
);
138 status
= sim_fpu_sqrt (&ans
, &op1
);
140 (*fpu
->ops
->error
) (fpu
, status
);
141 sim_fpu_to32 (&res
, &ans
);
147 invsf (CGEN_FPU
* fpu
, SF x
)
152 sim_fpu_status status
;
154 sim_fpu_32to (&op1
, x
);
155 status
= sim_fpu_inv (&ans
, &op1
);
157 (*fpu
->ops
->error
) (fpu
, status
);
158 sim_fpu_to32 (&res
, &ans
);
164 minsf (CGEN_FPU
* fpu
, SF x
, SF y
)
170 sim_fpu_status status
;
172 sim_fpu_32to (&op1
, x
);
173 sim_fpu_32to (&op2
, y
);
174 status
= sim_fpu_min (&ans
, &op1
, &op2
);
176 (*fpu
->ops
->error
) (fpu
, status
);
177 sim_fpu_to32 (&res
, &ans
);
183 maxsf (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_max (&ans
, &op1
, &op2
);
195 (*fpu
->ops
->error
) (fpu
, status
);
196 sim_fpu_to32 (&res
, &ans
);
202 cmpsf (CGEN_FPU
* fpu
, SF x
, SF y
)
207 sim_fpu_32to (&op1
, x
);
208 sim_fpu_32to (&op2
, y
);
210 if (sim_fpu_is_nan (&op1
)
211 || sim_fpu_is_nan (&op2
))
222 eqsf (CGEN_FPU
* fpu
, SF x
, SF y
)
227 sim_fpu_32to (&op1
, x
);
228 sim_fpu_32to (&op2
, y
);
229 return sim_fpu_is_eq (&op1
, &op2
);
233 nesf (CGEN_FPU
* fpu
, SF x
, SF y
)
238 sim_fpu_32to (&op1
, x
);
239 sim_fpu_32to (&op2
, y
);
240 return sim_fpu_is_ne (&op1
, &op2
);
244 ltsf (CGEN_FPU
* fpu
, SF x
, SF y
)
249 sim_fpu_32to (&op1
, x
);
250 sim_fpu_32to (&op2
, y
);
251 return sim_fpu_is_lt (&op1
, &op2
);
255 lesf (CGEN_FPU
* fpu
, SF x
, SF y
)
260 sim_fpu_32to (&op1
, x
);
261 sim_fpu_32to (&op2
, y
);
262 return sim_fpu_is_le (&op1
, &op2
);
266 gtsf (CGEN_FPU
* fpu
, SF x
, SF y
)
271 sim_fpu_32to (&op1
, x
);
272 sim_fpu_32to (&op2
, y
);
273 return sim_fpu_is_gt (&op1
, &op2
);
277 gesf (CGEN_FPU
* fpu
, SF x
, SF y
)
282 sim_fpu_32to (&op1
, x
);
283 sim_fpu_32to (&op2
, y
);
284 return sim_fpu_is_ge (&op1
, &op2
);
288 fextsfdf (CGEN_FPU
* fpu
, SF x
)
293 sim_fpu_32to (&op1
, x
);
294 sim_fpu_to64 (&res
, &op1
);
300 ftruncdfsf (CGEN_FPU
* fpu
, DF x
)
305 sim_fpu_64to (&op1
, x
);
306 sim_fpu_to32 (&res
, &op1
);
312 floatsisf (CGEN_FPU
* fpu
, SI x
)
317 sim_fpu_i32to (&ans
, x
, sim_fpu_round_near
);
318 sim_fpu_to32 (&res
, &ans
);
323 floatsidf (CGEN_FPU
* fpu
, SI x
)
328 sim_fpu_i32to (&ans
, x
, sim_fpu_round_near
);
329 sim_fpu_to64 (&res
, &ans
);
334 ufloatsisf (CGEN_FPU
* fpu
, USI x
)
339 sim_fpu_u32to (&ans
, x
, sim_fpu_round_near
);
340 sim_fpu_to32 (&res
, &ans
);
345 fixsfsi (CGEN_FPU
* fpu
, SF x
)
350 sim_fpu_32to (&op1
, x
);
351 sim_fpu_to32i (&res
, &op1
, sim_fpu_round_near
);
356 fixdfsi (CGEN_FPU
* fpu
, DF x
)
361 sim_fpu_64to (&op1
, x
);
362 sim_fpu_to32i (&res
, &op1
, sim_fpu_round_near
);
367 ufixsfsi (CGEN_FPU
* fpu
, SF x
)
372 sim_fpu_32to (&op1
, x
);
373 sim_fpu_to32u (&res
, &op1
, sim_fpu_round_near
);
377 /* DF mode support */
380 adddf (CGEN_FPU
* fpu
, DF x
, DF y
)
386 sim_fpu_status status
;
388 sim_fpu_64to (&op1
, x
);
389 sim_fpu_64to (&op2
, y
);
390 status
= sim_fpu_add (&ans
, &op1
, &op2
);
392 (*fpu
->ops
->error
) (fpu
, status
);
393 sim_fpu_to64 (&res
, &ans
);
399 subdf (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_sub (&ans
, &op1
, &op2
);
411 (*fpu
->ops
->error
) (fpu
, status
);
412 sim_fpu_to64 (&res
, &ans
);
418 muldf (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_mul (&ans
, &op1
, &op2
);
430 (*fpu
->ops
->error
) (fpu
, status
);
431 sim_fpu_to64 (&res
, &ans
);
437 divdf (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_div (&ans
, &op1
, &op2
);
449 (*fpu
->ops
->error
) (fpu
, status
);
450 sim_fpu_to64 (&res
, &ans
);
456 negdf (CGEN_FPU
* fpu
, DF x
)
461 sim_fpu_status status
;
463 sim_fpu_64to (&op1
, x
);
464 status
= sim_fpu_neg (&ans
, &op1
);
466 (*fpu
->ops
->error
) (fpu
, status
);
467 sim_fpu_to64 (&res
, &ans
);
473 absdf (CGEN_FPU
* fpu
, DF x
)
478 sim_fpu_status status
;
480 sim_fpu_64to (&op1
, x
);
481 status
= sim_fpu_abs (&ans
, &op1
);
483 (*fpu
->ops
->error
) (fpu
, status
);
484 sim_fpu_to64 (&res
, &ans
);
490 sqrtdf (CGEN_FPU
* fpu
, DF x
)
495 sim_fpu_status status
;
497 sim_fpu_64to (&op1
, x
);
498 status
= sim_fpu_sqrt (&ans
, &op1
);
500 (*fpu
->ops
->error
) (fpu
, status
);
501 sim_fpu_to64 (&res
, &ans
);
507 invdf (CGEN_FPU
* fpu
, DF x
)
512 sim_fpu_status status
;
514 sim_fpu_64to (&op1
, x
);
515 status
= sim_fpu_inv (&ans
, &op1
);
517 (*fpu
->ops
->error
) (fpu
, status
);
518 sim_fpu_to64 (&res
, &ans
);
524 mindf (CGEN_FPU
* fpu
, DF x
, DF y
)
530 sim_fpu_status status
;
532 sim_fpu_64to (&op1
, x
);
533 sim_fpu_64to (&op2
, y
);
534 status
= sim_fpu_min (&ans
, &op1
, &op2
);
536 (*fpu
->ops
->error
) (fpu
, status
);
537 sim_fpu_to64 (&res
, &ans
);
543 maxdf (CGEN_FPU
* fpu
, DF x
, DF y
)
549 sim_fpu_status status
;
551 sim_fpu_64to (&op1
, x
);
552 sim_fpu_64to (&op2
, y
);
553 status
= sim_fpu_max (&ans
, &op1
, &op2
);
555 (*fpu
->ops
->error
) (fpu
, status
);
556 sim_fpu_to64 (&res
, &ans
);
562 cmpdf (CGEN_FPU
* fpu
, DF x
, DF y
)
567 sim_fpu_64to (&op1
, x
);
568 sim_fpu_64to (&op2
, y
);
570 if (sim_fpu_is_nan (&op1
)
571 || sim_fpu_is_nan (&op2
))
582 eqdf (CGEN_FPU
* fpu
, DF x
, DF y
)
587 sim_fpu_64to (&op1
, x
);
588 sim_fpu_64to (&op2
, y
);
589 return sim_fpu_is_eq (&op1
, &op2
);
593 nedf (CGEN_FPU
* fpu
, DF x
, DF y
)
598 sim_fpu_64to (&op1
, x
);
599 sim_fpu_64to (&op2
, y
);
600 return sim_fpu_is_ne (&op1
, &op2
);
604 ltdf (CGEN_FPU
* fpu
, DF x
, DF y
)
609 sim_fpu_64to (&op1
, x
);
610 sim_fpu_64to (&op2
, y
);
611 return sim_fpu_is_lt (&op1
, &op2
);
615 ledf (CGEN_FPU
* fpu
, DF x
, DF y
)
620 sim_fpu_64to (&op1
, x
);
621 sim_fpu_64to (&op2
, y
);
622 return sim_fpu_is_le (&op1
, &op2
);
626 gtdf (CGEN_FPU
* fpu
, DF x
, DF y
)
631 sim_fpu_64to (&op1
, x
);
632 sim_fpu_64to (&op2
, y
);
633 return sim_fpu_is_gt (&op1
, &op2
);
637 gedf (CGEN_FPU
* fpu
, DF x
, DF y
)
642 sim_fpu_64to (&op1
, x
);
643 sim_fpu_64to (&op2
, y
);
644 return sim_fpu_is_ge (&op1
, &op2
);
647 /* Initialize FP_OPS to use accurate library. */
650 cgen_init_accurate_fpu (SIM_CPU
* cpu
, CGEN_FPU
* fpu
, CGEN_FPU_ERROR_FN
* error
)
655 /* ??? small memory leak, not freed by sim_close */
656 fpu
->ops
= (CGEN_FP_OPS
*) xmalloc (sizeof (CGEN_FP_OPS
));
659 memset (o
, 0, sizeof (*o
));
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
;