xref: /qemu/target/s390x/tcg/fpu_helper.c (revision ed0bcecec105137567f461e5b57834e72c851855)
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"
22f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h"
232ef6175aSRichard Henderson #include "exec/helper-proto.h"
24e72ca652SBlue Swirl 
25e72ca652SBlue Swirl /* #define DEBUG_HELPER */
26e72ca652SBlue Swirl #ifdef DEBUG_HELPER
27e72ca652SBlue Swirl #define HELPER_LOG(x...) qemu_log(x)
28e72ca652SBlue Swirl #else
29e72ca652SBlue Swirl #define HELPER_LOG(x...)
30e72ca652SBlue Swirl #endif
31e72ca652SBlue Swirl 
32587626f8SRichard Henderson #define RET128(F) (env->retxl = F.low, F.high)
33587626f8SRichard Henderson 
34587626f8SRichard Henderson #define convert_bit(mask, from, to) \
35587626f8SRichard Henderson     (to < from                      \
36587626f8SRichard Henderson      ? (mask / (from / to)) & to    \
37587626f8SRichard Henderson      : (mask & from) * (to / from))
38587626f8SRichard Henderson 
39587626f8SRichard Henderson static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
40587626f8SRichard Henderson {
41587626f8SRichard Henderson     /* Install the DXC code.  */
42587626f8SRichard Henderson     env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
43587626f8SRichard Henderson     /* Trap.  */
44587626f8SRichard Henderson     runtime_exception(env, PGM_DATA, retaddr);
45587626f8SRichard Henderson }
46587626f8SRichard Henderson 
47587626f8SRichard Henderson /* Should be called after any operation that may raise IEEE exceptions.  */
48587626f8SRichard Henderson static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
49587626f8SRichard Henderson {
50587626f8SRichard Henderson     unsigned s390_exc, qemu_exc;
51587626f8SRichard Henderson 
52587626f8SRichard Henderson     /* Get the exceptions raised by the current operation.  Reset the
53587626f8SRichard Henderson        fpu_status contents so that the next operation has a clean slate.  */
54587626f8SRichard Henderson     qemu_exc = env->fpu_status.float_exception_flags;
55587626f8SRichard Henderson     if (qemu_exc == 0) {
56587626f8SRichard Henderson         return;
57587626f8SRichard Henderson     }
58587626f8SRichard Henderson     env->fpu_status.float_exception_flags = 0;
59587626f8SRichard Henderson 
60587626f8SRichard Henderson     /* Convert softfloat exception bits to s390 exception bits.  */
61587626f8SRichard Henderson     s390_exc = 0;
62587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
63587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
64587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
65587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
66587626f8SRichard Henderson     s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
67587626f8SRichard Henderson 
68587626f8SRichard Henderson     /* Install the exceptions that we raised.  */
69587626f8SRichard Henderson     env->fpc |= s390_exc << 16;
70587626f8SRichard Henderson 
71587626f8SRichard Henderson     /* Send signals for enabled exceptions.  */
72587626f8SRichard Henderson     s390_exc &= env->fpc >> 24;
73587626f8SRichard Henderson     if (s390_exc) {
74587626f8SRichard Henderson         ieee_exception(env, s390_exc, retaddr);
75587626f8SRichard Henderson     }
76587626f8SRichard Henderson }
77587626f8SRichard Henderson 
78449c0d70SBlue Swirl static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
79e72ca652SBlue Swirl {
80a47dddd7SAndreas Färber     S390CPU *cpu = s390_env_get_cpu(env);
81a47dddd7SAndreas Färber 
82e72ca652SBlue Swirl     switch (float_compare) {
83e72ca652SBlue Swirl     case float_relation_equal:
84e72ca652SBlue Swirl         return 0;
85e72ca652SBlue Swirl     case float_relation_less:
86e72ca652SBlue Swirl         return 1;
87e72ca652SBlue Swirl     case float_relation_greater:
88e72ca652SBlue Swirl         return 2;
89e72ca652SBlue Swirl     case float_relation_unordered:
90e72ca652SBlue Swirl         return 3;
91e72ca652SBlue Swirl     default:
92a47dddd7SAndreas Färber         cpu_abort(CPU(cpu), "unknown return value for float compare\n");
93e72ca652SBlue Swirl     }
94e72ca652SBlue Swirl }
95e72ca652SBlue Swirl 
96e72ca652SBlue Swirl /* condition codes for unary FP ops */
97e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v)
98e72ca652SBlue Swirl {
99e72ca652SBlue Swirl     if (float32_is_any_nan(v)) {
100e72ca652SBlue Swirl         return 3;
101e72ca652SBlue Swirl     } else if (float32_is_zero(v)) {
102e72ca652SBlue Swirl         return 0;
103e72ca652SBlue Swirl     } else if (float32_is_neg(v)) {
104e72ca652SBlue Swirl         return 1;
105e72ca652SBlue Swirl     } else {
106e72ca652SBlue Swirl         return 2;
107e72ca652SBlue Swirl     }
108e72ca652SBlue Swirl }
109e72ca652SBlue Swirl 
110e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v)
111e72ca652SBlue Swirl {
112e72ca652SBlue Swirl     if (float64_is_any_nan(v)) {
113e72ca652SBlue Swirl         return 3;
114e72ca652SBlue Swirl     } else if (float64_is_zero(v)) {
115e72ca652SBlue Swirl         return 0;
116e72ca652SBlue Swirl     } else if (float64_is_neg(v)) {
117e72ca652SBlue Swirl         return 1;
118e72ca652SBlue Swirl     } else {
119e72ca652SBlue Swirl         return 2;
120e72ca652SBlue Swirl     }
121e72ca652SBlue Swirl }
122e72ca652SBlue Swirl 
123587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v)
124e72ca652SBlue Swirl {
125e72ca652SBlue Swirl     if (float128_is_any_nan(v)) {
126e72ca652SBlue Swirl         return 3;
127e72ca652SBlue Swirl     } else if (float128_is_zero(v)) {
128e72ca652SBlue Swirl         return 0;
129e72ca652SBlue Swirl     } else if (float128_is_neg(v)) {
130e72ca652SBlue Swirl         return 1;
131e72ca652SBlue Swirl     } else {
132e72ca652SBlue Swirl         return 2;
133e72ca652SBlue Swirl     }
134e72ca652SBlue Swirl }
135e72ca652SBlue Swirl 
136587626f8SRichard Henderson /* 32-bit FP addition */
137587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
138e72ca652SBlue Swirl {
139587626f8SRichard Henderson     float32 ret = float32_add(f1, f2, &env->fpu_status);
140587626f8SRichard Henderson     handle_exceptions(env, GETPC());
141587626f8SRichard Henderson     return ret;
142e72ca652SBlue Swirl }
143e72ca652SBlue Swirl 
144587626f8SRichard Henderson /* 64-bit FP addition */
145587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
146e72ca652SBlue Swirl {
147587626f8SRichard Henderson     float64 ret = float64_add(f1, f2, &env->fpu_status);
148587626f8SRichard Henderson     handle_exceptions(env, GETPC());
149587626f8SRichard Henderson     return ret;
150587626f8SRichard Henderson }
151e72ca652SBlue Swirl 
152587626f8SRichard Henderson /* 128-bit FP addition */
153587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
154587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
155587626f8SRichard Henderson {
156587626f8SRichard Henderson     float128 ret = float128_add(make_float128(ah, al),
157587626f8SRichard Henderson                                 make_float128(bh, bl),
158587626f8SRichard Henderson                                 &env->fpu_status);
159587626f8SRichard Henderson     handle_exceptions(env, GETPC());
160587626f8SRichard Henderson     return RET128(ret);
161e72ca652SBlue Swirl }
162e72ca652SBlue Swirl 
1631a800a2dSRichard Henderson /* 32-bit FP subtraction */
1641a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
165e72ca652SBlue Swirl {
1661a800a2dSRichard Henderson     float32 ret = float32_sub(f1, f2, &env->fpu_status);
1671a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
1681a800a2dSRichard Henderson     return ret;
169e72ca652SBlue Swirl }
170e72ca652SBlue Swirl 
1711a800a2dSRichard Henderson /* 64-bit FP subtraction */
1721a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
173e72ca652SBlue Swirl {
1741a800a2dSRichard Henderson     float64 ret = float64_sub(f1, f2, &env->fpu_status);
1751a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
1761a800a2dSRichard Henderson     return ret;
1771a800a2dSRichard Henderson }
178e72ca652SBlue Swirl 
1791a800a2dSRichard Henderson /* 128-bit FP subtraction */
1801a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
1811a800a2dSRichard Henderson                      uint64_t bh, uint64_t bl)
1821a800a2dSRichard Henderson {
1831a800a2dSRichard Henderson     float128 ret = float128_sub(make_float128(ah, al),
1841a800a2dSRichard Henderson                                 make_float128(bh, bl),
1851a800a2dSRichard Henderson                                 &env->fpu_status);
1861a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
1871a800a2dSRichard Henderson     return RET128(ret);
188e72ca652SBlue Swirl }
189e72ca652SBlue Swirl 
190f08a5c31SRichard Henderson /* 32-bit FP division */
191f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
192e72ca652SBlue Swirl {
193f08a5c31SRichard Henderson     float32 ret = float32_div(f1, f2, &env->fpu_status);
194f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
195f08a5c31SRichard Henderson     return ret;
196e72ca652SBlue Swirl }
197e72ca652SBlue Swirl 
198f08a5c31SRichard Henderson /* 64-bit FP division */
199f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
200e72ca652SBlue Swirl {
201f08a5c31SRichard Henderson     float64 ret = float64_div(f1, f2, &env->fpu_status);
202f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
203f08a5c31SRichard Henderson     return ret;
204f08a5c31SRichard Henderson }
205e72ca652SBlue Swirl 
206f08a5c31SRichard Henderson /* 128-bit FP division */
207f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
208f08a5c31SRichard Henderson                      uint64_t bh, uint64_t bl)
209f08a5c31SRichard Henderson {
210f08a5c31SRichard Henderson     float128 ret = float128_div(make_float128(ah, al),
211f08a5c31SRichard Henderson                                 make_float128(bh, bl),
212f08a5c31SRichard Henderson                                 &env->fpu_status);
213f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
214f08a5c31SRichard Henderson     return RET128(ret);
215e72ca652SBlue Swirl }
216e72ca652SBlue Swirl 
21783b00736SRichard Henderson /* 32-bit FP multiplication */
21883b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
219e72ca652SBlue Swirl {
22083b00736SRichard Henderson     float32 ret = float32_mul(f1, f2, &env->fpu_status);
22183b00736SRichard Henderson     handle_exceptions(env, GETPC());
22283b00736SRichard Henderson     return ret;
223e72ca652SBlue Swirl }
224e72ca652SBlue Swirl 
22583b00736SRichard Henderson /* 64-bit FP multiplication */
22683b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
227e72ca652SBlue Swirl {
22883b00736SRichard Henderson     float64 ret = float64_mul(f1, f2, &env->fpu_status);
22983b00736SRichard Henderson     handle_exceptions(env, GETPC());
23083b00736SRichard Henderson     return ret;
23183b00736SRichard Henderson }
232e72ca652SBlue Swirl 
23383b00736SRichard Henderson /* 64/32-bit FP multiplication */
23483b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
23583b00736SRichard Henderson {
23683b00736SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
23783b00736SRichard Henderson     ret = float64_mul(f1, ret, &env->fpu_status);
23883b00736SRichard Henderson     handle_exceptions(env, GETPC());
23983b00736SRichard Henderson     return ret;
24083b00736SRichard Henderson }
24183b00736SRichard Henderson 
24283b00736SRichard Henderson /* 128-bit FP multiplication */
24383b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
24483b00736SRichard Henderson                      uint64_t bh, uint64_t bl)
24583b00736SRichard Henderson {
24683b00736SRichard Henderson     float128 ret = float128_mul(make_float128(ah, al),
24783b00736SRichard Henderson                                 make_float128(bh, bl),
24883b00736SRichard Henderson                                 &env->fpu_status);
24983b00736SRichard Henderson     handle_exceptions(env, GETPC());
25083b00736SRichard Henderson     return RET128(ret);
25183b00736SRichard Henderson }
25283b00736SRichard Henderson 
25383b00736SRichard Henderson /* 128/64-bit FP multiplication */
25483b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
25583b00736SRichard Henderson                       uint64_t f2)
25683b00736SRichard Henderson {
25783b00736SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
25883b00736SRichard Henderson     ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
25983b00736SRichard Henderson     handle_exceptions(env, GETPC());
26083b00736SRichard Henderson     return RET128(ret);
261e72ca652SBlue Swirl }
262e72ca652SBlue Swirl 
263e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */
264587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
265e72ca652SBlue Swirl {
266587626f8SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
267587626f8SRichard Henderson     handle_exceptions(env, GETPC());
268f821135cSAurelien Jarno     return float64_maybe_silence_nan(ret);
269e72ca652SBlue Swirl }
270e72ca652SBlue Swirl 
271e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */
272587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
273e72ca652SBlue Swirl {
274587626f8SRichard Henderson     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
275587626f8SRichard Henderson     handle_exceptions(env, GETPC());
276f821135cSAurelien Jarno     return float64_maybe_silence_nan(ret);
277e72ca652SBlue Swirl }
278e72ca652SBlue Swirl 
279e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */
280587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
281e72ca652SBlue Swirl {
282587626f8SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
283587626f8SRichard Henderson     handle_exceptions(env, GETPC());
284f821135cSAurelien Jarno     return RET128(float128_maybe_silence_nan(ret));
285587626f8SRichard Henderson }
286e72ca652SBlue Swirl 
287587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */
288587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
289587626f8SRichard Henderson {
290587626f8SRichard Henderson     float128 ret = float32_to_float128(f2, &env->fpu_status);
291587626f8SRichard Henderson     handle_exceptions(env, GETPC());
292f821135cSAurelien Jarno     return RET128(float128_maybe_silence_nan(ret));
293e72ca652SBlue Swirl }
294e72ca652SBlue Swirl 
295e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */
296587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
297e72ca652SBlue Swirl {
298587626f8SRichard Henderson     float32 ret = float64_to_float32(f2, &env->fpu_status);
299587626f8SRichard Henderson     handle_exceptions(env, GETPC());
300f821135cSAurelien Jarno     return float32_maybe_silence_nan(ret);
301e72ca652SBlue Swirl }
302e72ca652SBlue Swirl 
303e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */
304587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
305e72ca652SBlue Swirl {
306587626f8SRichard Henderson     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
307587626f8SRichard Henderson     handle_exceptions(env, GETPC());
308f821135cSAurelien Jarno     return float32_maybe_silence_nan(ret);
309e72ca652SBlue Swirl }
310e72ca652SBlue Swirl 
311587626f8SRichard Henderson /* 32-bit FP compare */
312587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
313e72ca652SBlue Swirl {
314587626f8SRichard Henderson     int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
315587626f8SRichard Henderson     handle_exceptions(env, GETPC());
316587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
317e72ca652SBlue Swirl }
318e72ca652SBlue Swirl 
319587626f8SRichard Henderson /* 64-bit FP compare */
320587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
321e72ca652SBlue Swirl {
322587626f8SRichard Henderson     int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
323587626f8SRichard Henderson     handle_exceptions(env, GETPC());
324587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
325e72ca652SBlue Swirl }
326e72ca652SBlue Swirl 
327587626f8SRichard Henderson /* 128-bit FP compare */
328587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
329587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
330e72ca652SBlue Swirl {
331587626f8SRichard Henderson     int cmp = float128_compare_quiet(make_float128(ah, al),
332587626f8SRichard Henderson                                      make_float128(bh, bl),
333587626f8SRichard Henderson                                      &env->fpu_status);
334587626f8SRichard Henderson     handle_exceptions(env, GETPC());
335587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
336e72ca652SBlue Swirl }
337e72ca652SBlue Swirl 
33868c8bd93SRichard Henderson static int swap_round_mode(CPUS390XState *env, int m3)
339e72ca652SBlue Swirl {
34068c8bd93SRichard Henderson     int ret = env->fpu_status.float_rounding_mode;
341e72ca652SBlue Swirl     switch (m3) {
342e72ca652SBlue Swirl     case 0:
343e72ca652SBlue Swirl         /* current mode */
344e72ca652SBlue Swirl         break;
345e72ca652SBlue Swirl     case 1:
346e72ca652SBlue Swirl         /* biased round no nearest */
347e72ca652SBlue Swirl     case 4:
348e72ca652SBlue Swirl         /* round to nearest */
349e72ca652SBlue Swirl         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
350e72ca652SBlue Swirl         break;
351e72ca652SBlue Swirl     case 5:
352e72ca652SBlue Swirl         /* round to zero */
353e72ca652SBlue Swirl         set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
354e72ca652SBlue Swirl         break;
355e72ca652SBlue Swirl     case 6:
356e72ca652SBlue Swirl         /* round to +inf */
357e72ca652SBlue Swirl         set_float_rounding_mode(float_round_up, &env->fpu_status);
358e72ca652SBlue Swirl         break;
359e72ca652SBlue Swirl     case 7:
360e72ca652SBlue Swirl         /* round to -inf */
361e72ca652SBlue Swirl         set_float_rounding_mode(float_round_down, &env->fpu_status);
362e72ca652SBlue Swirl         break;
363e72ca652SBlue Swirl     }
36468c8bd93SRichard Henderson     return ret;
365e72ca652SBlue Swirl }
366e72ca652SBlue Swirl 
367683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */
368683bb9a8SRichard Henderson uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
369683bb9a8SRichard Henderson {
370683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
371683bb9a8SRichard Henderson     float32 ret = int64_to_float32(v2, &env->fpu_status);
372683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
373683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
374683bb9a8SRichard Henderson     return ret;
375683bb9a8SRichard Henderson }
376683bb9a8SRichard Henderson 
377683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */
378683bb9a8SRichard Henderson uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
379683bb9a8SRichard Henderson {
380683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
381683bb9a8SRichard Henderson     float64 ret = int64_to_float64(v2, &env->fpu_status);
382683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
383683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
384683bb9a8SRichard Henderson     return ret;
385683bb9a8SRichard Henderson }
386683bb9a8SRichard Henderson 
387683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */
388683bb9a8SRichard Henderson uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
389683bb9a8SRichard Henderson {
390683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
391683bb9a8SRichard Henderson     float128 ret = int64_to_float128(v2, &env->fpu_status);
392683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
393683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
394683bb9a8SRichard Henderson     return RET128(ret);
395683bb9a8SRichard Henderson }
396683bb9a8SRichard Henderson 
3972112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */
3982112bf1bSRichard Henderson uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
3992112bf1bSRichard Henderson {
4002112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
4012112bf1bSRichard Henderson     float32 ret = uint64_to_float32(v2, &env->fpu_status);
4022112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4032112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4042112bf1bSRichard Henderson     return ret;
4052112bf1bSRichard Henderson }
4062112bf1bSRichard Henderson 
4072112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */
4082112bf1bSRichard Henderson uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4092112bf1bSRichard Henderson {
4102112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
4112112bf1bSRichard Henderson     float64 ret = uint64_to_float64(v2, &env->fpu_status);
4122112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4132112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4142112bf1bSRichard Henderson     return ret;
4152112bf1bSRichard Henderson }
4162112bf1bSRichard Henderson 
4172112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */
4182112bf1bSRichard Henderson uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4192112bf1bSRichard Henderson {
4202112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
421d2d9feacSRichard Henderson     float128 ret = uint64_to_float128(v2, &env->fpu_status);
4222112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4232112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4242112bf1bSRichard Henderson     return RET128(ret);
4252112bf1bSRichard Henderson }
4262112bf1bSRichard Henderson 
427e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */
42868c8bd93SRichard Henderson uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
429e72ca652SBlue Swirl {
43068c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
43168c8bd93SRichard Henderson     int64_t ret = float32_to_int64(v2, &env->fpu_status);
43268c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
43368c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
43468c8bd93SRichard Henderson     return ret;
435e72ca652SBlue Swirl }
436e72ca652SBlue Swirl 
437e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */
43868c8bd93SRichard Henderson uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
439e72ca652SBlue Swirl {
44068c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
44168c8bd93SRichard Henderson     int64_t ret = float64_to_int64(v2, &env->fpu_status);
44268c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
44368c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
44468c8bd93SRichard Henderson     return ret;
445e72ca652SBlue Swirl }
446e72ca652SBlue Swirl 
447e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */
44868c8bd93SRichard Henderson uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
449e72ca652SBlue Swirl {
45068c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
45168c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
45268c8bd93SRichard Henderson     int64_t ret = float128_to_int64(v2, &env->fpu_status);
45368c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
45468c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
45568c8bd93SRichard Henderson     return ret;
456e72ca652SBlue Swirl }
457e72ca652SBlue Swirl 
458e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */
45968c8bd93SRichard Henderson uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
460e72ca652SBlue Swirl {
46168c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
46268c8bd93SRichard Henderson     int32_t ret = float32_to_int32(v2, &env->fpu_status);
46368c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
46468c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
46568c8bd93SRichard Henderson     return ret;
466e72ca652SBlue Swirl }
467e72ca652SBlue Swirl 
468e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */
46968c8bd93SRichard Henderson uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
470e72ca652SBlue Swirl {
47168c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
47268c8bd93SRichard Henderson     int32_t ret = float64_to_int32(v2, &env->fpu_status);
47368c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
47468c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
47568c8bd93SRichard Henderson     return ret;
476e72ca652SBlue Swirl }
477e72ca652SBlue Swirl 
478e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */
47968c8bd93SRichard Henderson uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
480e72ca652SBlue Swirl {
48168c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
48268c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
48368c8bd93SRichard Henderson     int32_t ret = float128_to_int32(v2, &env->fpu_status);
48468c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
48568c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
48668c8bd93SRichard Henderson     return ret;
487e72ca652SBlue Swirl }
488e72ca652SBlue Swirl 
4896ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */
4906ac1b45fSRichard Henderson uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4916ac1b45fSRichard Henderson {
4926ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
4936ac1b45fSRichard Henderson     uint64_t ret;
4946ac1b45fSRichard Henderson     v2 = float32_to_float64(v2, &env->fpu_status);
4956ac1b45fSRichard Henderson     ret = float64_to_uint64(v2, &env->fpu_status);
4966ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4976ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
4986ac1b45fSRichard Henderson     return ret;
4996ac1b45fSRichard Henderson }
5006ac1b45fSRichard Henderson 
5016ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */
5026ac1b45fSRichard Henderson uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5036ac1b45fSRichard Henderson {
5046ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5056ac1b45fSRichard Henderson     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
5066ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5076ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5086ac1b45fSRichard Henderson     return ret;
5096ac1b45fSRichard Henderson }
5106ac1b45fSRichard Henderson 
5116ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */
5126ac1b45fSRichard Henderson uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
5136ac1b45fSRichard Henderson {
5146ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5156ac1b45fSRichard Henderson     float128 v2 = make_float128(h, l);
5166ac1b45fSRichard Henderson     /* ??? Not 100% correct.  */
5176ac1b45fSRichard Henderson     uint64_t ret = float128_to_int64(v2, &env->fpu_status);
5186ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5196ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5206ac1b45fSRichard Henderson     return ret;
5216ac1b45fSRichard Henderson }
5226ac1b45fSRichard Henderson 
5236ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */
5246ac1b45fSRichard Henderson uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5256ac1b45fSRichard Henderson {
5266ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5276ac1b45fSRichard Henderson     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
5286ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5296ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5306ac1b45fSRichard Henderson     return ret;
5316ac1b45fSRichard Henderson }
5326ac1b45fSRichard Henderson 
5336ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */
5346ac1b45fSRichard Henderson uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5356ac1b45fSRichard Henderson {
5366ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5376ac1b45fSRichard Henderson     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
5386ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5396ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5406ac1b45fSRichard Henderson     return ret;
5416ac1b45fSRichard Henderson }
5426ac1b45fSRichard Henderson 
5436ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */
5446ac1b45fSRichard Henderson uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
5456ac1b45fSRichard Henderson {
5466ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5476ac1b45fSRichard Henderson     float128 v2 = make_float128(h, l);
5486ac1b45fSRichard Henderson     /* Not 100% correct.  */
5496ac1b45fSRichard Henderson     uint32_t ret = float128_to_int64(v2, &env->fpu_status);
5506ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5516ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5526ac1b45fSRichard Henderson     return ret;
5536ac1b45fSRichard Henderson }
5546ac1b45fSRichard Henderson 
555ed0bceceSAurelien Jarno /* round to integer 32-bit */
556ed0bceceSAurelien Jarno uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
557ed0bceceSAurelien Jarno {
558ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
559ed0bceceSAurelien Jarno     float32 ret = float32_round_to_int(f2, &env->fpu_status);
560ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
561ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
562ed0bceceSAurelien Jarno     return ret;
563ed0bceceSAurelien Jarno }
564ed0bceceSAurelien Jarno 
565ed0bceceSAurelien Jarno /* round to integer 64-bit */
566ed0bceceSAurelien Jarno uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
567ed0bceceSAurelien Jarno {
568ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
569ed0bceceSAurelien Jarno     float64 ret = float64_round_to_int(f2, &env->fpu_status);
570ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
571ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
572ed0bceceSAurelien Jarno     return ret;
573ed0bceceSAurelien Jarno }
574ed0bceceSAurelien Jarno 
575ed0bceceSAurelien Jarno /* round to integer 128-bit */
576ed0bceceSAurelien Jarno uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
577ed0bceceSAurelien Jarno {
578ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
579ed0bceceSAurelien Jarno     float128 ret = float128_round_to_int(make_float128(ah, al),
580ed0bceceSAurelien Jarno                                          &env->fpu_status);
581ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
582ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
583ed0bceceSAurelien Jarno     return RET128(ret);
584ed0bceceSAurelien Jarno }
585ed0bceceSAurelien Jarno 
586722bfec3SRichard Henderson /* 32-bit FP multiply and add */
587722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
588722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
589e72ca652SBlue Swirl {
590722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
591722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
592722bfec3SRichard Henderson     return ret;
593722bfec3SRichard Henderson }
594e72ca652SBlue Swirl 
595722bfec3SRichard Henderson /* 64-bit FP multiply and add */
596722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
597722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
598722bfec3SRichard Henderson {
599722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
600722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
601722bfec3SRichard Henderson     return ret;
602722bfec3SRichard Henderson }
603722bfec3SRichard Henderson 
604722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */
605722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
606722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
607722bfec3SRichard Henderson {
608722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
609e72ca652SBlue Swirl                                  &env->fpu_status);
610722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
611722bfec3SRichard Henderson     return ret;
612e72ca652SBlue Swirl }
613e72ca652SBlue Swirl 
614722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */
615722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
616722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
617e72ca652SBlue Swirl {
618722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
619e72ca652SBlue Swirl                                  &env->fpu_status);
620722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
621722bfec3SRichard Henderson     return ret;
622e72ca652SBlue Swirl }
623e72ca652SBlue Swirl 
624e72ca652SBlue Swirl /* test data class 32-bit */
62531aa97d1SRichard Henderson uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2)
626e72ca652SBlue Swirl {
62731aa97d1SRichard Henderson     float32 v1 = f1;
628e72ca652SBlue Swirl     int neg = float32_is_neg(v1);
629e72ca652SBlue Swirl     uint32_t cc = 0;
630e72ca652SBlue Swirl 
631e72ca652SBlue Swirl     if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
632e72ca652SBlue Swirl         (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
633e72ca652SBlue Swirl         (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
634e72ca652SBlue Swirl         (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
635e72ca652SBlue Swirl         cc = 1;
636e72ca652SBlue Swirl     } else if (m2 & (1 << (9-neg))) {
637e72ca652SBlue Swirl         /* assume normalized number */
638e72ca652SBlue Swirl         cc = 1;
639e72ca652SBlue Swirl     }
640e72ca652SBlue Swirl     /* FIXME: denormalized? */
641e72ca652SBlue Swirl     return cc;
642e72ca652SBlue Swirl }
643e72ca652SBlue Swirl 
644e72ca652SBlue Swirl /* test data class 64-bit */
64531aa97d1SRichard Henderson uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2)
646e72ca652SBlue Swirl {
647e72ca652SBlue Swirl     int neg = float64_is_neg(v1);
648e72ca652SBlue Swirl     uint32_t cc = 0;
649e72ca652SBlue Swirl 
650e72ca652SBlue Swirl     if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
651e72ca652SBlue Swirl         (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
652e72ca652SBlue Swirl         (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
653e72ca652SBlue Swirl         (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
654e72ca652SBlue Swirl         cc = 1;
655e72ca652SBlue Swirl     } else if (m2 & (1 << (9-neg))) {
656e72ca652SBlue Swirl         /* assume normalized number */
657e72ca652SBlue Swirl         cc = 1;
658e72ca652SBlue Swirl     }
659e72ca652SBlue Swirl     /* FIXME: denormalized? */
660e72ca652SBlue Swirl     return cc;
661e72ca652SBlue Swirl }
662e72ca652SBlue Swirl 
663e72ca652SBlue Swirl /* test data class 128-bit */
66431aa97d1SRichard Henderson uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
665e72ca652SBlue Swirl {
66631aa97d1SRichard Henderson     float128 v1 = make_float128(ah, al);
66731aa97d1SRichard Henderson     int neg = float128_is_neg(v1);
668e72ca652SBlue Swirl     uint32_t cc = 0;
669e72ca652SBlue Swirl 
67031aa97d1SRichard Henderson     if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
67131aa97d1SRichard Henderson         (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
67231aa97d1SRichard Henderson         (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
67331aa97d1SRichard Henderson         (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
674e72ca652SBlue Swirl         cc = 1;
675e72ca652SBlue Swirl     } else if (m2 & (1 << (9-neg))) {
676e72ca652SBlue Swirl         /* assume normalized number */
677e72ca652SBlue Swirl         cc = 1;
678e72ca652SBlue Swirl     }
679e72ca652SBlue Swirl     /* FIXME: denormalized? */
680e72ca652SBlue Swirl     return cc;
681e72ca652SBlue Swirl }
682e72ca652SBlue Swirl 
68316d7b2a4SRichard Henderson /* square root 32-bit */
68416d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
685e72ca652SBlue Swirl {
68616d7b2a4SRichard Henderson     float32 ret = float32_sqrt(f2, &env->fpu_status);
68716d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
68816d7b2a4SRichard Henderson     return ret;
68916d7b2a4SRichard Henderson }
69016d7b2a4SRichard Henderson 
69116d7b2a4SRichard Henderson /* square root 64-bit */
69216d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
69316d7b2a4SRichard Henderson {
69416d7b2a4SRichard Henderson     float64 ret = float64_sqrt(f2, &env->fpu_status);
69516d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
69616d7b2a4SRichard Henderson     return ret;
69716d7b2a4SRichard Henderson }
69816d7b2a4SRichard Henderson 
69916d7b2a4SRichard Henderson /* square root 128-bit */
70016d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
70116d7b2a4SRichard Henderson {
70216d7b2a4SRichard Henderson     float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
70316d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
70416d7b2a4SRichard Henderson     return RET128(ret);
705e72ca652SBlue Swirl }
7068379bfdbSRichard Henderson 
707411edc22SRichard Henderson static const int fpc_to_rnd[4] = {
7088379bfdbSRichard Henderson     float_round_nearest_even,
7098379bfdbSRichard Henderson     float_round_to_zero,
7108379bfdbSRichard Henderson     float_round_up,
7118379bfdbSRichard Henderson     float_round_down
7128379bfdbSRichard Henderson };
7138379bfdbSRichard Henderson 
714411edc22SRichard Henderson /* set fpc */
715411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
716411edc22SRichard Henderson {
7178379bfdbSRichard Henderson     /* Install everything in the main FPC.  */
7188379bfdbSRichard Henderson     env->fpc = fpc;
7198379bfdbSRichard Henderson 
7208379bfdbSRichard Henderson     /* Install the rounding mode in the shadow fpu_status.  */
721411edc22SRichard Henderson     set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
722411edc22SRichard Henderson }
723411edc22SRichard Henderson 
724411edc22SRichard Henderson /* set fpc and signal */
725411edc22SRichard Henderson void HELPER(sfas)(CPUS390XState *env, uint64_t val)
726411edc22SRichard Henderson {
727411edc22SRichard Henderson     uint32_t signalling = env->fpc;
728411edc22SRichard Henderson     uint32_t source = val;
729411edc22SRichard Henderson     uint32_t s390_exc;
730411edc22SRichard Henderson 
731411edc22SRichard Henderson     /* The contents of the source operand are placed in the FPC register;
732411edc22SRichard Henderson        then the flags in the FPC register are set to the logical OR of the
733411edc22SRichard Henderson        signalling flags and the source flags.  */
734411edc22SRichard Henderson     env->fpc = source | (signalling & 0x00ff0000);
735411edc22SRichard Henderson     set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
736411edc22SRichard Henderson 
737411edc22SRichard Henderson     /* If any signalling flag is 1 and the corresponding source mask
738411edc22SRichard Henderson        is also 1, a simulated-iee-exception trap occurs.  */
739411edc22SRichard Henderson     s390_exc = (signalling >> 16) & (source >> 24);
740411edc22SRichard Henderson     if (s390_exc) {
741411edc22SRichard Henderson         ieee_exception(env, s390_exc | 3, GETPC());
742411edc22SRichard Henderson     }
7438379bfdbSRichard Henderson }
744