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