]> git.proxmox.com Git - mirror_qemu.git/blame - target-s390x/fpu_helper.c
9pfs: forbid . and .. in file names
[mirror_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
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
9615495a 21#include "qemu/osdep.h"
e72ca652 22#include "cpu.h"
63c91552 23#include "exec/exec-all.h"
f08b6170 24#include "exec/cpu_ldst.h"
2ef6175a 25#include "exec/helper-proto.h"
e72ca652 26
e72ca652
BS
27/* #define DEBUG_HELPER */
28#ifdef DEBUG_HELPER
29#define HELPER_LOG(x...) qemu_log(x)
30#else
31#define HELPER_LOG(x...)
32#endif
33
587626f8
RH
34#define RET128(F) (env->retxl = F.low, F.high)
35
36#define convert_bit(mask, from, to) \
37 (to < from \
38 ? (mask / (from / to)) & to \
39 : (mask & from) * (to / from))
40
41static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
42{
43 /* Install the DXC code. */
44 env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
45 /* Trap. */
46 runtime_exception(env, PGM_DATA, retaddr);
47}
48
49/* Should be called after any operation that may raise IEEE exceptions. */
50static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
51{
52 unsigned s390_exc, qemu_exc;
53
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;
57 if (qemu_exc == 0) {
58 return;
59 }
60 env->fpu_status.float_exception_flags = 0;
61
62 /* Convert softfloat exception bits to s390 exception bits. */
63 s390_exc = 0;
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);
69
70 /* Install the exceptions that we raised. */
71 env->fpc |= s390_exc << 16;
72
73 /* Send signals for enabled exceptions. */
74 s390_exc &= env->fpc >> 24;
75 if (s390_exc) {
76 ieee_exception(env, s390_exc, retaddr);
77 }
78}
79
449c0d70 80static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
e72ca652 81{
a47dddd7
AF
82 S390CPU *cpu = s390_env_get_cpu(env);
83
e72ca652
BS
84 switch (float_compare) {
85 case float_relation_equal:
86 return 0;
87 case float_relation_less:
88 return 1;
89 case float_relation_greater:
90 return 2;
91 case float_relation_unordered:
92 return 3;
93 default:
a47dddd7 94 cpu_abort(CPU(cpu), "unknown return value for float compare\n");
e72ca652
BS
95 }
96}
97
e72ca652
BS
98/* condition codes for unary FP ops */
99uint32_t set_cc_nz_f32(float32 v)
100{
101 if (float32_is_any_nan(v)) {
102 return 3;
103 } else if (float32_is_zero(v)) {
104 return 0;
105 } else if (float32_is_neg(v)) {
106 return 1;
107 } else {
108 return 2;
109 }
110}
111
112uint32_t set_cc_nz_f64(float64 v)
113{
114 if (float64_is_any_nan(v)) {
115 return 3;
116 } else if (float64_is_zero(v)) {
117 return 0;
118 } else if (float64_is_neg(v)) {
119 return 1;
120 } else {
121 return 2;
122 }
123}
124
587626f8 125uint32_t set_cc_nz_f128(float128 v)
e72ca652
BS
126{
127 if (float128_is_any_nan(v)) {
128 return 3;
129 } else if (float128_is_zero(v)) {
130 return 0;
131 } else if (float128_is_neg(v)) {
132 return 1;
133 } else {
134 return 2;
135 }
136}
137
587626f8
RH
138/* 32-bit FP addition */
139uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 140{
587626f8
RH
141 float32 ret = float32_add(f1, f2, &env->fpu_status);
142 handle_exceptions(env, GETPC());
143 return ret;
e72ca652
BS
144}
145
587626f8
RH
146/* 64-bit FP addition */
147uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 148{
587626f8
RH
149 float64 ret = float64_add(f1, f2, &env->fpu_status);
150 handle_exceptions(env, GETPC());
151 return ret;
152}
e72ca652 153
587626f8
RH
154/* 128-bit FP addition */
155uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
156 uint64_t bh, uint64_t bl)
157{
158 float128 ret = float128_add(make_float128(ah, al),
159 make_float128(bh, bl),
160 &env->fpu_status);
161 handle_exceptions(env, GETPC());
162 return RET128(ret);
e72ca652
BS
163}
164
1a800a2d
RH
165/* 32-bit FP subtraction */
166uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 167{
1a800a2d
RH
168 float32 ret = float32_sub(f1, f2, &env->fpu_status);
169 handle_exceptions(env, GETPC());
170 return ret;
e72ca652
BS
171}
172
1a800a2d
RH
173/* 64-bit FP subtraction */
174uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 175{
1a800a2d
RH
176 float64 ret = float64_sub(f1, f2, &env->fpu_status);
177 handle_exceptions(env, GETPC());
178 return ret;
179}
e72ca652 180
1a800a2d
RH
181/* 128-bit FP subtraction */
182uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
183 uint64_t bh, uint64_t bl)
184{
185 float128 ret = float128_sub(make_float128(ah, al),
186 make_float128(bh, bl),
187 &env->fpu_status);
188 handle_exceptions(env, GETPC());
189 return RET128(ret);
e72ca652
BS
190}
191
f08a5c31
RH
192/* 32-bit FP division */
193uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 194{
f08a5c31
RH
195 float32 ret = float32_div(f1, f2, &env->fpu_status);
196 handle_exceptions(env, GETPC());
197 return ret;
e72ca652
BS
198}
199
f08a5c31
RH
200/* 64-bit FP division */
201uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 202{
f08a5c31
RH
203 float64 ret = float64_div(f1, f2, &env->fpu_status);
204 handle_exceptions(env, GETPC());
205 return ret;
206}
e72ca652 207
f08a5c31
RH
208/* 128-bit FP division */
209uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
210 uint64_t bh, uint64_t bl)
211{
212 float128 ret = float128_div(make_float128(ah, al),
213 make_float128(bh, bl),
214 &env->fpu_status);
215 handle_exceptions(env, GETPC());
216 return RET128(ret);
e72ca652
BS
217}
218
83b00736
RH
219/* 32-bit FP multiplication */
220uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 221{
83b00736
RH
222 float32 ret = float32_mul(f1, f2, &env->fpu_status);
223 handle_exceptions(env, GETPC());
224 return ret;
e72ca652
BS
225}
226
83b00736
RH
227/* 64-bit FP multiplication */
228uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 229{
83b00736
RH
230 float64 ret = float64_mul(f1, f2, &env->fpu_status);
231 handle_exceptions(env, GETPC());
232 return ret;
233}
e72ca652 234
83b00736
RH
235/* 64/32-bit FP multiplication */
236uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
237{
238 float64 ret = float32_to_float64(f2, &env->fpu_status);
239 ret = float64_mul(f1, ret, &env->fpu_status);
240 handle_exceptions(env, GETPC());
241 return ret;
242}
243
244/* 128-bit FP multiplication */
245uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
246 uint64_t bh, uint64_t bl)
247{
248 float128 ret = float128_mul(make_float128(ah, al),
249 make_float128(bh, bl),
250 &env->fpu_status);
251 handle_exceptions(env, GETPC());
252 return RET128(ret);
253}
254
255/* 128/64-bit FP multiplication */
256uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
257 uint64_t f2)
258{
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());
262 return RET128(ret);
e72ca652
BS
263}
264
265/* convert 32-bit float to 64-bit float */
587626f8 266uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
e72ca652 267{
587626f8
RH
268 float64 ret = float32_to_float64(f2, &env->fpu_status);
269 handle_exceptions(env, GETPC());
af39bc8c 270 return float64_maybe_silence_nan(ret, &env->fpu_status);
e72ca652
BS
271}
272
273/* convert 128-bit float to 64-bit float */
587626f8 274uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
e72ca652 275{
587626f8
RH
276 float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
277 handle_exceptions(env, GETPC());
af39bc8c 278 return float64_maybe_silence_nan(ret, &env->fpu_status);
e72ca652
BS
279}
280
281/* convert 64-bit float to 128-bit float */
587626f8 282uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
e72ca652 283{
587626f8
RH
284 float128 ret = float64_to_float128(f2, &env->fpu_status);
285 handle_exceptions(env, GETPC());
af39bc8c 286 return RET128(float128_maybe_silence_nan(ret, &env->fpu_status));
587626f8 287}
e72ca652 288
587626f8
RH
289/* convert 32-bit float to 128-bit float */
290uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
291{
292 float128 ret = float32_to_float128(f2, &env->fpu_status);
293 handle_exceptions(env, GETPC());
af39bc8c 294 return RET128(float128_maybe_silence_nan(ret, &env->fpu_status));
e72ca652
BS
295}
296
297/* convert 64-bit float to 32-bit float */
587626f8 298uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
e72ca652 299{
587626f8
RH
300 float32 ret = float64_to_float32(f2, &env->fpu_status);
301 handle_exceptions(env, GETPC());
af39bc8c 302 return float32_maybe_silence_nan(ret, &env->fpu_status);
e72ca652
BS
303}
304
305/* convert 128-bit float to 32-bit float */
587626f8 306uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
e72ca652 307{
587626f8
RH
308 float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
309 handle_exceptions(env, GETPC());
af39bc8c 310 return float32_maybe_silence_nan(ret, &env->fpu_status);
e72ca652
BS
311}
312
587626f8
RH
313/* 32-bit FP compare */
314uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 315{
587626f8
RH
316 int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
317 handle_exceptions(env, GETPC());
318 return float_comp_to_cc(env, cmp);
e72ca652
BS
319}
320
587626f8
RH
321/* 64-bit FP compare */
322uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
e72ca652 323{
587626f8
RH
324 int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
325 handle_exceptions(env, GETPC());
326 return float_comp_to_cc(env, cmp);
e72ca652
BS
327}
328
587626f8
RH
329/* 128-bit FP compare */
330uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
331 uint64_t bh, uint64_t bl)
e72ca652 332{
587626f8
RH
333 int cmp = float128_compare_quiet(make_float128(ah, al),
334 make_float128(bh, bl),
335 &env->fpu_status);
336 handle_exceptions(env, GETPC());
337 return float_comp_to_cc(env, cmp);
e72ca652
BS
338}
339
68c8bd93 340static int swap_round_mode(CPUS390XState *env, int m3)
e72ca652 341{
68c8bd93 342 int ret = env->fpu_status.float_rounding_mode;
e72ca652
BS
343 switch (m3) {
344 case 0:
345 /* current mode */
346 break;
347 case 1:
348 /* biased round no nearest */
349 case 4:
350 /* round to nearest */
351 set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
352 break;
353 case 5:
354 /* round to zero */
355 set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
356 break;
357 case 6:
358 /* round to +inf */
359 set_float_rounding_mode(float_round_up, &env->fpu_status);
360 break;
361 case 7:
362 /* round to -inf */
363 set_float_rounding_mode(float_round_down, &env->fpu_status);
364 break;
365 }
68c8bd93 366 return ret;
e72ca652
BS
367}
368
683bb9a8
RH
369/* convert 64-bit int to 32-bit float */
370uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
371{
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());
376 return ret;
377}
378
379/* convert 64-bit int to 64-bit float */
380uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
381{
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());
386 return ret;
387}
388
389/* convert 64-bit int to 128-bit float */
390uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
391{
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);
2112bf1b
RH
395 handle_exceptions(env, GETPC());
396 return RET128(ret);
397}
398
399/* convert 64-bit uint to 32-bit float */
400uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
401{
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());
406 return ret;
407}
408
409/* convert 64-bit uint to 64-bit float */
410uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
411{
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());
416 return ret;
417}
418
419/* convert 64-bit uint to 128-bit float */
420uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
421{
422 int hold = swap_round_mode(env, m3);
d2d9feac 423 float128 ret = uint64_to_float128(v2, &env->fpu_status);
2112bf1b 424 set_float_rounding_mode(hold, &env->fpu_status);
683bb9a8
RH
425 handle_exceptions(env, GETPC());
426 return RET128(ret);
427}
428
e72ca652 429/* convert 32-bit float to 64-bit int */
68c8bd93 430uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
e72ca652 431{
68c8bd93
RH
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());
436 return ret;
e72ca652
BS
437}
438
439/* convert 64-bit float to 64-bit int */
68c8bd93 440uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
e72ca652 441{
68c8bd93
RH
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());
446 return ret;
e72ca652
BS
447}
448
449/* convert 128-bit float to 64-bit int */
68c8bd93 450uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
e72ca652 451{
68c8bd93
RH
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());
457 return ret;
e72ca652
BS
458}
459
460/* convert 32-bit float to 32-bit int */
68c8bd93 461uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
e72ca652 462{
68c8bd93
RH
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());
467 return ret;
e72ca652
BS
468}
469
470/* convert 64-bit float to 32-bit int */
68c8bd93 471uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
e72ca652 472{
68c8bd93
RH
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());
477 return ret;
e72ca652
BS
478}
479
480/* convert 128-bit float to 32-bit int */
68c8bd93 481uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
e72ca652 482{
68c8bd93
RH
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());
488 return ret;
e72ca652
BS
489}
490
6ac1b45f
RH
491/* convert 32-bit float to 64-bit uint */
492uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
493{
494 int hold = swap_round_mode(env, m3);
495 uint64_t ret;
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());
500 return ret;
501}
502
503/* convert 64-bit float to 64-bit uint */
504uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
505{
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());
510 return ret;
511}
512
513/* convert 128-bit float to 64-bit uint */
514uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
515{
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());
522 return ret;
523}
524
525/* convert 32-bit float to 32-bit uint */
526uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
527{
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());
532 return ret;
533}
534
535/* convert 64-bit float to 32-bit uint */
536uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
537{
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());
542 return ret;
543}
544
545/* convert 128-bit float to 32-bit uint */
546uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
547{
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());
554 return ret;
555}
556
ed0bcece
AJ
557/* round to integer 32-bit */
558uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
559{
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());
564 return ret;
565}
566
567/* round to integer 64-bit */
568uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
569{
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());
574 return ret;
575}
576
577/* round to integer 128-bit */
578uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
579{
580 int hold = swap_round_mode(env, m3);
581 float128 ret = float128_round_to_int(make_float128(ah, al),
582 &env->fpu_status);
583 set_float_rounding_mode(hold, &env->fpu_status);
584 handle_exceptions(env, GETPC());
585 return RET128(ret);
586}
587
722bfec3
RH
588/* 32-bit FP multiply and add */
589uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
590 uint64_t f2, uint64_t f3)
e72ca652 591{
722bfec3
RH
592 float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
593 handle_exceptions(env, GETPC());
594 return ret;
e72ca652
BS
595}
596
722bfec3
RH
597/* 64-bit FP multiply and add */
598uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
599 uint64_t f2, uint64_t f3)
e72ca652 600{
722bfec3
RH
601 float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
602 handle_exceptions(env, GETPC());
603 return ret;
e72ca652
BS
604}
605
722bfec3
RH
606/* 32-bit FP multiply and subtract */
607uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
608 uint64_t f2, uint64_t f3)
e72ca652 609{
722bfec3
RH
610 float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
611 &env->fpu_status);
612 handle_exceptions(env, GETPC());
613 return ret;
e72ca652
BS
614}
615
722bfec3
RH
616/* 64-bit FP multiply and subtract */
617uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
618 uint64_t f2, uint64_t f3)
e72ca652 619{
722bfec3
RH
620 float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
621 &env->fpu_status);
622 handle_exceptions(env, GETPC());
623 return ret;
e72ca652
BS
624}
625
e72ca652 626/* test data class 32-bit */
af39bc8c 627uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
e72ca652 628{
31aa97d1 629 float32 v1 = f1;
e72ca652
BS
630 int neg = float32_is_neg(v1);
631 uint32_t cc = 0;
632
e72ca652
BS
633 if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
634 (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
635 (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
af39bc8c
AM
636 (float32_is_signaling_nan(v1, &env->fpu_status) &&
637 (m2 & (1 << (1-neg))))) {
e72ca652
BS
638 cc = 1;
639 } else if (m2 & (1 << (9-neg))) {
640 /* assume normalized number */
641 cc = 1;
642 }
e72ca652
BS
643 /* FIXME: denormalized? */
644 return cc;
645}
646
647/* test data class 64-bit */
af39bc8c 648uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
e72ca652 649{
e72ca652
BS
650 int neg = float64_is_neg(v1);
651 uint32_t cc = 0;
652
e72ca652
BS
653 if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
654 (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
655 (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
af39bc8c
AM
656 (float64_is_signaling_nan(v1, &env->fpu_status) &&
657 (m2 & (1 << (1-neg))))) {
e72ca652
BS
658 cc = 1;
659 } else if (m2 & (1 << (9-neg))) {
660 /* assume normalized number */
661 cc = 1;
662 }
663 /* FIXME: denormalized? */
664 return cc;
665}
666
667/* test data class 128-bit */
af39bc8c
AM
668uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
669 uint64_t al, uint64_t m2)
e72ca652 670{
31aa97d1
RH
671 float128 v1 = make_float128(ah, al);
672 int neg = float128_is_neg(v1);
e72ca652 673 uint32_t cc = 0;
e72ca652 674
31aa97d1
RH
675 if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
676 (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
677 (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
af39bc8c
AM
678 (float128_is_signaling_nan(v1, &env->fpu_status) &&
679 (m2 & (1 << (1-neg))))) {
e72ca652
BS
680 cc = 1;
681 } else if (m2 & (1 << (9-neg))) {
682 /* assume normalized number */
683 cc = 1;
684 }
685 /* FIXME: denormalized? */
686 return cc;
687}
688
16d7b2a4
RH
689/* square root 32-bit */
690uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
e72ca652 691{
16d7b2a4
RH
692 float32 ret = float32_sqrt(f2, &env->fpu_status);
693 handle_exceptions(env, GETPC());
694 return ret;
695}
696
697/* square root 64-bit */
698uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
699{
700 float64 ret = float64_sqrt(f2, &env->fpu_status);
701 handle_exceptions(env, GETPC());
702 return ret;
703}
704
705/* square root 128-bit */
706uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
707{
708 float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
709 handle_exceptions(env, GETPC());
710 return RET128(ret);
e72ca652 711}
8379bfdb 712
411edc22
RH
713static const int fpc_to_rnd[4] = {
714 float_round_nearest_even,
715 float_round_to_zero,
716 float_round_up,
717 float_round_down
718};
719
8379bfdb
RH
720/* set fpc */
721void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
722{
8379bfdb
RH
723 /* Install everything in the main FPC. */
724 env->fpc = fpc;
725
726 /* Install the rounding mode in the shadow fpu_status. */
411edc22
RH
727 set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
728}
729
730/* set fpc and signal */
731void HELPER(sfas)(CPUS390XState *env, uint64_t val)
732{
733 uint32_t signalling = env->fpc;
734 uint32_t source = val;
735 uint32_t s390_exc;
736
737 /* The contents of the source operand are placed in the FPC register;
738 then the flags in the FPC register are set to the logical OR of the
739 signalling flags and the source flags. */
740 env->fpc = source | (signalling & 0x00ff0000);
741 set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
742
743 /* If any signalling flag is 1 and the corresponding source mask
744 is also 1, a simulated-iee-exception trap occurs. */
745 s390_exc = (signalling >> 16) & (source >> 24);
746 if (s390_exc) {
747 ieee_exception(env, s390_exc | 3, GETPC());
748 }
8379bfdb 749}