xref: /qemu/target/s390x/tcg/fpu_helper.c (revision 6ac1b45f9b3cb788255c0fde7637ba663eba632c)
1e72ca652SBlue Swirl /*
2e72ca652SBlue Swirl  *  S/390 FPU helper routines
3e72ca652SBlue Swirl  *
4e72ca652SBlue Swirl  *  Copyright (c) 2009 Ulrich Hecht
5e72ca652SBlue Swirl  *  Copyright (c) 2009 Alexander Graf
6e72ca652SBlue Swirl  *
7e72ca652SBlue Swirl  * This library is free software; you can redistribute it and/or
8e72ca652SBlue Swirl  * modify it under the terms of the GNU Lesser General Public
9e72ca652SBlue Swirl  * License as published by the Free Software Foundation; either
10e72ca652SBlue Swirl  * version 2 of the License, or (at your option) any later version.
11e72ca652SBlue Swirl  *
12e72ca652SBlue Swirl  * This library is distributed in the hope that it will be useful,
13e72ca652SBlue Swirl  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14e72ca652SBlue Swirl  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15e72ca652SBlue Swirl  * Lesser General Public License for more details.
16e72ca652SBlue Swirl  *
17e72ca652SBlue Swirl  * You should have received a copy of the GNU Lesser General Public
18e72ca652SBlue Swirl  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19e72ca652SBlue Swirl  */
20e72ca652SBlue Swirl 
21e72ca652SBlue Swirl #include "cpu.h"
22e72ca652SBlue Swirl #include "helper.h"
23e72ca652SBlue Swirl 
2419b0516fSBlue Swirl #if !defined(CONFIG_USER_ONLY)
25022c62cbSPaolo Bonzini #include "exec/softmmu_exec.h"
26e72ca652SBlue Swirl #endif
27e72ca652SBlue Swirl 
28e72ca652SBlue Swirl /* #define DEBUG_HELPER */
29e72ca652SBlue Swirl #ifdef DEBUG_HELPER
30e72ca652SBlue Swirl #define HELPER_LOG(x...) qemu_log(x)
31e72ca652SBlue Swirl #else
32e72ca652SBlue Swirl #define HELPER_LOG(x...)
33e72ca652SBlue Swirl #endif
34e72ca652SBlue Swirl 
35587626f8SRichard Henderson #define RET128(F) (env->retxl = F.low, F.high)
36587626f8SRichard Henderson 
37587626f8SRichard Henderson #define convert_bit(mask, from, to) \
38587626f8SRichard Henderson     (to < from                      \
39587626f8SRichard Henderson      ? (mask / (from / to)) & to    \
40587626f8SRichard Henderson      : (mask & from) * (to / from))
41587626f8SRichard Henderson 
42587626f8SRichard Henderson static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
43587626f8SRichard Henderson {
44587626f8SRichard Henderson     /* Install the DXC code.  */
45587626f8SRichard Henderson     env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
46587626f8SRichard Henderson     /* Trap.  */
47587626f8SRichard Henderson     runtime_exception(env, PGM_DATA, retaddr);
48587626f8SRichard Henderson }
49587626f8SRichard Henderson 
50587626f8SRichard Henderson /* Should be called after any operation that may raise IEEE exceptions.  */
51587626f8SRichard Henderson static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
52587626f8SRichard Henderson {
53587626f8SRichard Henderson     unsigned s390_exc, qemu_exc;
54587626f8SRichard Henderson 
55587626f8SRichard Henderson     /* Get the exceptions raised by the current operation.  Reset the
56587626f8SRichard Henderson        fpu_status contents so that the next operation has a clean slate.  */
57587626f8SRichard Henderson     qemu_exc = env->fpu_status.float_exception_flags;
58587626f8SRichard Henderson     if (qemu_exc == 0) {
59587626f8SRichard Henderson         return;
60587626f8SRichard Henderson     }
61587626f8SRichard Henderson     env->fpu_status.float_exception_flags = 0;
62587626f8SRichard Henderson 
63587626f8SRichard Henderson     /* Convert softfloat exception bits to s390 exception bits.  */
64587626f8SRichard Henderson     s390_exc = 0;
65587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
66587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
67587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
68587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
69587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
70587626f8SRichard Henderson 
71587626f8SRichard Henderson     /* Install the exceptions that we raised.  */
72587626f8SRichard Henderson     env->fpc |= s390_exc << 16;
73587626f8SRichard Henderson 
74587626f8SRichard Henderson     /* Send signals for enabled exceptions.  */
75587626f8SRichard Henderson     s390_exc &= env->fpc >> 24;
76587626f8SRichard Henderson     if (s390_exc) {
77587626f8SRichard Henderson         ieee_exception(env, s390_exc, retaddr);
78587626f8SRichard Henderson     }
79587626f8SRichard Henderson }
80587626f8SRichard Henderson 
81449c0d70SBlue Swirl static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
82e72ca652SBlue Swirl {
83e72ca652SBlue Swirl     switch (float_compare) {
84e72ca652SBlue Swirl     case float_relation_equal:
85e72ca652SBlue Swirl         return 0;
86e72ca652SBlue Swirl     case float_relation_less:
87e72ca652SBlue Swirl         return 1;
88e72ca652SBlue Swirl     case float_relation_greater:
89e72ca652SBlue Swirl         return 2;
90e72ca652SBlue Swirl     case float_relation_unordered:
91e72ca652SBlue Swirl         return 3;
92e72ca652SBlue Swirl     default:
93e72ca652SBlue Swirl         cpu_abort(env, "unknown return value for float compare\n");
94e72ca652SBlue Swirl     }
95e72ca652SBlue Swirl }
96e72ca652SBlue Swirl 
97e72ca652SBlue Swirl /* condition codes for unary FP ops */
98e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v)
99e72ca652SBlue Swirl {
100e72ca652SBlue Swirl     if (float32_is_any_nan(v)) {
101e72ca652SBlue Swirl         return 3;
102e72ca652SBlue Swirl     } else if (float32_is_zero(v)) {
103e72ca652SBlue Swirl         return 0;
104e72ca652SBlue Swirl     } else if (float32_is_neg(v)) {
105e72ca652SBlue Swirl         return 1;
106e72ca652SBlue Swirl     } else {
107e72ca652SBlue Swirl         return 2;
108e72ca652SBlue Swirl     }
109e72ca652SBlue Swirl }
110e72ca652SBlue Swirl 
111e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v)
112e72ca652SBlue Swirl {
113e72ca652SBlue Swirl     if (float64_is_any_nan(v)) {
114e72ca652SBlue Swirl         return 3;
115e72ca652SBlue Swirl     } else if (float64_is_zero(v)) {
116e72ca652SBlue Swirl         return 0;
117e72ca652SBlue Swirl     } else if (float64_is_neg(v)) {
118e72ca652SBlue Swirl         return 1;
119e72ca652SBlue Swirl     } else {
120e72ca652SBlue Swirl         return 2;
121e72ca652SBlue Swirl     }
122e72ca652SBlue Swirl }
123e72ca652SBlue Swirl 
124587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v)
125e72ca652SBlue Swirl {
126e72ca652SBlue Swirl     if (float128_is_any_nan(v)) {
127e72ca652SBlue Swirl         return 3;
128e72ca652SBlue Swirl     } else if (float128_is_zero(v)) {
129e72ca652SBlue Swirl         return 0;
130e72ca652SBlue Swirl     } else if (float128_is_neg(v)) {
131e72ca652SBlue Swirl         return 1;
132e72ca652SBlue Swirl     } else {
133e72ca652SBlue Swirl         return 2;
134e72ca652SBlue Swirl     }
135e72ca652SBlue Swirl }
136e72ca652SBlue Swirl 
137587626f8SRichard Henderson /* 32-bit FP addition */
138587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
139e72ca652SBlue Swirl {
140587626f8SRichard Henderson     float32 ret = float32_add(f1, f2, &env->fpu_status);
141587626f8SRichard Henderson     handle_exceptions(env, GETPC());
142587626f8SRichard Henderson     return ret;
143e72ca652SBlue Swirl }
144e72ca652SBlue Swirl 
145587626f8SRichard Henderson /* 64-bit FP addition */
146587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
147e72ca652SBlue Swirl {
148587626f8SRichard Henderson     float64 ret = float64_add(f1, f2, &env->fpu_status);
149587626f8SRichard Henderson     handle_exceptions(env, GETPC());
150587626f8SRichard Henderson     return ret;
151587626f8SRichard Henderson }
152e72ca652SBlue Swirl 
153587626f8SRichard Henderson /* 128-bit FP addition */
154587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
155587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
156587626f8SRichard Henderson {
157587626f8SRichard Henderson     float128 ret = float128_add(make_float128(ah, al),
158587626f8SRichard Henderson                                 make_float128(bh, bl),
159587626f8SRichard Henderson                                 &env->fpu_status);
160587626f8SRichard Henderson     handle_exceptions(env, GETPC());
161587626f8SRichard Henderson     return RET128(ret);
162e72ca652SBlue Swirl }
163e72ca652SBlue Swirl 
1641a800a2dSRichard Henderson /* 32-bit FP subtraction */
1651a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
166e72ca652SBlue Swirl {
1671a800a2dSRichard Henderson     float32 ret = float32_sub(f1, f2, &env->fpu_status);
1681a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
1691a800a2dSRichard Henderson     return ret;
170e72ca652SBlue Swirl }
171e72ca652SBlue Swirl 
1721a800a2dSRichard Henderson /* 64-bit FP subtraction */
1731a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
174e72ca652SBlue Swirl {
1751a800a2dSRichard Henderson     float64 ret = float64_sub(f1, f2, &env->fpu_status);
1761a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
1771a800a2dSRichard Henderson     return ret;
1781a800a2dSRichard Henderson }
179e72ca652SBlue Swirl 
1801a800a2dSRichard Henderson /* 128-bit FP subtraction */
1811a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
1821a800a2dSRichard Henderson                      uint64_t bh, uint64_t bl)
1831a800a2dSRichard Henderson {
1841a800a2dSRichard Henderson     float128 ret = float128_sub(make_float128(ah, al),
1851a800a2dSRichard Henderson                                 make_float128(bh, bl),
1861a800a2dSRichard Henderson                                 &env->fpu_status);
1871a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
1881a800a2dSRichard Henderson     return RET128(ret);
189e72ca652SBlue Swirl }
190e72ca652SBlue Swirl 
191f08a5c31SRichard Henderson /* 32-bit FP division */
192f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
193e72ca652SBlue Swirl {
194f08a5c31SRichard Henderson     float32 ret = float32_div(f1, f2, &env->fpu_status);
195f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
196f08a5c31SRichard Henderson     return ret;
197e72ca652SBlue Swirl }
198e72ca652SBlue Swirl 
199f08a5c31SRichard Henderson /* 64-bit FP division */
200f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
201e72ca652SBlue Swirl {
202f08a5c31SRichard Henderson     float64 ret = float64_div(f1, f2, &env->fpu_status);
203f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
204f08a5c31SRichard Henderson     return ret;
205f08a5c31SRichard Henderson }
206e72ca652SBlue Swirl 
207f08a5c31SRichard Henderson /* 128-bit FP division */
208f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
209f08a5c31SRichard Henderson                      uint64_t bh, uint64_t bl)
210f08a5c31SRichard Henderson {
211f08a5c31SRichard Henderson     float128 ret = float128_div(make_float128(ah, al),
212f08a5c31SRichard Henderson                                 make_float128(bh, bl),
213f08a5c31SRichard Henderson                                 &env->fpu_status);
214f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
215f08a5c31SRichard Henderson     return RET128(ret);
216e72ca652SBlue Swirl }
217e72ca652SBlue Swirl 
21883b00736SRichard Henderson /* 32-bit FP multiplication */
21983b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
220e72ca652SBlue Swirl {
22183b00736SRichard Henderson     float32 ret = float32_mul(f1, f2, &env->fpu_status);
22283b00736SRichard Henderson     handle_exceptions(env, GETPC());
22383b00736SRichard Henderson     return ret;
224e72ca652SBlue Swirl }
225e72ca652SBlue Swirl 
22683b00736SRichard Henderson /* 64-bit FP multiplication */
22783b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
228e72ca652SBlue Swirl {
22983b00736SRichard Henderson     float64 ret = float64_mul(f1, f2, &env->fpu_status);
23083b00736SRichard Henderson     handle_exceptions(env, GETPC());
23183b00736SRichard Henderson     return ret;
23283b00736SRichard Henderson }
233e72ca652SBlue Swirl 
23483b00736SRichard Henderson /* 64/32-bit FP multiplication */
23583b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
23683b00736SRichard Henderson {
23783b00736SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
23883b00736SRichard Henderson     ret = float64_mul(f1, ret, &env->fpu_status);
23983b00736SRichard Henderson     handle_exceptions(env, GETPC());
24083b00736SRichard Henderson     return ret;
24183b00736SRichard Henderson }
24283b00736SRichard Henderson 
24383b00736SRichard Henderson /* 128-bit FP multiplication */
24483b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
24583b00736SRichard Henderson                      uint64_t bh, uint64_t bl)
24683b00736SRichard Henderson {
24783b00736SRichard Henderson     float128 ret = float128_mul(make_float128(ah, al),
24883b00736SRichard Henderson                                 make_float128(bh, bl),
24983b00736SRichard Henderson                                 &env->fpu_status);
25083b00736SRichard Henderson     handle_exceptions(env, GETPC());
25183b00736SRichard Henderson     return RET128(ret);
25283b00736SRichard Henderson }
25383b00736SRichard Henderson 
25483b00736SRichard Henderson /* 128/64-bit FP multiplication */
25583b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
25683b00736SRichard Henderson                       uint64_t f2)
25783b00736SRichard Henderson {
25883b00736SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
25983b00736SRichard Henderson     ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
26083b00736SRichard Henderson     handle_exceptions(env, GETPC());
26183b00736SRichard Henderson     return RET128(ret);
262e72ca652SBlue Swirl }
263e72ca652SBlue Swirl 
264e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */
265587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
266e72ca652SBlue Swirl {
267587626f8SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
268587626f8SRichard Henderson     handle_exceptions(env, GETPC());
269587626f8SRichard Henderson     return ret;
270e72ca652SBlue Swirl }
271e72ca652SBlue Swirl 
272e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */
273587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
274e72ca652SBlue Swirl {
275587626f8SRichard Henderson     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
276587626f8SRichard Henderson     handle_exceptions(env, GETPC());
277587626f8SRichard Henderson     return ret;
278e72ca652SBlue Swirl }
279e72ca652SBlue Swirl 
280e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */
281587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
282e72ca652SBlue Swirl {
283587626f8SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
284587626f8SRichard Henderson     handle_exceptions(env, GETPC());
285587626f8SRichard Henderson     return RET128(ret);
286587626f8SRichard Henderson }
287e72ca652SBlue Swirl 
288587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */
289587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
290587626f8SRichard Henderson {
291587626f8SRichard Henderson     float128 ret = float32_to_float128(f2, &env->fpu_status);
292587626f8SRichard Henderson     handle_exceptions(env, GETPC());
293587626f8SRichard Henderson     return RET128(ret);
294e72ca652SBlue Swirl }
295e72ca652SBlue Swirl 
296e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */
297587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
298e72ca652SBlue Swirl {
299587626f8SRichard Henderson     float32 ret = float64_to_float32(f2, &env->fpu_status);
300587626f8SRichard Henderson     handle_exceptions(env, GETPC());
301587626f8SRichard Henderson     return ret;
302e72ca652SBlue Swirl }
303e72ca652SBlue Swirl 
304e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */
305587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
306e72ca652SBlue Swirl {
307587626f8SRichard Henderson     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
308587626f8SRichard Henderson     handle_exceptions(env, GETPC());
309587626f8SRichard Henderson     return ret;
310e72ca652SBlue Swirl }
311e72ca652SBlue Swirl 
312587626f8SRichard Henderson /* 32-bit FP compare */
313587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
314e72ca652SBlue Swirl {
315587626f8SRichard Henderson     int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
316587626f8SRichard Henderson     handle_exceptions(env, GETPC());
317587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
318e72ca652SBlue Swirl }
319e72ca652SBlue Swirl 
320587626f8SRichard Henderson /* 64-bit FP compare */
321587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
322e72ca652SBlue Swirl {
323587626f8SRichard Henderson     int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
324587626f8SRichard Henderson     handle_exceptions(env, GETPC());
325587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
326e72ca652SBlue Swirl }
327e72ca652SBlue Swirl 
328587626f8SRichard Henderson /* 128-bit FP compare */
329587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
330587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
331e72ca652SBlue Swirl {
332587626f8SRichard Henderson     int cmp = float128_compare_quiet(make_float128(ah, al),
333587626f8SRichard Henderson                                      make_float128(bh, bl),
334587626f8SRichard Henderson                                      &env->fpu_status);
335587626f8SRichard Henderson     handle_exceptions(env, GETPC());
336587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
337e72ca652SBlue Swirl }
338e72ca652SBlue Swirl 
33968c8bd93SRichard Henderson static int swap_round_mode(CPUS390XState *env, int m3)
340e72ca652SBlue Swirl {
34168c8bd93SRichard Henderson     int ret = env->fpu_status.float_rounding_mode;
342e72ca652SBlue Swirl     switch (m3) {
343e72ca652SBlue Swirl     case 0:
344e72ca652SBlue Swirl         /* current mode */
345e72ca652SBlue Swirl         break;
346e72ca652SBlue Swirl     case 1:
347e72ca652SBlue Swirl         /* biased round no nearest */
348e72ca652SBlue Swirl     case 4:
349e72ca652SBlue Swirl         /* round to nearest */
350e72ca652SBlue Swirl         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
351e72ca652SBlue Swirl         break;
352e72ca652SBlue Swirl     case 5:
353e72ca652SBlue Swirl         /* round to zero */
354e72ca652SBlue Swirl         set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
355e72ca652SBlue Swirl         break;
356e72ca652SBlue Swirl     case 6:
357e72ca652SBlue Swirl         /* round to +inf */
358e72ca652SBlue Swirl         set_float_rounding_mode(float_round_up, &env->fpu_status);
359e72ca652SBlue Swirl         break;
360e72ca652SBlue Swirl     case 7:
361e72ca652SBlue Swirl         /* round to -inf */
362e72ca652SBlue Swirl         set_float_rounding_mode(float_round_down, &env->fpu_status);
363e72ca652SBlue Swirl         break;
364e72ca652SBlue Swirl     }
36568c8bd93SRichard Henderson     return ret;
366e72ca652SBlue Swirl }
367e72ca652SBlue Swirl 
368683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */
369683bb9a8SRichard Henderson uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
370683bb9a8SRichard Henderson {
371683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
372683bb9a8SRichard Henderson     float32 ret = int64_to_float32(v2, &env->fpu_status);
373683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
374683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
375683bb9a8SRichard Henderson     return ret;
376683bb9a8SRichard Henderson }
377683bb9a8SRichard Henderson 
378683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */
379683bb9a8SRichard Henderson uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
380683bb9a8SRichard Henderson {
381683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
382683bb9a8SRichard Henderson     float64 ret = int64_to_float64(v2, &env->fpu_status);
383683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
384683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
385683bb9a8SRichard Henderson     return ret;
386683bb9a8SRichard Henderson }
387683bb9a8SRichard Henderson 
388683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */
389683bb9a8SRichard Henderson uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
390683bb9a8SRichard Henderson {
391683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
392683bb9a8SRichard Henderson     float128 ret = int64_to_float128(v2, &env->fpu_status);
393683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
394683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
395683bb9a8SRichard Henderson     return RET128(ret);
396683bb9a8SRichard Henderson }
397683bb9a8SRichard Henderson 
398e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */
39968c8bd93SRichard Henderson uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
400e72ca652SBlue Swirl {
40168c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
40268c8bd93SRichard Henderson     int64_t ret = float32_to_int64(v2, &env->fpu_status);
40368c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
40468c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
40568c8bd93SRichard Henderson     return ret;
406e72ca652SBlue Swirl }
407e72ca652SBlue Swirl 
408e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */
40968c8bd93SRichard Henderson uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
410e72ca652SBlue Swirl {
41168c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
41268c8bd93SRichard Henderson     int64_t ret = float64_to_int64(v2, &env->fpu_status);
41368c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
41468c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
41568c8bd93SRichard Henderson     return ret;
416e72ca652SBlue Swirl }
417e72ca652SBlue Swirl 
418e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */
41968c8bd93SRichard Henderson uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
420e72ca652SBlue Swirl {
42168c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
42268c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
42368c8bd93SRichard Henderson     int64_t ret = float128_to_int64(v2, &env->fpu_status);
42468c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
42568c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
42668c8bd93SRichard Henderson     return ret;
427e72ca652SBlue Swirl }
428e72ca652SBlue Swirl 
429e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */
43068c8bd93SRichard Henderson uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
431e72ca652SBlue Swirl {
43268c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
43368c8bd93SRichard Henderson     int32_t ret = float32_to_int32(v2, &env->fpu_status);
43468c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
43568c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
43668c8bd93SRichard Henderson     return ret;
437e72ca652SBlue Swirl }
438e72ca652SBlue Swirl 
439e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */
44068c8bd93SRichard Henderson uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
441e72ca652SBlue Swirl {
44268c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
44368c8bd93SRichard Henderson     int32_t ret = float64_to_int32(v2, &env->fpu_status);
44468c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
44568c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
44668c8bd93SRichard Henderson     return ret;
447e72ca652SBlue Swirl }
448e72ca652SBlue Swirl 
449e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */
45068c8bd93SRichard Henderson uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
451e72ca652SBlue Swirl {
45268c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
45368c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
45468c8bd93SRichard Henderson     int32_t ret = float128_to_int32(v2, &env->fpu_status);
45568c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
45668c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
45768c8bd93SRichard Henderson     return ret;
458e72ca652SBlue Swirl }
459e72ca652SBlue Swirl 
4606ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */
4616ac1b45fSRichard Henderson uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4626ac1b45fSRichard Henderson {
4636ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
4646ac1b45fSRichard Henderson     uint64_t ret;
4656ac1b45fSRichard Henderson     v2 = float32_to_float64(v2, &env->fpu_status);
4666ac1b45fSRichard Henderson     ret = float64_to_uint64(v2, &env->fpu_status);
4676ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4686ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
4696ac1b45fSRichard Henderson     return ret;
4706ac1b45fSRichard Henderson }
4716ac1b45fSRichard Henderson 
4726ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */
4736ac1b45fSRichard Henderson uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4746ac1b45fSRichard Henderson {
4756ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
4766ac1b45fSRichard Henderson     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
4776ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4786ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
4796ac1b45fSRichard Henderson     return ret;
4806ac1b45fSRichard Henderson }
4816ac1b45fSRichard Henderson 
4826ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */
4836ac1b45fSRichard Henderson uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
4846ac1b45fSRichard Henderson {
4856ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
4866ac1b45fSRichard Henderson     float128 v2 = make_float128(h, l);
4876ac1b45fSRichard Henderson     /* ??? Not 100% correct.  */
4886ac1b45fSRichard Henderson     uint64_t ret = float128_to_int64(v2, &env->fpu_status);
4896ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4906ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
4916ac1b45fSRichard Henderson     return ret;
4926ac1b45fSRichard Henderson }
4936ac1b45fSRichard Henderson 
4946ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */
4956ac1b45fSRichard Henderson uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4966ac1b45fSRichard Henderson {
4976ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
4986ac1b45fSRichard Henderson     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
4996ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5006ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5016ac1b45fSRichard Henderson     return ret;
5026ac1b45fSRichard Henderson }
5036ac1b45fSRichard Henderson 
5046ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */
5056ac1b45fSRichard Henderson uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5066ac1b45fSRichard Henderson {
5076ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5086ac1b45fSRichard Henderson     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
5096ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5106ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5116ac1b45fSRichard Henderson     return ret;
5126ac1b45fSRichard Henderson }
5136ac1b45fSRichard Henderson 
5146ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */
5156ac1b45fSRichard Henderson uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
5166ac1b45fSRichard Henderson {
5176ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5186ac1b45fSRichard Henderson     float128 v2 = make_float128(h, l);
5196ac1b45fSRichard Henderson     /* Not 100% correct.  */
5206ac1b45fSRichard Henderson     uint32_t ret = float128_to_int64(v2, &env->fpu_status);
5216ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5226ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5236ac1b45fSRichard Henderson     return ret;
5246ac1b45fSRichard Henderson }
5256ac1b45fSRichard Henderson 
526722bfec3SRichard Henderson /* 32-bit FP multiply and add */
527722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
528722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
529e72ca652SBlue Swirl {
530722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
531722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
532722bfec3SRichard Henderson     return ret;
533722bfec3SRichard Henderson }
534e72ca652SBlue Swirl 
535722bfec3SRichard Henderson /* 64-bit FP multiply and add */
536722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
537722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
538722bfec3SRichard Henderson {
539722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
540722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
541722bfec3SRichard Henderson     return ret;
542722bfec3SRichard Henderson }
543722bfec3SRichard Henderson 
544722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */
545722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
546722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
547722bfec3SRichard Henderson {
548722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
549e72ca652SBlue Swirl                                  &env->fpu_status);
550722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
551722bfec3SRichard Henderson     return ret;
552e72ca652SBlue Swirl }
553e72ca652SBlue Swirl 
554722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */
555722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
556722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
557e72ca652SBlue Swirl {
558722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
559e72ca652SBlue Swirl                                  &env->fpu_status);
560722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
561722bfec3SRichard Henderson     return ret;
562e72ca652SBlue Swirl }
563e72ca652SBlue Swirl 
564e72ca652SBlue Swirl /* test data class 32-bit */
56531aa97d1SRichard Henderson uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2)
566e72ca652SBlue Swirl {
56731aa97d1SRichard Henderson     float32 v1 = f1;
568e72ca652SBlue Swirl     int neg = float32_is_neg(v1);
569e72ca652SBlue Swirl     uint32_t cc = 0;
570e72ca652SBlue Swirl 
571e72ca652SBlue Swirl     if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
572e72ca652SBlue Swirl         (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
573e72ca652SBlue Swirl         (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
574e72ca652SBlue Swirl         (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
575e72ca652SBlue Swirl         cc = 1;
576e72ca652SBlue Swirl     } else if (m2 & (1 << (9-neg))) {
577e72ca652SBlue Swirl         /* assume normalized number */
578e72ca652SBlue Swirl         cc = 1;
579e72ca652SBlue Swirl     }
580e72ca652SBlue Swirl     /* FIXME: denormalized? */
581e72ca652SBlue Swirl     return cc;
582e72ca652SBlue Swirl }
583e72ca652SBlue Swirl 
584e72ca652SBlue Swirl /* test data class 64-bit */
58531aa97d1SRichard Henderson uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2)
586e72ca652SBlue Swirl {
587e72ca652SBlue Swirl     int neg = float64_is_neg(v1);
588e72ca652SBlue Swirl     uint32_t cc = 0;
589e72ca652SBlue Swirl 
590e72ca652SBlue Swirl     if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
591e72ca652SBlue Swirl         (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
592e72ca652SBlue Swirl         (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
593e72ca652SBlue Swirl         (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
594e72ca652SBlue Swirl         cc = 1;
595e72ca652SBlue Swirl     } else if (m2 & (1 << (9-neg))) {
596e72ca652SBlue Swirl         /* assume normalized number */
597e72ca652SBlue Swirl         cc = 1;
598e72ca652SBlue Swirl     }
599e72ca652SBlue Swirl     /* FIXME: denormalized? */
600e72ca652SBlue Swirl     return cc;
601e72ca652SBlue Swirl }
602e72ca652SBlue Swirl 
603e72ca652SBlue Swirl /* test data class 128-bit */
60431aa97d1SRichard Henderson uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
605e72ca652SBlue Swirl {
60631aa97d1SRichard Henderson     float128 v1 = make_float128(ah, al);
60731aa97d1SRichard Henderson     int neg = float128_is_neg(v1);
608e72ca652SBlue Swirl     uint32_t cc = 0;
609e72ca652SBlue Swirl 
61031aa97d1SRichard Henderson     if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
61131aa97d1SRichard Henderson         (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
61231aa97d1SRichard Henderson         (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
61331aa97d1SRichard Henderson         (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
614e72ca652SBlue Swirl         cc = 1;
615e72ca652SBlue Swirl     } else if (m2 & (1 << (9-neg))) {
616e72ca652SBlue Swirl         /* assume normalized number */
617e72ca652SBlue Swirl         cc = 1;
618e72ca652SBlue Swirl     }
619e72ca652SBlue Swirl     /* FIXME: denormalized? */
620e72ca652SBlue Swirl     return cc;
621e72ca652SBlue Swirl }
622e72ca652SBlue Swirl 
62316d7b2a4SRichard Henderson /* square root 32-bit */
62416d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
625e72ca652SBlue Swirl {
62616d7b2a4SRichard Henderson     float32 ret = float32_sqrt(f2, &env->fpu_status);
62716d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
62816d7b2a4SRichard Henderson     return ret;
62916d7b2a4SRichard Henderson }
63016d7b2a4SRichard Henderson 
63116d7b2a4SRichard Henderson /* square root 64-bit */
63216d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
63316d7b2a4SRichard Henderson {
63416d7b2a4SRichard Henderson     float64 ret = float64_sqrt(f2, &env->fpu_status);
63516d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
63616d7b2a4SRichard Henderson     return ret;
63716d7b2a4SRichard Henderson }
63816d7b2a4SRichard Henderson 
63916d7b2a4SRichard Henderson /* square root 128-bit */
64016d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
64116d7b2a4SRichard Henderson {
64216d7b2a4SRichard Henderson     float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
64316d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
64416d7b2a4SRichard Henderson     return RET128(ret);
645e72ca652SBlue Swirl }
6468379bfdbSRichard Henderson 
6478379bfdbSRichard Henderson /* set fpc */
6488379bfdbSRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
6498379bfdbSRichard Henderson {
6508379bfdbSRichard Henderson     static const int rnd[4] = {
6518379bfdbSRichard Henderson         float_round_nearest_even,
6528379bfdbSRichard Henderson         float_round_to_zero,
6538379bfdbSRichard Henderson         float_round_up,
6548379bfdbSRichard Henderson         float_round_down
6558379bfdbSRichard Henderson     };
6568379bfdbSRichard Henderson 
6578379bfdbSRichard Henderson     /* Install everything in the main FPC.  */
6588379bfdbSRichard Henderson     env->fpc = fpc;
6598379bfdbSRichard Henderson 
6608379bfdbSRichard Henderson     /* Install the rounding mode in the shadow fpu_status.  */
6618379bfdbSRichard Henderson     set_float_rounding_mode(rnd[fpc & 3], &env->fpu_status);
6628379bfdbSRichard Henderson }
663