]> Git Repo - qemu.git/blob - target/s390x/fpu_helper.c
Merge remote-tracking branch 'remotes/kraxel/tags/usb-20180518-pull-request' into...
[qemu.git] / target / s390x / fpu_helper.c
1 /*
2  *  S/390 FPU helper routines
3  *
4  *  Copyright (c) 2009 Ulrich Hecht
5  *  Copyright (c) 2009 Alexander Graf
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23 #include "internal.h"
24 #include "exec/exec-all.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/helper-proto.h"
27 #include "fpu/softfloat.h"
28
29 /* #define DEBUG_HELPER */
30 #ifdef DEBUG_HELPER
31 #define HELPER_LOG(x...) qemu_log(x)
32 #else
33 #define HELPER_LOG(x...)
34 #endif
35
36 #define RET128(F) (env->retxl = F.low, F.high)
37
38 #define convert_bit(mask, from, to) \
39     (to < from                      \
40      ? (mask / (from / to)) & to    \
41      : (mask & from) * (to / from))
42
43 static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
44 {
45     /* Install the DXC code.  */
46     env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
47     /* Trap.  */
48     s390_program_interrupt(env, PGM_DATA, ILEN_AUTO, retaddr);
49 }
50
51 /* Should be called after any operation that may raise IEEE exceptions.  */
52 static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
53 {
54     unsigned s390_exc, qemu_exc;
55
56     /* Get the exceptions raised by the current operation.  Reset the
57        fpu_status contents so that the next operation has a clean slate.  */
58     qemu_exc = env->fpu_status.float_exception_flags;
59     if (qemu_exc == 0) {
60         return;
61     }
62     env->fpu_status.float_exception_flags = 0;
63
64     /* Convert softfloat exception bits to s390 exception bits.  */
65     s390_exc = 0;
66     s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
67     s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
68     s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
69     s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
70     s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
71
72     /* Install the exceptions that we raised.  */
73     env->fpc |= s390_exc << 16;
74
75     /* Send signals for enabled exceptions.  */
76     s390_exc &= env->fpc >> 24;
77     if (s390_exc) {
78         ieee_exception(env, s390_exc, retaddr);
79     }
80 }
81
82 static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
83 {
84     S390CPU *cpu = s390_env_get_cpu(env);
85
86     switch (float_compare) {
87     case float_relation_equal:
88         return 0;
89     case float_relation_less:
90         return 1;
91     case float_relation_greater:
92         return 2;
93     case float_relation_unordered:
94         return 3;
95     default:
96         cpu_abort(CPU(cpu), "unknown return value for float compare\n");
97     }
98 }
99
100 /* condition codes for unary FP ops */
101 uint32_t set_cc_nz_f32(float32 v)
102 {
103     if (float32_is_any_nan(v)) {
104         return 3;
105     } else if (float32_is_zero(v)) {
106         return 0;
107     } else if (float32_is_neg(v)) {
108         return 1;
109     } else {
110         return 2;
111     }
112 }
113
114 uint32_t set_cc_nz_f64(float64 v)
115 {
116     if (float64_is_any_nan(v)) {
117         return 3;
118     } else if (float64_is_zero(v)) {
119         return 0;
120     } else if (float64_is_neg(v)) {
121         return 1;
122     } else {
123         return 2;
124     }
125 }
126
127 uint32_t set_cc_nz_f128(float128 v)
128 {
129     if (float128_is_any_nan(v)) {
130         return 3;
131     } else if (float128_is_zero(v)) {
132         return 0;
133     } else if (float128_is_neg(v)) {
134         return 1;
135     } else {
136         return 2;
137     }
138 }
139
140 /* 32-bit FP addition */
141 uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
142 {
143     float32 ret = float32_add(f1, f2, &env->fpu_status);
144     handle_exceptions(env, GETPC());
145     return ret;
146 }
147
148 /* 64-bit FP addition */
149 uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
150 {
151     float64 ret = float64_add(f1, f2, &env->fpu_status);
152     handle_exceptions(env, GETPC());
153     return ret;
154 }
155
156 /* 128-bit FP addition */
157 uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
158                      uint64_t bh, uint64_t bl)
159 {
160     float128 ret = float128_add(make_float128(ah, al),
161                                 make_float128(bh, bl),
162                                 &env->fpu_status);
163     handle_exceptions(env, GETPC());
164     return RET128(ret);
165 }
166
167 /* 32-bit FP subtraction */
168 uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
169 {
170     float32 ret = float32_sub(f1, f2, &env->fpu_status);
171     handle_exceptions(env, GETPC());
172     return ret;
173 }
174
175 /* 64-bit FP subtraction */
176 uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
177 {
178     float64 ret = float64_sub(f1, f2, &env->fpu_status);
179     handle_exceptions(env, GETPC());
180     return ret;
181 }
182
183 /* 128-bit FP subtraction */
184 uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
185                      uint64_t bh, uint64_t bl)
186 {
187     float128 ret = float128_sub(make_float128(ah, al),
188                                 make_float128(bh, bl),
189                                 &env->fpu_status);
190     handle_exceptions(env, GETPC());
191     return RET128(ret);
192 }
193
194 /* 32-bit FP division */
195 uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
196 {
197     float32 ret = float32_div(f1, f2, &env->fpu_status);
198     handle_exceptions(env, GETPC());
199     return ret;
200 }
201
202 /* 64-bit FP division */
203 uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
204 {
205     float64 ret = float64_div(f1, f2, &env->fpu_status);
206     handle_exceptions(env, GETPC());
207     return ret;
208 }
209
210 /* 128-bit FP division */
211 uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
212                      uint64_t bh, uint64_t bl)
213 {
214     float128 ret = float128_div(make_float128(ah, al),
215                                 make_float128(bh, bl),
216                                 &env->fpu_status);
217     handle_exceptions(env, GETPC());
218     return RET128(ret);
219 }
220
221 /* 32-bit FP multiplication */
222 uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
223 {
224     float32 ret = float32_mul(f1, f2, &env->fpu_status);
225     handle_exceptions(env, GETPC());
226     return ret;
227 }
228
229 /* 64-bit FP multiplication */
230 uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
231 {
232     float64 ret = float64_mul(f1, f2, &env->fpu_status);
233     handle_exceptions(env, GETPC());
234     return ret;
235 }
236
237 /* 64/32-bit FP multiplication */
238 uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
239 {
240     float64 ret = float32_to_float64(f2, &env->fpu_status);
241     ret = float64_mul(f1, ret, &env->fpu_status);
242     handle_exceptions(env, GETPC());
243     return ret;
244 }
245
246 /* 128-bit FP multiplication */
247 uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
248                      uint64_t bh, uint64_t bl)
249 {
250     float128 ret = float128_mul(make_float128(ah, al),
251                                 make_float128(bh, bl),
252                                 &env->fpu_status);
253     handle_exceptions(env, GETPC());
254     return RET128(ret);
255 }
256
257 /* 128/64-bit FP multiplication */
258 uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
259                       uint64_t f2)
260 {
261     float128 ret = float64_to_float128(f2, &env->fpu_status);
262     ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
263     handle_exceptions(env, GETPC());
264     return RET128(ret);
265 }
266
267 /* convert 32-bit float to 64-bit float */
268 uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
269 {
270     float64 ret = float32_to_float64(f2, &env->fpu_status);
271     handle_exceptions(env, GETPC());
272     return ret;
273 }
274
275 /* convert 128-bit float to 64-bit float */
276 uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
277 {
278     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
279     handle_exceptions(env, GETPC());
280     return ret;
281 }
282
283 /* convert 64-bit float to 128-bit float */
284 uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
285 {
286     float128 ret = float64_to_float128(f2, &env->fpu_status);
287     handle_exceptions(env, GETPC());
288     return RET128(ret);
289 }
290
291 /* convert 32-bit float to 128-bit float */
292 uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
293 {
294     float128 ret = float32_to_float128(f2, &env->fpu_status);
295     handle_exceptions(env, GETPC());
296     return RET128(ret);
297 }
298
299 /* convert 64-bit float to 32-bit float */
300 uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
301 {
302     float32 ret = float64_to_float32(f2, &env->fpu_status);
303     handle_exceptions(env, GETPC());
304     return ret;
305 }
306
307 /* convert 128-bit float to 32-bit float */
308 uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
309 {
310     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
311     handle_exceptions(env, GETPC());
312     return ret;
313 }
314
315 /* 32-bit FP compare */
316 uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
317 {
318     int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
319     handle_exceptions(env, GETPC());
320     return float_comp_to_cc(env, cmp);
321 }
322
323 /* 64-bit FP compare */
324 uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
325 {
326     int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
327     handle_exceptions(env, GETPC());
328     return float_comp_to_cc(env, cmp);
329 }
330
331 /* 128-bit FP compare */
332 uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
333                      uint64_t bh, uint64_t bl)
334 {
335     int cmp = float128_compare_quiet(make_float128(ah, al),
336                                      make_float128(bh, bl),
337                                      &env->fpu_status);
338     handle_exceptions(env, GETPC());
339     return float_comp_to_cc(env, cmp);
340 }
341
342 static int swap_round_mode(CPUS390XState *env, int m3)
343 {
344     int ret = env->fpu_status.float_rounding_mode;
345     switch (m3) {
346     case 0:
347         /* current mode */
348         break;
349     case 1:
350         /* biased round no nearest */
351     case 4:
352         /* round to nearest */
353         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
354         break;
355     case 5:
356         /* round to zero */
357         set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
358         break;
359     case 6:
360         /* round to +inf */
361         set_float_rounding_mode(float_round_up, &env->fpu_status);
362         break;
363     case 7:
364         /* round to -inf */
365         set_float_rounding_mode(float_round_down, &env->fpu_status);
366         break;
367     }
368     return ret;
369 }
370
371 /* convert 64-bit int to 32-bit float */
372 uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
373 {
374     int hold = swap_round_mode(env, m3);
375     float32 ret = int64_to_float32(v2, &env->fpu_status);
376     set_float_rounding_mode(hold, &env->fpu_status);
377     handle_exceptions(env, GETPC());
378     return ret;
379 }
380
381 /* convert 64-bit int to 64-bit float */
382 uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
383 {
384     int hold = swap_round_mode(env, m3);
385     float64 ret = int64_to_float64(v2, &env->fpu_status);
386     set_float_rounding_mode(hold, &env->fpu_status);
387     handle_exceptions(env, GETPC());
388     return ret;
389 }
390
391 /* convert 64-bit int to 128-bit float */
392 uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
393 {
394     int hold = swap_round_mode(env, m3);
395     float128 ret = int64_to_float128(v2, &env->fpu_status);
396     set_float_rounding_mode(hold, &env->fpu_status);
397     handle_exceptions(env, GETPC());
398     return RET128(ret);
399 }
400
401 /* convert 64-bit uint to 32-bit float */
402 uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
403 {
404     int hold = swap_round_mode(env, m3);
405     float32 ret = uint64_to_float32(v2, &env->fpu_status);
406     set_float_rounding_mode(hold, &env->fpu_status);
407     handle_exceptions(env, GETPC());
408     return ret;
409 }
410
411 /* convert 64-bit uint to 64-bit float */
412 uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
413 {
414     int hold = swap_round_mode(env, m3);
415     float64 ret = uint64_to_float64(v2, &env->fpu_status);
416     set_float_rounding_mode(hold, &env->fpu_status);
417     handle_exceptions(env, GETPC());
418     return ret;
419 }
420
421 /* convert 64-bit uint to 128-bit float */
422 uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
423 {
424     int hold = swap_round_mode(env, m3);
425     float128 ret = uint64_to_float128(v2, &env->fpu_status);
426     set_float_rounding_mode(hold, &env->fpu_status);
427     handle_exceptions(env, GETPC());
428     return RET128(ret);
429 }
430
431 /* convert 32-bit float to 64-bit int */
432 uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
433 {
434     int hold = swap_round_mode(env, m3);
435     int64_t ret = float32_to_int64(v2, &env->fpu_status);
436     set_float_rounding_mode(hold, &env->fpu_status);
437     handle_exceptions(env, GETPC());
438     return ret;
439 }
440
441 /* convert 64-bit float to 64-bit int */
442 uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
443 {
444     int hold = swap_round_mode(env, m3);
445     int64_t ret = float64_to_int64(v2, &env->fpu_status);
446     set_float_rounding_mode(hold, &env->fpu_status);
447     handle_exceptions(env, GETPC());
448     return ret;
449 }
450
451 /* convert 128-bit float to 64-bit int */
452 uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
453 {
454     int hold = swap_round_mode(env, m3);
455     float128 v2 = make_float128(h, l);
456     int64_t ret = float128_to_int64(v2, &env->fpu_status);
457     set_float_rounding_mode(hold, &env->fpu_status);
458     handle_exceptions(env, GETPC());
459     return ret;
460 }
461
462 /* convert 32-bit float to 32-bit int */
463 uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
464 {
465     int hold = swap_round_mode(env, m3);
466     int32_t ret = float32_to_int32(v2, &env->fpu_status);
467     set_float_rounding_mode(hold, &env->fpu_status);
468     handle_exceptions(env, GETPC());
469     return ret;
470 }
471
472 /* convert 64-bit float to 32-bit int */
473 uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
474 {
475     int hold = swap_round_mode(env, m3);
476     int32_t ret = float64_to_int32(v2, &env->fpu_status);
477     set_float_rounding_mode(hold, &env->fpu_status);
478     handle_exceptions(env, GETPC());
479     return ret;
480 }
481
482 /* convert 128-bit float to 32-bit int */
483 uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
484 {
485     int hold = swap_round_mode(env, m3);
486     float128 v2 = make_float128(h, l);
487     int32_t ret = float128_to_int32(v2, &env->fpu_status);
488     set_float_rounding_mode(hold, &env->fpu_status);
489     handle_exceptions(env, GETPC());
490     return ret;
491 }
492
493 /* convert 32-bit float to 64-bit uint */
494 uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
495 {
496     int hold = swap_round_mode(env, m3);
497     uint64_t ret;
498     v2 = float32_to_float64(v2, &env->fpu_status);
499     ret = float64_to_uint64(v2, &env->fpu_status);
500     set_float_rounding_mode(hold, &env->fpu_status);
501     handle_exceptions(env, GETPC());
502     return ret;
503 }
504
505 /* convert 64-bit float to 64-bit uint */
506 uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
507 {
508     int hold = swap_round_mode(env, m3);
509     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
510     set_float_rounding_mode(hold, &env->fpu_status);
511     handle_exceptions(env, GETPC());
512     return ret;
513 }
514
515 /* convert 128-bit float to 64-bit uint */
516 uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
517 {
518     int hold = swap_round_mode(env, m3);
519     float128 v2 = make_float128(h, l);
520     /* ??? Not 100% correct.  */
521     uint64_t ret = float128_to_int64(v2, &env->fpu_status);
522     set_float_rounding_mode(hold, &env->fpu_status);
523     handle_exceptions(env, GETPC());
524     return ret;
525 }
526
527 /* convert 32-bit float to 32-bit uint */
528 uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
529 {
530     int hold = swap_round_mode(env, m3);
531     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
532     set_float_rounding_mode(hold, &env->fpu_status);
533     handle_exceptions(env, GETPC());
534     return ret;
535 }
536
537 /* convert 64-bit float to 32-bit uint */
538 uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
539 {
540     int hold = swap_round_mode(env, m3);
541     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
542     set_float_rounding_mode(hold, &env->fpu_status);
543     handle_exceptions(env, GETPC());
544     return ret;
545 }
546
547 /* convert 128-bit float to 32-bit uint */
548 uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
549 {
550     int hold = swap_round_mode(env, m3);
551     float128 v2 = make_float128(h, l);
552     /* Not 100% correct.  */
553     uint32_t ret = float128_to_int64(v2, &env->fpu_status);
554     set_float_rounding_mode(hold, &env->fpu_status);
555     handle_exceptions(env, GETPC());
556     return ret;
557 }
558
559 /* round to integer 32-bit */
560 uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
561 {
562     int hold = swap_round_mode(env, m3);
563     float32 ret = float32_round_to_int(f2, &env->fpu_status);
564     set_float_rounding_mode(hold, &env->fpu_status);
565     handle_exceptions(env, GETPC());
566     return ret;
567 }
568
569 /* round to integer 64-bit */
570 uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
571 {
572     int hold = swap_round_mode(env, m3);
573     float64 ret = float64_round_to_int(f2, &env->fpu_status);
574     set_float_rounding_mode(hold, &env->fpu_status);
575     handle_exceptions(env, GETPC());
576     return ret;
577 }
578
579 /* round to integer 128-bit */
580 uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
581 {
582     int hold = swap_round_mode(env, m3);
583     float128 ret = float128_round_to_int(make_float128(ah, al),
584                                          &env->fpu_status);
585     set_float_rounding_mode(hold, &env->fpu_status);
586     handle_exceptions(env, GETPC());
587     return RET128(ret);
588 }
589
590 /* 32-bit FP compare and signal */
591 uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
592 {
593     int cmp = float32_compare(f1, f2, &env->fpu_status);
594     handle_exceptions(env, GETPC());
595     return float_comp_to_cc(env, cmp);
596 }
597
598 /* 64-bit FP compare and signal */
599 uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
600 {
601     int cmp = float64_compare(f1, f2, &env->fpu_status);
602     handle_exceptions(env, GETPC());
603     return float_comp_to_cc(env, cmp);
604 }
605
606 /* 128-bit FP compare and signal */
607 uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
608                      uint64_t bh, uint64_t bl)
609 {
610     int cmp = float128_compare(make_float128(ah, al),
611                                make_float128(bh, bl),
612                                &env->fpu_status);
613     handle_exceptions(env, GETPC());
614     return float_comp_to_cc(env, cmp);
615 }
616
617 /* 32-bit FP multiply and add */
618 uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
619                       uint64_t f2, uint64_t f3)
620 {
621     float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
622     handle_exceptions(env, GETPC());
623     return ret;
624 }
625
626 /* 64-bit FP multiply and add */
627 uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
628                       uint64_t f2, uint64_t f3)
629 {
630     float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
631     handle_exceptions(env, GETPC());
632     return ret;
633 }
634
635 /* 32-bit FP multiply and subtract */
636 uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
637                       uint64_t f2, uint64_t f3)
638 {
639     float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
640                                  &env->fpu_status);
641     handle_exceptions(env, GETPC());
642     return ret;
643 }
644
645 /* 64-bit FP multiply and subtract */
646 uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
647                       uint64_t f2, uint64_t f3)
648 {
649     float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
650                                  &env->fpu_status);
651     handle_exceptions(env, GETPC());
652     return ret;
653 }
654
655 /* test data class 32-bit */
656 uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
657 {
658     float32 v1 = f1;
659     int neg = float32_is_neg(v1);
660     uint32_t cc = 0;
661
662     if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
663         (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
664         (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
665         (float32_is_signaling_nan(v1, &env->fpu_status) &&
666          (m2 & (1 << (1-neg))))) {
667         cc = 1;
668     } else if (m2 & (1 << (9-neg))) {
669         /* assume normalized number */
670         cc = 1;
671     }
672     /* FIXME: denormalized? */
673     return cc;
674 }
675
676 /* test data class 64-bit */
677 uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
678 {
679     int neg = float64_is_neg(v1);
680     uint32_t cc = 0;
681
682     if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
683         (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
684         (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
685         (float64_is_signaling_nan(v1, &env->fpu_status) &&
686          (m2 & (1 << (1-neg))))) {
687         cc = 1;
688     } else if (m2 & (1 << (9-neg))) {
689         /* assume normalized number */
690         cc = 1;
691     }
692     /* FIXME: denormalized? */
693     return cc;
694 }
695
696 /* test data class 128-bit */
697 uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
698                       uint64_t al, uint64_t m2)
699 {
700     float128 v1 = make_float128(ah, al);
701     int neg = float128_is_neg(v1);
702     uint32_t cc = 0;
703
704     if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
705         (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
706         (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
707         (float128_is_signaling_nan(v1, &env->fpu_status) &&
708          (m2 & (1 << (1-neg))))) {
709         cc = 1;
710     } else if (m2 & (1 << (9-neg))) {
711         /* assume normalized number */
712         cc = 1;
713     }
714     /* FIXME: denormalized? */
715     return cc;
716 }
717
718 /* square root 32-bit */
719 uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
720 {
721     float32 ret = float32_sqrt(f2, &env->fpu_status);
722     handle_exceptions(env, GETPC());
723     return ret;
724 }
725
726 /* square root 64-bit */
727 uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
728 {
729     float64 ret = float64_sqrt(f2, &env->fpu_status);
730     handle_exceptions(env, GETPC());
731     return ret;
732 }
733
734 /* square root 128-bit */
735 uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
736 {
737     float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
738     handle_exceptions(env, GETPC());
739     return RET128(ret);
740 }
741
742 static const int fpc_to_rnd[4] = {
743     float_round_nearest_even,
744     float_round_to_zero,
745     float_round_up,
746     float_round_down
747 };
748
749 /* set fpc */
750 void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
751 {
752     /* Install everything in the main FPC.  */
753     env->fpc = fpc;
754
755     /* Install the rounding mode in the shadow fpu_status.  */
756     set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
757 }
758
759 /* set fpc and signal */
760 void HELPER(sfas)(CPUS390XState *env, uint64_t val)
761 {
762     uint32_t signalling = env->fpc;
763     uint32_t source = val;
764     uint32_t s390_exc;
765
766     /* The contents of the source operand are placed in the FPC register;
767        then the flags in the FPC register are set to the logical OR of the
768        signalling flags and the source flags.  */
769     env->fpc = source | (signalling & 0x00ff0000);
770     set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
771
772     /* If any signalling flag is 1 and the corresponding source mask
773        is also 1, a simulated-iee-exception trap occurs.  */
774     s390_exc = (signalling >> 16) & (source >> 24);
775     if (s390_exc) {
776         ieee_exception(env, s390_exc | 3, GETPC());
777     }
778 }
This page took 0.066017 seconds and 4 git commands to generate.