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