blob: e604e9f7be86f9ccd5aeb01d41bfa55d25e685e5 [file] [log] [blame]
Blue Swirle72ca652012-09-02 07:33:31 +00001/*
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
Peter Maydell96154952016-01-26 18:17:00 +000021#include "qemu/osdep.h"
Blue Swirle72ca652012-09-02 07:33:31 +000022#include "cpu.h"
Paolo Bonzini63c91552016-03-15 13:18:37 +010023#include "exec/exec-all.h"
Paolo Bonzinif08b6172014-03-28 19:42:10 +010024#include "exec/cpu_ldst.h"
Richard Henderson2ef61752014-04-07 22:31:41 -070025#include "exec/helper-proto.h"
Blue Swirle72ca652012-09-02 07:33:31 +000026
Blue Swirle72ca652012-09-02 07:33:31 +000027/* #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
Richard Henderson587626f2012-08-23 10:48:20 -070034#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
Blue Swirl449c0d72012-09-02 07:33:36 +000080static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
Blue Swirle72ca652012-09-02 07:33:31 +000081{
Andreas Färbera47dddd2013-09-03 17:38:47 +020082 S390CPU *cpu = s390_env_get_cpu(env);
83
Blue Swirle72ca652012-09-02 07:33:31 +000084 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:
Andreas Färbera47dddd2013-09-03 17:38:47 +020094 cpu_abort(CPU(cpu), "unknown return value for float compare\n");
Blue Swirle72ca652012-09-02 07:33:31 +000095 }
96}
97
Blue Swirle72ca652012-09-02 07:33:31 +000098/* 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
Richard Henderson587626f2012-08-23 10:48:20 -0700125uint32_t set_cc_nz_f128(float128 v)
Blue Swirle72ca652012-09-02 07:33:31 +0000126{
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
Richard Henderson587626f2012-08-23 10:48:20 -0700138/* 32-bit FP addition */
139uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000140{
Richard Henderson587626f2012-08-23 10:48:20 -0700141 float32 ret = float32_add(f1, f2, &env->fpu_status);
142 handle_exceptions(env, GETPC());
143 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000144}
145
Richard Henderson587626f2012-08-23 10:48:20 -0700146/* 64-bit FP addition */
147uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000148{
Richard Henderson587626f2012-08-23 10:48:20 -0700149 float64 ret = float64_add(f1, f2, &env->fpu_status);
150 handle_exceptions(env, GETPC());
151 return ret;
152}
Blue Swirle72ca652012-09-02 07:33:31 +0000153
Richard Henderson587626f2012-08-23 10:48:20 -0700154/* 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);
Blue Swirle72ca652012-09-02 07:33:31 +0000163}
164
Richard Henderson1a800a22012-08-23 11:05:03 -0700165/* 32-bit FP subtraction */
166uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000167{
Richard Henderson1a800a22012-08-23 11:05:03 -0700168 float32 ret = float32_sub(f1, f2, &env->fpu_status);
169 handle_exceptions(env, GETPC());
170 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000171}
172
Richard Henderson1a800a22012-08-23 11:05:03 -0700173/* 64-bit FP subtraction */
174uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000175{
Richard Henderson1a800a22012-08-23 11:05:03 -0700176 float64 ret = float64_sub(f1, f2, &env->fpu_status);
177 handle_exceptions(env, GETPC());
178 return ret;
179}
Blue Swirle72ca652012-09-02 07:33:31 +0000180
Richard Henderson1a800a22012-08-23 11:05:03 -0700181/* 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);
Blue Swirle72ca652012-09-02 07:33:31 +0000190}
191
Richard Hendersonf08a5c32012-09-07 11:41:12 -0700192/* 32-bit FP division */
193uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000194{
Richard Hendersonf08a5c32012-09-07 11:41:12 -0700195 float32 ret = float32_div(f1, f2, &env->fpu_status);
196 handle_exceptions(env, GETPC());
197 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000198}
199
Richard Hendersonf08a5c32012-09-07 11:41:12 -0700200/* 64-bit FP division */
201uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000202{
Richard Hendersonf08a5c32012-09-07 11:41:12 -0700203 float64 ret = float64_div(f1, f2, &env->fpu_status);
204 handle_exceptions(env, GETPC());
205 return ret;
206}
Blue Swirle72ca652012-09-02 07:33:31 +0000207
Richard Hendersonf08a5c32012-09-07 11:41:12 -0700208/* 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);
Blue Swirle72ca652012-09-02 07:33:31 +0000217}
218
Richard Henderson83b00732012-08-23 12:02:38 -0700219/* 32-bit FP multiplication */
220uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000221{
Richard Henderson83b00732012-08-23 12:02:38 -0700222 float32 ret = float32_mul(f1, f2, &env->fpu_status);
223 handle_exceptions(env, GETPC());
224 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000225}
226
Richard Henderson83b00732012-08-23 12:02:38 -0700227/* 64-bit FP multiplication */
228uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000229{
Richard Henderson83b00732012-08-23 12:02:38 -0700230 float64 ret = float64_mul(f1, f2, &env->fpu_status);
231 handle_exceptions(env, GETPC());
232 return ret;
233}
Blue Swirle72ca652012-09-02 07:33:31 +0000234
Richard Henderson83b00732012-08-23 12:02:38 -0700235/* 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);
Blue Swirle72ca652012-09-02 07:33:31 +0000263}
264
265/* convert 32-bit float to 64-bit float */
Richard Henderson587626f2012-08-23 10:48:20 -0700266uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000267{
Richard Henderson587626f2012-08-23 10:48:20 -0700268 float64 ret = float32_to_float64(f2, &env->fpu_status);
269 handle_exceptions(env, GETPC());
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200270 return float64_maybe_silence_nan(ret, &env->fpu_status);
Blue Swirle72ca652012-09-02 07:33:31 +0000271}
272
273/* convert 128-bit float to 64-bit float */
Richard Henderson587626f2012-08-23 10:48:20 -0700274uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
Blue Swirle72ca652012-09-02 07:33:31 +0000275{
Richard Henderson587626f2012-08-23 10:48:20 -0700276 float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
277 handle_exceptions(env, GETPC());
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200278 return float64_maybe_silence_nan(ret, &env->fpu_status);
Blue Swirle72ca652012-09-02 07:33:31 +0000279}
280
281/* convert 64-bit float to 128-bit float */
Richard Henderson587626f2012-08-23 10:48:20 -0700282uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000283{
Richard Henderson587626f2012-08-23 10:48:20 -0700284 float128 ret = float64_to_float128(f2, &env->fpu_status);
285 handle_exceptions(env, GETPC());
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200286 return RET128(float128_maybe_silence_nan(ret, &env->fpu_status));
Richard Henderson587626f2012-08-23 10:48:20 -0700287}
Blue Swirle72ca652012-09-02 07:33:31 +0000288
Richard Henderson587626f2012-08-23 10:48:20 -0700289/* 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());
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200294 return RET128(float128_maybe_silence_nan(ret, &env->fpu_status));
Blue Swirle72ca652012-09-02 07:33:31 +0000295}
296
297/* convert 64-bit float to 32-bit float */
Richard Henderson587626f2012-08-23 10:48:20 -0700298uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000299{
Richard Henderson587626f2012-08-23 10:48:20 -0700300 float32 ret = float64_to_float32(f2, &env->fpu_status);
301 handle_exceptions(env, GETPC());
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200302 return float32_maybe_silence_nan(ret, &env->fpu_status);
Blue Swirle72ca652012-09-02 07:33:31 +0000303}
304
305/* convert 128-bit float to 32-bit float */
Richard Henderson587626f2012-08-23 10:48:20 -0700306uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
Blue Swirle72ca652012-09-02 07:33:31 +0000307{
Richard Henderson587626f2012-08-23 10:48:20 -0700308 float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
309 handle_exceptions(env, GETPC());
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200310 return float32_maybe_silence_nan(ret, &env->fpu_status);
Blue Swirle72ca652012-09-02 07:33:31 +0000311}
312
Richard Henderson587626f2012-08-23 10:48:20 -0700313/* 32-bit FP compare */
314uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000315{
Richard Henderson587626f2012-08-23 10:48:20 -0700316 int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
317 handle_exceptions(env, GETPC());
318 return float_comp_to_cc(env, cmp);
Blue Swirle72ca652012-09-02 07:33:31 +0000319}
320
Richard Henderson587626f2012-08-23 10:48:20 -0700321/* 64-bit FP compare */
322uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000323{
Richard Henderson587626f2012-08-23 10:48:20 -0700324 int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
325 handle_exceptions(env, GETPC());
326 return float_comp_to_cc(env, cmp);
Blue Swirle72ca652012-09-02 07:33:31 +0000327}
328
Richard Henderson587626f2012-08-23 10:48:20 -0700329/* 128-bit FP compare */
330uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
331 uint64_t bh, uint64_t bl)
Blue Swirle72ca652012-09-02 07:33:31 +0000332{
Richard Henderson587626f2012-08-23 10:48:20 -0700333 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);
Blue Swirle72ca652012-09-02 07:33:31 +0000338}
339
Richard Henderson68c8bd92012-08-23 15:17:35 -0700340static int swap_round_mode(CPUS390XState *env, int m3)
Blue Swirle72ca652012-09-02 07:33:31 +0000341{
Richard Henderson68c8bd92012-08-23 15:17:35 -0700342 int ret = env->fpu_status.float_rounding_mode;
Blue Swirle72ca652012-09-02 07:33:31 +0000343 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 }
Richard Henderson68c8bd92012-08-23 15:17:35 -0700366 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000367}
368
Richard Henderson683bb9a2012-08-23 21:08:22 -0700369/* 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);
395 handle_exceptions(env, GETPC());
396 return RET128(ret);
397}
398
Richard Henderson2112bf12012-09-01 11:08:17 -0700399/* 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);
Richard Hendersond2d9fea2012-09-09 16:04:17 -0700423 float128 ret = uint64_to_float128(v2, &env->fpu_status);
Richard Henderson2112bf12012-09-01 11:08:17 -0700424 set_float_rounding_mode(hold, &env->fpu_status);
425 handle_exceptions(env, GETPC());
426 return RET128(ret);
427}
428
Blue Swirle72ca652012-09-02 07:33:31 +0000429/* convert 32-bit float to 64-bit int */
Richard Henderson68c8bd92012-08-23 15:17:35 -0700430uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
Blue Swirle72ca652012-09-02 07:33:31 +0000431{
Richard Henderson68c8bd92012-08-23 15:17:35 -0700432 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;
Blue Swirle72ca652012-09-02 07:33:31 +0000437}
438
439/* convert 64-bit float to 64-bit int */
Richard Henderson68c8bd92012-08-23 15:17:35 -0700440uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
Blue Swirle72ca652012-09-02 07:33:31 +0000441{
Richard Henderson68c8bd92012-08-23 15:17:35 -0700442 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;
Blue Swirle72ca652012-09-02 07:33:31 +0000447}
448
449/* convert 128-bit float to 64-bit int */
Richard Henderson68c8bd92012-08-23 15:17:35 -0700450uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
Blue Swirle72ca652012-09-02 07:33:31 +0000451{
Richard Henderson68c8bd92012-08-23 15:17:35 -0700452 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;
Blue Swirle72ca652012-09-02 07:33:31 +0000458}
459
460/* convert 32-bit float to 32-bit int */
Richard Henderson68c8bd92012-08-23 15:17:35 -0700461uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
Blue Swirle72ca652012-09-02 07:33:31 +0000462{
Richard Henderson68c8bd92012-08-23 15:17:35 -0700463 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;
Blue Swirle72ca652012-09-02 07:33:31 +0000468}
469
470/* convert 64-bit float to 32-bit int */
Richard Henderson68c8bd92012-08-23 15:17:35 -0700471uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
Blue Swirle72ca652012-09-02 07:33:31 +0000472{
Richard Henderson68c8bd92012-08-23 15:17:35 -0700473 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;
Blue Swirle72ca652012-09-02 07:33:31 +0000478}
479
480/* convert 128-bit float to 32-bit int */
Richard Henderson68c8bd92012-08-23 15:17:35 -0700481uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
Blue Swirle72ca652012-09-02 07:33:31 +0000482{
Richard Henderson68c8bd92012-08-23 15:17:35 -0700483 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;
Blue Swirle72ca652012-09-02 07:33:31 +0000489}
490
Richard Henderson6ac1b452012-09-01 10:42:54 -0700491/* 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
Aurelien Jarnoed0bcec2015-06-03 23:09:46 +0200557/* 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
Richard Henderson722bfec2012-08-23 12:30:12 -0700588/* 32-bit FP multiply and add */
589uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
590 uint64_t f2, uint64_t f3)
Blue Swirle72ca652012-09-02 07:33:31 +0000591{
Richard Henderson722bfec2012-08-23 12:30:12 -0700592 float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
593 handle_exceptions(env, GETPC());
594 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000595}
596
Richard Henderson722bfec2012-08-23 12:30:12 -0700597/* 64-bit FP multiply and add */
598uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
599 uint64_t f2, uint64_t f3)
Blue Swirle72ca652012-09-02 07:33:31 +0000600{
Richard Henderson722bfec2012-08-23 12:30:12 -0700601 float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
602 handle_exceptions(env, GETPC());
603 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000604}
605
Richard Henderson722bfec2012-08-23 12:30:12 -0700606/* 32-bit FP multiply and subtract */
607uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
608 uint64_t f2, uint64_t f3)
Blue Swirle72ca652012-09-02 07:33:31 +0000609{
Richard Henderson722bfec2012-08-23 12:30:12 -0700610 float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
611 &env->fpu_status);
612 handle_exceptions(env, GETPC());
613 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000614}
615
Richard Henderson722bfec2012-08-23 12:30:12 -0700616/* 64-bit FP multiply and subtract */
617uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
618 uint64_t f2, uint64_t f3)
Blue Swirle72ca652012-09-02 07:33:31 +0000619{
Richard Henderson722bfec2012-08-23 12:30:12 -0700620 float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
621 &env->fpu_status);
622 handle_exceptions(env, GETPC());
623 return ret;
Blue Swirle72ca652012-09-02 07:33:31 +0000624}
625
Blue Swirle72ca652012-09-02 07:33:31 +0000626/* test data class 32-bit */
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200627uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
Blue Swirle72ca652012-09-02 07:33:31 +0000628{
Richard Henderson31aa97d2012-08-23 12:40:09 -0700629 float32 v1 = f1;
Blue Swirle72ca652012-09-02 07:33:31 +0000630 int neg = float32_is_neg(v1);
631 uint32_t cc = 0;
632
Blue Swirle72ca652012-09-02 07:33:31 +0000633 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)))) ||
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200636 (float32_is_signaling_nan(v1, &env->fpu_status) &&
637 (m2 & (1 << (1-neg))))) {
Blue Swirle72ca652012-09-02 07:33:31 +0000638 cc = 1;
639 } else if (m2 & (1 << (9-neg))) {
640 /* assume normalized number */
641 cc = 1;
642 }
Blue Swirle72ca652012-09-02 07:33:31 +0000643 /* FIXME: denormalized? */
644 return cc;
645}
646
647/* test data class 64-bit */
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200648uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
Blue Swirle72ca652012-09-02 07:33:31 +0000649{
Blue Swirle72ca652012-09-02 07:33:31 +0000650 int neg = float64_is_neg(v1);
651 uint32_t cc = 0;
652
Blue Swirle72ca652012-09-02 07:33:31 +0000653 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)))) ||
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200656 (float64_is_signaling_nan(v1, &env->fpu_status) &&
657 (m2 & (1 << (1-neg))))) {
Blue Swirle72ca652012-09-02 07:33:31 +0000658 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 */
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200668uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
669 uint64_t al, uint64_t m2)
Blue Swirle72ca652012-09-02 07:33:31 +0000670{
Richard Henderson31aa97d2012-08-23 12:40:09 -0700671 float128 v1 = make_float128(ah, al);
672 int neg = float128_is_neg(v1);
Blue Swirle72ca652012-09-02 07:33:31 +0000673 uint32_t cc = 0;
Blue Swirle72ca652012-09-02 07:33:31 +0000674
Richard Henderson31aa97d2012-08-23 12:40:09 -0700675 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)))) ||
Aleksandar Markovicaf39bc82016-06-10 11:57:28 +0200678 (float128_is_signaling_nan(v1, &env->fpu_status) &&
679 (m2 & (1 << (1-neg))))) {
Blue Swirle72ca652012-09-02 07:33:31 +0000680 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
Richard Henderson16d7b2a2012-08-23 14:33:03 -0700689/* square root 32-bit */
690uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
Blue Swirle72ca652012-09-02 07:33:31 +0000691{
Richard Henderson16d7b2a2012-08-23 14:33:03 -0700692 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);
Blue Swirle72ca652012-09-02 07:33:31 +0000711}
Richard Henderson8379bfd2012-08-24 07:44:43 -0700712
Richard Henderson411edc22012-09-10 17:23:13 -0700713static 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
Richard Henderson8379bfd2012-08-24 07:44:43 -0700720/* set fpc */
721void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
722{
Richard Henderson8379bfd2012-08-24 07:44:43 -0700723 /* Install everything in the main FPC. */
724 env->fpc = fpc;
725
726 /* Install the rounding mode in the shadow fpu_status. */
Richard Henderson411edc22012-09-10 17:23:13 -0700727 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 }
Richard Henderson8379bfd2012-08-24 07:44:43 -0700749}