2 * S/390 FPU helper routines
4 * Copyright (c) 2009 Ulrich Hecht
5 * Copyright (c) 2009 Alexander Graf
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.
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.
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/>.
21 #include "qemu/osdep.h"
23 #include "exec/exec-all.h"
24 #include "exec/cpu_ldst.h"
25 #include "exec/helper-proto.h"
27 /* #define DEBUG_HELPER */
29 #define HELPER_LOG(x...) qemu_log(x)
31 #define HELPER_LOG(x...)
34 #define RET128(F) (env->retxl = F.low, F.high)
36 #define convert_bit(mask, from, to) \
38 ? (mask / (from / to)) & to \
39 : (mask & from) * (to / from))
41 static void ieee_exception(CPUS390XState
*env
, uint32_t dxc
, uintptr_t retaddr
)
43 /* Install the DXC code. */
44 env
->fpc
= (env
->fpc
& ~0xff00) | (dxc
<< 8);
46 runtime_exception(env
, PGM_DATA
, retaddr
);
49 /* Should be called after any operation that may raise IEEE exceptions. */
50 static void handle_exceptions(CPUS390XState
*env
, uintptr_t retaddr
)
52 unsigned s390_exc
, qemu_exc
;
54 /* Get the exceptions raised by the current operation. Reset the
55 fpu_status contents so that the next operation has a clean slate. */
56 qemu_exc
= env
->fpu_status
.float_exception_flags
;
60 env
->fpu_status
.float_exception_flags
= 0;
62 /* Convert softfloat exception bits to s390 exception bits. */
64 s390_exc
|= convert_bit(qemu_exc
, float_flag_invalid
, 0x80);
65 s390_exc
|= convert_bit(qemu_exc
, float_flag_divbyzero
, 0x40);
66 s390_exc
|= convert_bit(qemu_exc
, float_flag_overflow
, 0x20);
67 s390_exc
|= convert_bit(qemu_exc
, float_flag_underflow
, 0x10);
68 s390_exc
|= convert_bit(qemu_exc
, float_flag_inexact
, 0x08);
70 /* Install the exceptions that we raised. */
71 env
->fpc
|= s390_exc
<< 16;
73 /* Send signals for enabled exceptions. */
74 s390_exc
&= env
->fpc
>> 24;
76 ieee_exception(env
, s390_exc
, retaddr
);
80 static inline int float_comp_to_cc(CPUS390XState
*env
, int float_compare
)
82 S390CPU
*cpu
= s390_env_get_cpu(env
);
84 switch (float_compare
) {
85 case float_relation_equal
:
87 case float_relation_less
:
89 case float_relation_greater
:
91 case float_relation_unordered
:
94 cpu_abort(CPU(cpu
), "unknown return value for float compare\n");
98 /* condition codes for unary FP ops */
99 uint32_t set_cc_nz_f32(float32 v
)
101 if (float32_is_any_nan(v
)) {
103 } else if (float32_is_zero(v
)) {
105 } else if (float32_is_neg(v
)) {
112 uint32_t set_cc_nz_f64(float64 v
)
114 if (float64_is_any_nan(v
)) {
116 } else if (float64_is_zero(v
)) {
118 } else if (float64_is_neg(v
)) {
125 uint32_t set_cc_nz_f128(float128 v
)
127 if (float128_is_any_nan(v
)) {
129 } else if (float128_is_zero(v
)) {
131 } else if (float128_is_neg(v
)) {
138 /* 32-bit FP addition */
139 uint64_t HELPER(aeb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
141 float32 ret
= float32_add(f1
, f2
, &env
->fpu_status
);
142 handle_exceptions(env
, GETPC());
146 /* 64-bit FP addition */
147 uint64_t HELPER(adb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
149 float64 ret
= float64_add(f1
, f2
, &env
->fpu_status
);
150 handle_exceptions(env
, GETPC());
154 /* 128-bit FP addition */
155 uint64_t HELPER(axb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
,
156 uint64_t bh
, uint64_t bl
)
158 float128 ret
= float128_add(make_float128(ah
, al
),
159 make_float128(bh
, bl
),
161 handle_exceptions(env
, GETPC());
165 /* 32-bit FP subtraction */
166 uint64_t HELPER(seb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
168 float32 ret
= float32_sub(f1
, f2
, &env
->fpu_status
);
169 handle_exceptions(env
, GETPC());
173 /* 64-bit FP subtraction */
174 uint64_t HELPER(sdb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
176 float64 ret
= float64_sub(f1
, f2
, &env
->fpu_status
);
177 handle_exceptions(env
, GETPC());
181 /* 128-bit FP subtraction */
182 uint64_t HELPER(sxb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
,
183 uint64_t bh
, uint64_t bl
)
185 float128 ret
= float128_sub(make_float128(ah
, al
),
186 make_float128(bh
, bl
),
188 handle_exceptions(env
, GETPC());
192 /* 32-bit FP division */
193 uint64_t HELPER(deb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
195 float32 ret
= float32_div(f1
, f2
, &env
->fpu_status
);
196 handle_exceptions(env
, GETPC());
200 /* 64-bit FP division */
201 uint64_t HELPER(ddb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
203 float64 ret
= float64_div(f1
, f2
, &env
->fpu_status
);
204 handle_exceptions(env
, GETPC());
208 /* 128-bit FP division */
209 uint64_t HELPER(dxb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
,
210 uint64_t bh
, uint64_t bl
)
212 float128 ret
= float128_div(make_float128(ah
, al
),
213 make_float128(bh
, bl
),
215 handle_exceptions(env
, GETPC());
219 /* 32-bit FP multiplication */
220 uint64_t HELPER(meeb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
222 float32 ret
= float32_mul(f1
, f2
, &env
->fpu_status
);
223 handle_exceptions(env
, GETPC());
227 /* 64-bit FP multiplication */
228 uint64_t HELPER(mdb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
230 float64 ret
= float64_mul(f1
, f2
, &env
->fpu_status
);
231 handle_exceptions(env
, GETPC());
235 /* 64/32-bit FP multiplication */
236 uint64_t HELPER(mdeb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
238 float64 ret
= float32_to_float64(f2
, &env
->fpu_status
);
239 ret
= float64_mul(f1
, ret
, &env
->fpu_status
);
240 handle_exceptions(env
, GETPC());
244 /* 128-bit FP multiplication */
245 uint64_t HELPER(mxb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
,
246 uint64_t bh
, uint64_t bl
)
248 float128 ret
= float128_mul(make_float128(ah
, al
),
249 make_float128(bh
, bl
),
251 handle_exceptions(env
, GETPC());
255 /* 128/64-bit FP multiplication */
256 uint64_t HELPER(mxdb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
,
259 float128 ret
= float64_to_float128(f2
, &env
->fpu_status
);
260 ret
= float128_mul(make_float128(ah
, al
), ret
, &env
->fpu_status
);
261 handle_exceptions(env
, GETPC());
265 /* convert 32-bit float to 64-bit float */
266 uint64_t HELPER(ldeb
)(CPUS390XState
*env
, uint64_t f2
)
268 float64 ret
= float32_to_float64(f2
, &env
->fpu_status
);
269 handle_exceptions(env
, GETPC());
270 return float64_maybe_silence_nan(ret
, &env
->fpu_status
);
273 /* convert 128-bit float to 64-bit float */
274 uint64_t HELPER(ldxb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
)
276 float64 ret
= float128_to_float64(make_float128(ah
, al
), &env
->fpu_status
);
277 handle_exceptions(env
, GETPC());
278 return float64_maybe_silence_nan(ret
, &env
->fpu_status
);
281 /* convert 64-bit float to 128-bit float */
282 uint64_t HELPER(lxdb
)(CPUS390XState
*env
, uint64_t f2
)
284 float128 ret
= float64_to_float128(f2
, &env
->fpu_status
);
285 handle_exceptions(env
, GETPC());
286 return RET128(float128_maybe_silence_nan(ret
, &env
->fpu_status
));
289 /* convert 32-bit float to 128-bit float */
290 uint64_t HELPER(lxeb
)(CPUS390XState
*env
, uint64_t f2
)
292 float128 ret
= float32_to_float128(f2
, &env
->fpu_status
);
293 handle_exceptions(env
, GETPC());
294 return RET128(float128_maybe_silence_nan(ret
, &env
->fpu_status
));
297 /* convert 64-bit float to 32-bit float */
298 uint64_t HELPER(ledb
)(CPUS390XState
*env
, uint64_t f2
)
300 float32 ret
= float64_to_float32(f2
, &env
->fpu_status
);
301 handle_exceptions(env
, GETPC());
302 return float32_maybe_silence_nan(ret
, &env
->fpu_status
);
305 /* convert 128-bit float to 32-bit float */
306 uint64_t HELPER(lexb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
)
308 float32 ret
= float128_to_float32(make_float128(ah
, al
), &env
->fpu_status
);
309 handle_exceptions(env
, GETPC());
310 return float32_maybe_silence_nan(ret
, &env
->fpu_status
);
313 /* 32-bit FP compare */
314 uint32_t HELPER(ceb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
316 int cmp
= float32_compare_quiet(f1
, f2
, &env
->fpu_status
);
317 handle_exceptions(env
, GETPC());
318 return float_comp_to_cc(env
, cmp
);
321 /* 64-bit FP compare */
322 uint32_t HELPER(cdb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
324 int cmp
= float64_compare_quiet(f1
, f2
, &env
->fpu_status
);
325 handle_exceptions(env
, GETPC());
326 return float_comp_to_cc(env
, cmp
);
329 /* 128-bit FP compare */
330 uint32_t HELPER(cxb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
,
331 uint64_t bh
, uint64_t bl
)
333 int cmp
= float128_compare_quiet(make_float128(ah
, al
),
334 make_float128(bh
, bl
),
336 handle_exceptions(env
, GETPC());
337 return float_comp_to_cc(env
, cmp
);
340 static int swap_round_mode(CPUS390XState
*env
, int m3
)
342 int ret
= env
->fpu_status
.float_rounding_mode
;
348 /* biased round no nearest */
350 /* round to nearest */
351 set_float_rounding_mode(float_round_nearest_even
, &env
->fpu_status
);
355 set_float_rounding_mode(float_round_to_zero
, &env
->fpu_status
);
359 set_float_rounding_mode(float_round_up
, &env
->fpu_status
);
363 set_float_rounding_mode(float_round_down
, &env
->fpu_status
);
369 /* convert 64-bit int to 32-bit float */
370 uint64_t HELPER(cegb
)(CPUS390XState
*env
, int64_t v2
, uint32_t m3
)
372 int hold
= swap_round_mode(env
, m3
);
373 float32 ret
= int64_to_float32(v2
, &env
->fpu_status
);
374 set_float_rounding_mode(hold
, &env
->fpu_status
);
375 handle_exceptions(env
, GETPC());
379 /* convert 64-bit int to 64-bit float */
380 uint64_t HELPER(cdgb
)(CPUS390XState
*env
, int64_t v2
, uint32_t m3
)
382 int hold
= swap_round_mode(env
, m3
);
383 float64 ret
= int64_to_float64(v2
, &env
->fpu_status
);
384 set_float_rounding_mode(hold
, &env
->fpu_status
);
385 handle_exceptions(env
, GETPC());
389 /* convert 64-bit int to 128-bit float */
390 uint64_t HELPER(cxgb
)(CPUS390XState
*env
, int64_t v2
, uint32_t m3
)
392 int hold
= swap_round_mode(env
, m3
);
393 float128 ret
= int64_to_float128(v2
, &env
->fpu_status
);
394 set_float_rounding_mode(hold
, &env
->fpu_status
);
395 handle_exceptions(env
, GETPC());
399 /* convert 64-bit uint to 32-bit float */
400 uint64_t HELPER(celgb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
402 int hold
= swap_round_mode(env
, m3
);
403 float32 ret
= uint64_to_float32(v2
, &env
->fpu_status
);
404 set_float_rounding_mode(hold
, &env
->fpu_status
);
405 handle_exceptions(env
, GETPC());
409 /* convert 64-bit uint to 64-bit float */
410 uint64_t HELPER(cdlgb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
412 int hold
= swap_round_mode(env
, m3
);
413 float64 ret
= uint64_to_float64(v2
, &env
->fpu_status
);
414 set_float_rounding_mode(hold
, &env
->fpu_status
);
415 handle_exceptions(env
, GETPC());
419 /* convert 64-bit uint to 128-bit float */
420 uint64_t HELPER(cxlgb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
422 int hold
= swap_round_mode(env
, m3
);
423 float128 ret
= uint64_to_float128(v2
, &env
->fpu_status
);
424 set_float_rounding_mode(hold
, &env
->fpu_status
);
425 handle_exceptions(env
, GETPC());
429 /* convert 32-bit float to 64-bit int */
430 uint64_t HELPER(cgeb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
432 int hold
= swap_round_mode(env
, m3
);
433 int64_t ret
= float32_to_int64(v2
, &env
->fpu_status
);
434 set_float_rounding_mode(hold
, &env
->fpu_status
);
435 handle_exceptions(env
, GETPC());
439 /* convert 64-bit float to 64-bit int */
440 uint64_t HELPER(cgdb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
442 int hold
= swap_round_mode(env
, m3
);
443 int64_t ret
= float64_to_int64(v2
, &env
->fpu_status
);
444 set_float_rounding_mode(hold
, &env
->fpu_status
);
445 handle_exceptions(env
, GETPC());
449 /* convert 128-bit float to 64-bit int */
450 uint64_t HELPER(cgxb
)(CPUS390XState
*env
, uint64_t h
, uint64_t l
, uint32_t m3
)
452 int hold
= swap_round_mode(env
, m3
);
453 float128 v2
= make_float128(h
, l
);
454 int64_t ret
= float128_to_int64(v2
, &env
->fpu_status
);
455 set_float_rounding_mode(hold
, &env
->fpu_status
);
456 handle_exceptions(env
, GETPC());
460 /* convert 32-bit float to 32-bit int */
461 uint64_t HELPER(cfeb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
463 int hold
= swap_round_mode(env
, m3
);
464 int32_t ret
= float32_to_int32(v2
, &env
->fpu_status
);
465 set_float_rounding_mode(hold
, &env
->fpu_status
);
466 handle_exceptions(env
, GETPC());
470 /* convert 64-bit float to 32-bit int */
471 uint64_t HELPER(cfdb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
473 int hold
= swap_round_mode(env
, m3
);
474 int32_t ret
= float64_to_int32(v2
, &env
->fpu_status
);
475 set_float_rounding_mode(hold
, &env
->fpu_status
);
476 handle_exceptions(env
, GETPC());
480 /* convert 128-bit float to 32-bit int */
481 uint64_t HELPER(cfxb
)(CPUS390XState
*env
, uint64_t h
, uint64_t l
, uint32_t m3
)
483 int hold
= swap_round_mode(env
, m3
);
484 float128 v2
= make_float128(h
, l
);
485 int32_t ret
= float128_to_int32(v2
, &env
->fpu_status
);
486 set_float_rounding_mode(hold
, &env
->fpu_status
);
487 handle_exceptions(env
, GETPC());
491 /* convert 32-bit float to 64-bit uint */
492 uint64_t HELPER(clgeb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
494 int hold
= swap_round_mode(env
, m3
);
496 v2
= float32_to_float64(v2
, &env
->fpu_status
);
497 ret
= float64_to_uint64(v2
, &env
->fpu_status
);
498 set_float_rounding_mode(hold
, &env
->fpu_status
);
499 handle_exceptions(env
, GETPC());
503 /* convert 64-bit float to 64-bit uint */
504 uint64_t HELPER(clgdb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
506 int hold
= swap_round_mode(env
, m3
);
507 uint64_t ret
= float64_to_uint64(v2
, &env
->fpu_status
);
508 set_float_rounding_mode(hold
, &env
->fpu_status
);
509 handle_exceptions(env
, GETPC());
513 /* convert 128-bit float to 64-bit uint */
514 uint64_t HELPER(clgxb
)(CPUS390XState
*env
, uint64_t h
, uint64_t l
, uint32_t m3
)
516 int hold
= swap_round_mode(env
, m3
);
517 float128 v2
= make_float128(h
, l
);
518 /* ??? Not 100% correct. */
519 uint64_t ret
= float128_to_int64(v2
, &env
->fpu_status
);
520 set_float_rounding_mode(hold
, &env
->fpu_status
);
521 handle_exceptions(env
, GETPC());
525 /* convert 32-bit float to 32-bit uint */
526 uint64_t HELPER(clfeb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
528 int hold
= swap_round_mode(env
, m3
);
529 uint32_t ret
= float32_to_uint32(v2
, &env
->fpu_status
);
530 set_float_rounding_mode(hold
, &env
->fpu_status
);
531 handle_exceptions(env
, GETPC());
535 /* convert 64-bit float to 32-bit uint */
536 uint64_t HELPER(clfdb
)(CPUS390XState
*env
, uint64_t v2
, uint32_t m3
)
538 int hold
= swap_round_mode(env
, m3
);
539 uint32_t ret
= float64_to_uint32(v2
, &env
->fpu_status
);
540 set_float_rounding_mode(hold
, &env
->fpu_status
);
541 handle_exceptions(env
, GETPC());
545 /* convert 128-bit float to 32-bit uint */
546 uint64_t HELPER(clfxb
)(CPUS390XState
*env
, uint64_t h
, uint64_t l
, uint32_t m3
)
548 int hold
= swap_round_mode(env
, m3
);
549 float128 v2
= make_float128(h
, l
);
550 /* Not 100% correct. */
551 uint32_t ret
= float128_to_int64(v2
, &env
->fpu_status
);
552 set_float_rounding_mode(hold
, &env
->fpu_status
);
553 handle_exceptions(env
, GETPC());
557 /* round to integer 32-bit */
558 uint64_t HELPER(fieb
)(CPUS390XState
*env
, uint64_t f2
, uint32_t m3
)
560 int hold
= swap_round_mode(env
, m3
);
561 float32 ret
= float32_round_to_int(f2
, &env
->fpu_status
);
562 set_float_rounding_mode(hold
, &env
->fpu_status
);
563 handle_exceptions(env
, GETPC());
567 /* round to integer 64-bit */
568 uint64_t HELPER(fidb
)(CPUS390XState
*env
, uint64_t f2
, uint32_t m3
)
570 int hold
= swap_round_mode(env
, m3
);
571 float64 ret
= float64_round_to_int(f2
, &env
->fpu_status
);
572 set_float_rounding_mode(hold
, &env
->fpu_status
);
573 handle_exceptions(env
, GETPC());
577 /* round to integer 128-bit */
578 uint64_t HELPER(fixb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
, uint32_t m3
)
580 int hold
= swap_round_mode(env
, m3
);
581 float128 ret
= float128_round_to_int(make_float128(ah
, al
),
583 set_float_rounding_mode(hold
, &env
->fpu_status
);
584 handle_exceptions(env
, GETPC());
588 /* 32-bit FP compare and signal */
589 uint32_t HELPER(keb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
591 int cmp
= float32_compare(f1
, f2
, &env
->fpu_status
);
592 handle_exceptions(env
, GETPC());
593 return float_comp_to_cc(env
, cmp
);
596 /* 64-bit FP compare and signal */
597 uint32_t HELPER(kdb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t f2
)
599 int cmp
= float64_compare(f1
, f2
, &env
->fpu_status
);
600 handle_exceptions(env
, GETPC());
601 return float_comp_to_cc(env
, cmp
);
604 /* 128-bit FP compare and signal */
605 uint32_t HELPER(kxb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
,
606 uint64_t bh
, uint64_t bl
)
608 int cmp
= float128_compare(make_float128(ah
, al
),
609 make_float128(bh
, bl
),
611 handle_exceptions(env
, GETPC());
612 return float_comp_to_cc(env
, cmp
);
615 /* 32-bit FP multiply and add */
616 uint64_t HELPER(maeb
)(CPUS390XState
*env
, uint64_t f1
,
617 uint64_t f2
, uint64_t f3
)
619 float32 ret
= float32_muladd(f2
, f3
, f1
, 0, &env
->fpu_status
);
620 handle_exceptions(env
, GETPC());
624 /* 64-bit FP multiply and add */
625 uint64_t HELPER(madb
)(CPUS390XState
*env
, uint64_t f1
,
626 uint64_t f2
, uint64_t f3
)
628 float64 ret
= float64_muladd(f2
, f3
, f1
, 0, &env
->fpu_status
);
629 handle_exceptions(env
, GETPC());
633 /* 32-bit FP multiply and subtract */
634 uint64_t HELPER(mseb
)(CPUS390XState
*env
, uint64_t f1
,
635 uint64_t f2
, uint64_t f3
)
637 float32 ret
= float32_muladd(f2
, f3
, f1
, float_muladd_negate_c
,
639 handle_exceptions(env
, GETPC());
643 /* 64-bit FP multiply and subtract */
644 uint64_t HELPER(msdb
)(CPUS390XState
*env
, uint64_t f1
,
645 uint64_t f2
, uint64_t f3
)
647 float64 ret
= float64_muladd(f2
, f3
, f1
, float_muladd_negate_c
,
649 handle_exceptions(env
, GETPC());
653 /* test data class 32-bit */
654 uint32_t HELPER(tceb
)(CPUS390XState
*env
, uint64_t f1
, uint64_t m2
)
657 int neg
= float32_is_neg(v1
);
660 if ((float32_is_zero(v1
) && (m2
& (1 << (11-neg
)))) ||
661 (float32_is_infinity(v1
) && (m2
& (1 << (5-neg
)))) ||
662 (float32_is_any_nan(v1
) && (m2
& (1 << (3-neg
)))) ||
663 (float32_is_signaling_nan(v1
, &env
->fpu_status
) &&
664 (m2
& (1 << (1-neg
))))) {
666 } else if (m2
& (1 << (9-neg
))) {
667 /* assume normalized number */
670 /* FIXME: denormalized? */
674 /* test data class 64-bit */
675 uint32_t HELPER(tcdb
)(CPUS390XState
*env
, uint64_t v1
, uint64_t m2
)
677 int neg
= float64_is_neg(v1
);
680 if ((float64_is_zero(v1
) && (m2
& (1 << (11-neg
)))) ||
681 (float64_is_infinity(v1
) && (m2
& (1 << (5-neg
)))) ||
682 (float64_is_any_nan(v1
) && (m2
& (1 << (3-neg
)))) ||
683 (float64_is_signaling_nan(v1
, &env
->fpu_status
) &&
684 (m2
& (1 << (1-neg
))))) {
686 } else if (m2
& (1 << (9-neg
))) {
687 /* assume normalized number */
690 /* FIXME: denormalized? */
694 /* test data class 128-bit */
695 uint32_t HELPER(tcxb
)(CPUS390XState
*env
, uint64_t ah
,
696 uint64_t al
, uint64_t m2
)
698 float128 v1
= make_float128(ah
, al
);
699 int neg
= float128_is_neg(v1
);
702 if ((float128_is_zero(v1
) && (m2
& (1 << (11-neg
)))) ||
703 (float128_is_infinity(v1
) && (m2
& (1 << (5-neg
)))) ||
704 (float128_is_any_nan(v1
) && (m2
& (1 << (3-neg
)))) ||
705 (float128_is_signaling_nan(v1
, &env
->fpu_status
) &&
706 (m2
& (1 << (1-neg
))))) {
708 } else if (m2
& (1 << (9-neg
))) {
709 /* assume normalized number */
712 /* FIXME: denormalized? */
716 /* square root 32-bit */
717 uint64_t HELPER(sqeb
)(CPUS390XState
*env
, uint64_t f2
)
719 float32 ret
= float32_sqrt(f2
, &env
->fpu_status
);
720 handle_exceptions(env
, GETPC());
724 /* square root 64-bit */
725 uint64_t HELPER(sqdb
)(CPUS390XState
*env
, uint64_t f2
)
727 float64 ret
= float64_sqrt(f2
, &env
->fpu_status
);
728 handle_exceptions(env
, GETPC());
732 /* square root 128-bit */
733 uint64_t HELPER(sqxb
)(CPUS390XState
*env
, uint64_t ah
, uint64_t al
)
735 float128 ret
= float128_sqrt(make_float128(ah
, al
), &env
->fpu_status
);
736 handle_exceptions(env
, GETPC());
740 static const int fpc_to_rnd
[4] = {
741 float_round_nearest_even
,
748 void HELPER(sfpc
)(CPUS390XState
*env
, uint64_t fpc
)
750 /* Install everything in the main FPC. */
753 /* Install the rounding mode in the shadow fpu_status. */
754 set_float_rounding_mode(fpc_to_rnd
[fpc
& 3], &env
->fpu_status
);
757 /* set fpc and signal */
758 void HELPER(sfas
)(CPUS390XState
*env
, uint64_t val
)
760 uint32_t signalling
= env
->fpc
;
761 uint32_t source
= val
;
764 /* The contents of the source operand are placed in the FPC register;
765 then the flags in the FPC register are set to the logical OR of the
766 signalling flags and the source flags. */
767 env
->fpc
= source
| (signalling
& 0x00ff0000);
768 set_float_rounding_mode(fpc_to_rnd
[source
& 3], &env
->fpu_status
);
770 /* If any signalling flag is 1 and the corresponding source mask
771 is also 1, a simulated-iee-exception trap occurs. */
772 s390_exc
= (signalling
>> 16) & (source
>> 24);
774 ieee_exception(env
, s390_exc
| 3, GETPC());