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