]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/cgen-accfp.c
import gdb-1999-12-06 snapshot
[thirdparty/binutils-gdb.git] / sim / common / cgen-accfp.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 SF
288 floatsisf (CGEN_FPU* fpu, SI x)
289 {
290 sim_fpu ans;
291 unsigned32 res;
292
293 sim_fpu_i32to (&ans, x, sim_fpu_round_near);
294 sim_fpu_to32 (&res, &ans);
295 return res;
296 }
297
298 static DF
299 floatsidf (CGEN_FPU* fpu, SI x)
300 {
301 sim_fpu ans;
302 unsigned64 res;
303
304 sim_fpu_i32to (&ans, x, sim_fpu_round_near);
305 sim_fpu_to64 (&res, &ans);
306 return res;
307 }
308
309 static SF
310 ufloatsisf (CGEN_FPU* fpu, USI x)
311 {
312 sim_fpu ans;
313 unsigned32 res;
314
315 sim_fpu_u32to (&ans, x, sim_fpu_round_near);
316 sim_fpu_to32 (&res, &ans);
317 return res;
318 }
319
320 static SI
321 fixsfsi (CGEN_FPU* fpu, SF x)
322 {
323 sim_fpu op1;
324 unsigned32 res;
325
326 sim_fpu_32to (&op1, x);
327 sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
328 return res;
329 }
330
331 static SI
332 fixdfsi (CGEN_FPU* fpu, DF x)
333 {
334 sim_fpu op1;
335 unsigned32 res;
336
337 sim_fpu_64to (&op1, x);
338 sim_fpu_to32i (&res, &op1, sim_fpu_round_near);
339 return res;
340 }
341
342 static USI
343 ufixsfsi (CGEN_FPU* fpu, SF x)
344 {
345 sim_fpu op1;
346 unsigned32 res;
347
348 sim_fpu_32to (&op1, x);
349 sim_fpu_to32u (&res, &op1, sim_fpu_round_near);
350 return res;
351 }
352 \f
353 /* DF mode support */
354
355 static DF
356 adddf (CGEN_FPU* fpu, DF x, DF y)
357 {
358 sim_fpu op1;
359 sim_fpu op2;
360 sim_fpu ans;
361 unsigned64 res;
362 sim_fpu_status status;
363
364 sim_fpu_64to (&op1, x);
365 sim_fpu_64to (&op2, y);
366 status = sim_fpu_add (&ans, &op1, &op2);
367 if (status != 0)
368 (*fpu->ops->error) (fpu, status);
369 sim_fpu_to64 (&res, &ans);
370
371 return res;
372 }
373
374 static DF
375 subdf (CGEN_FPU* fpu, DF x, DF y)
376 {
377 sim_fpu op1;
378 sim_fpu op2;
379 sim_fpu ans;
380 unsigned64 res;
381 sim_fpu_status status;
382
383 sim_fpu_64to (&op1, x);
384 sim_fpu_64to (&op2, y);
385 status = sim_fpu_sub (&ans, &op1, &op2);
386 if (status != 0)
387 (*fpu->ops->error) (fpu, status);
388 sim_fpu_to64 (&res, &ans);
389
390 return res;
391 }
392
393 static DF
394 muldf (CGEN_FPU* fpu, DF x, DF y)
395 {
396 sim_fpu op1;
397 sim_fpu op2;
398 sim_fpu ans;
399 unsigned64 res;
400 sim_fpu_status status;
401
402 sim_fpu_64to (&op1, x);
403 sim_fpu_64to (&op2, y);
404 status = sim_fpu_mul (&ans, &op1, &op2);
405 if (status != 0)
406 (*fpu->ops->error) (fpu, status);
407 sim_fpu_to64 (&res, &ans);
408
409 return res;
410 }
411
412 static DF
413 divdf (CGEN_FPU* fpu, DF x, DF y)
414 {
415 sim_fpu op1;
416 sim_fpu op2;
417 sim_fpu ans;
418 unsigned64 res;
419 sim_fpu_status status;
420
421 sim_fpu_64to (&op1, x);
422 sim_fpu_64to (&op2, y);
423 status = sim_fpu_div (&ans, &op1, &op2);
424 if (status != 0)
425 (*fpu->ops->error) (fpu, status);
426 sim_fpu_to64 (&res, &ans);
427
428 return res;
429 }
430
431 static DF
432 negdf (CGEN_FPU* fpu, DF x)
433 {
434 sim_fpu op1;
435 sim_fpu ans;
436 unsigned64 res;
437 sim_fpu_status status;
438
439 sim_fpu_64to (&op1, x);
440 status = sim_fpu_neg (&ans, &op1);
441 if (status != 0)
442 (*fpu->ops->error) (fpu, status);
443 sim_fpu_to64 (&res, &ans);
444
445 return res;
446 }
447
448 static DF
449 absdf (CGEN_FPU* fpu, DF x)
450 {
451 sim_fpu op1;
452 sim_fpu ans;
453 unsigned64 res;
454 sim_fpu_status status;
455
456 sim_fpu_64to (&op1, x);
457 status = sim_fpu_abs (&ans, &op1);
458 if (status != 0)
459 (*fpu->ops->error) (fpu, status);
460 sim_fpu_to64 (&res, &ans);
461
462 return res;
463 }
464
465 static DF
466 sqrtdf (CGEN_FPU* fpu, DF x)
467 {
468 sim_fpu op1;
469 sim_fpu ans;
470 unsigned64 res;
471 sim_fpu_status status;
472
473 sim_fpu_64to (&op1, x);
474 status = sim_fpu_sqrt (&ans, &op1);
475 if (status != 0)
476 (*fpu->ops->error) (fpu, status);
477 sim_fpu_to64 (&res, &ans);
478
479 return res;
480 }
481
482 static DF
483 invdf (CGEN_FPU* fpu, DF x)
484 {
485 sim_fpu op1;
486 sim_fpu ans;
487 unsigned64 res;
488 sim_fpu_status status;
489
490 sim_fpu_64to (&op1, x);
491 status = sim_fpu_inv (&ans, &op1);
492 if (status != 0)
493 (*fpu->ops->error) (fpu, status);
494 sim_fpu_to64 (&res, &ans);
495
496 return res;
497 }
498
499 static DF
500 mindf (CGEN_FPU* fpu, DF x, DF y)
501 {
502 sim_fpu op1;
503 sim_fpu op2;
504 sim_fpu ans;
505 unsigned64 res;
506 sim_fpu_status status;
507
508 sim_fpu_64to (&op1, x);
509 sim_fpu_64to (&op2, y);
510 status = sim_fpu_min (&ans, &op1, &op2);
511 if (status != 0)
512 (*fpu->ops->error) (fpu, status);
513 sim_fpu_to64 (&res, &ans);
514
515 return res;
516 }
517
518 static DF
519 maxdf (CGEN_FPU* fpu, DF x, DF y)
520 {
521 sim_fpu op1;
522 sim_fpu op2;
523 sim_fpu ans;
524 unsigned64 res;
525 sim_fpu_status status;
526
527 sim_fpu_64to (&op1, x);
528 sim_fpu_64to (&op2, y);
529 status = sim_fpu_max (&ans, &op1, &op2);
530 if (status != 0)
531 (*fpu->ops->error) (fpu, status);
532 sim_fpu_to64 (&res, &ans);
533
534 return res;
535 }
536
537 static CGEN_FP_CMP
538 cmpdf (CGEN_FPU* fpu, DF x, DF y)
539 {
540 sim_fpu op1;
541 sim_fpu op2;
542
543 sim_fpu_64to (&op1, x);
544 sim_fpu_64to (&op2, y);
545
546 if (sim_fpu_is_nan (&op1)
547 || sim_fpu_is_nan (&op2))
548 return FP_CMP_NAN;
549
550 if (x < y)
551 return FP_CMP_LT;
552 if (x > y)
553 return FP_CMP_GT;
554 return FP_CMP_EQ;
555 }
556
557 static int
558 eqdf (CGEN_FPU* fpu, DF x, DF y)
559 {
560 sim_fpu op1;
561 sim_fpu op2;
562
563 sim_fpu_64to (&op1, x);
564 sim_fpu_64to (&op2, y);
565 return sim_fpu_is_eq (&op1, &op2);
566 }
567
568 static int
569 nedf (CGEN_FPU* fpu, DF x, DF y)
570 {
571 sim_fpu op1;
572 sim_fpu op2;
573
574 sim_fpu_64to (&op1, x);
575 sim_fpu_64to (&op2, y);
576 return sim_fpu_is_ne (&op1, &op2);
577 }
578
579 static int
580 ltdf (CGEN_FPU* fpu, DF x, DF y)
581 {
582 sim_fpu op1;
583 sim_fpu op2;
584
585 sim_fpu_64to (&op1, x);
586 sim_fpu_64to (&op2, y);
587 return sim_fpu_is_lt (&op1, &op2);
588 }
589
590 static int
591 ledf (CGEN_FPU* fpu, DF x, DF y)
592 {
593 sim_fpu op1;
594 sim_fpu op2;
595
596 sim_fpu_64to (&op1, x);
597 sim_fpu_64to (&op2, y);
598 return sim_fpu_is_le (&op1, &op2);
599 }
600
601 static int
602 gtdf (CGEN_FPU* fpu, DF x, DF y)
603 {
604 sim_fpu op1;
605 sim_fpu op2;
606
607 sim_fpu_64to (&op1, x);
608 sim_fpu_64to (&op2, y);
609 return sim_fpu_is_gt (&op1, &op2);
610 }
611
612 static int
613 gedf (CGEN_FPU* fpu, DF x, DF y)
614 {
615 sim_fpu op1;
616 sim_fpu op2;
617
618 sim_fpu_64to (&op1, x);
619 sim_fpu_64to (&op2, y);
620 return sim_fpu_is_ge (&op1, &op2);
621 }
622 \f
623 /* Initialize FP_OPS to use accurate library. */
624
625 void
626 cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error)
627 {
628 CGEN_FP_OPS* o;
629
630 fpu->owner = cpu;
631 /* ??? small memory leak, not freed by sim_close */
632 fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS));
633
634 o = fpu->ops;
635 memset (o, 0, sizeof (*o));
636
637 o->error = error;
638
639 o->addsf = addsf;
640 o->subsf = subsf;
641 o->mulsf = mulsf;
642 o->divsf = divsf;
643 o->negsf = negsf;
644 o->abssf = abssf;
645 o->sqrtsf = sqrtsf;
646 o->invsf = invsf;
647 o->minsf = minsf;
648 o->maxsf = maxsf;
649 o->cmpsf = cmpsf;
650 o->eqsf = eqsf;
651 o->nesf = nesf;
652 o->ltsf = ltsf;
653 o->lesf = lesf;
654 o->gtsf = gtsf;
655 o->gesf = gesf;
656
657 o->adddf = adddf;
658 o->subdf = subdf;
659 o->muldf = muldf;
660 o->divdf = divdf;
661 o->negdf = negdf;
662 o->absdf = absdf;
663 o->sqrtdf = sqrtdf;
664 o->invdf = invdf;
665 o->mindf = mindf;
666 o->maxdf = maxdf;
667 o->cmpdf = cmpdf;
668 o->eqdf = eqdf;
669 o->nedf = nedf;
670 o->ltdf = ltdf;
671 o->ledf = ledf;
672 o->gtdf = gtdf;
673 o->gedf = gedf;
674 o->floatsisf = floatsisf;
675 o->floatsidf = floatsidf;
676 o->ufloatsisf = ufloatsisf;
677 o->fixsfsi = fixsfsi;
678 o->fixdfsi = fixdfsi;
679 o->ufixsfsi = ufixsfsi;
680 }