xref: /qemu/target/s390x/tcg/fpu_helper.c (revision fcb9e9f2a1b229b834e4133f626c4f40b43f7b9d)
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
1041c6a6ddSThomas Huth  * version 2.1 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 
219615495aSPeter Maydell #include "qemu/osdep.h"
22e72ca652SBlue Swirl #include "cpu.h"
234e58b838SDavid Hildenbrand #include "internal.h"
24bbf6ea3bSDavid Hildenbrand #include "tcg_s390x.h"
2563c91552SPaolo Bonzini #include "exec/exec-all.h"
26f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h"
272ef6175aSRichard Henderson #include "exec/helper-proto.h"
2824f91e81SAlex Bennée #include "fpu/softfloat.h"
29e72ca652SBlue Swirl 
30e72ca652SBlue Swirl /* #define DEBUG_HELPER */
31e72ca652SBlue Swirl #ifdef DEBUG_HELPER
32e72ca652SBlue Swirl #define HELPER_LOG(x...) qemu_log(x)
33e72ca652SBlue Swirl #else
34e72ca652SBlue Swirl #define HELPER_LOG(x...)
35e72ca652SBlue Swirl #endif
36e72ca652SBlue Swirl 
37587626f8SRichard Henderson #define RET128(F) (env->retxl = F.low, F.high)
38587626f8SRichard Henderson 
394b70fc54SDavid Hildenbrand uint8_t s390_softfloat_exc_to_ieee(unsigned int exc)
404b70fc54SDavid Hildenbrand {
414b70fc54SDavid Hildenbrand     uint8_t s390_exc = 0;
424b70fc54SDavid Hildenbrand 
434b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_invalid) ? S390_IEEE_MASK_INVALID : 0;
444b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0;
454b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0;
464b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0;
474b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_inexact) ? S390_IEEE_MASK_INEXACT : 0;
484b70fc54SDavid Hildenbrand 
494b70fc54SDavid Hildenbrand     return s390_exc;
504b70fc54SDavid Hildenbrand }
51587626f8SRichard Henderson 
52587626f8SRichard Henderson /* Should be called after any operation that may raise IEEE exceptions.  */
53587626f8SRichard Henderson static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
54587626f8SRichard Henderson {
55587626f8SRichard Henderson     unsigned s390_exc, qemu_exc;
56587626f8SRichard Henderson 
57587626f8SRichard Henderson     /* Get the exceptions raised by the current operation.  Reset the
58587626f8SRichard Henderson        fpu_status contents so that the next operation has a clean slate.  */
59587626f8SRichard Henderson     qemu_exc = env->fpu_status.float_exception_flags;
60587626f8SRichard Henderson     if (qemu_exc == 0) {
61587626f8SRichard Henderson         return;
62587626f8SRichard Henderson     }
63587626f8SRichard Henderson     env->fpu_status.float_exception_flags = 0;
644b70fc54SDavid Hildenbrand     s390_exc = s390_softfloat_exc_to_ieee(qemu_exc);
65587626f8SRichard Henderson 
66*fcb9e9f2SDavid Hildenbrand     /*
67*fcb9e9f2SDavid Hildenbrand      * FIXME:
68*fcb9e9f2SDavid Hildenbrand      * 1. Right now, all inexact conditions are inidicated as
69*fcb9e9f2SDavid Hildenbrand      *    "truncated" (0) and never as "incremented" (1) in the DXC.
70*fcb9e9f2SDavid Hildenbrand      * 2. Only traps due to invalid/divbyzero are suppressing. Other traps
71*fcb9e9f2SDavid Hildenbrand      *    are completing, meaning the target register has to be written!
72*fcb9e9f2SDavid Hildenbrand      *    This, however will mean that we have to write the register before
73*fcb9e9f2SDavid Hildenbrand      *    triggering the trap - impossible right now.
74*fcb9e9f2SDavid Hildenbrand      */
75587626f8SRichard Henderson 
76*fcb9e9f2SDavid Hildenbrand     /*
77*fcb9e9f2SDavid Hildenbrand      * invalid/divbyzero cannot coexist with other conditions.
78*fcb9e9f2SDavid Hildenbrand      * overflow/underflow however can coexist with inexact, we have to
79*fcb9e9f2SDavid Hildenbrand      * handle it separatly.
80*fcb9e9f2SDavid Hildenbrand      */
81*fcb9e9f2SDavid Hildenbrand     if (s390_exc & ~S390_IEEE_MASK_INEXACT) {
82*fcb9e9f2SDavid Hildenbrand         if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
83*fcb9e9f2SDavid Hildenbrand             /* trap condition - inexact reported along */
84bbf6ea3bSDavid Hildenbrand             tcg_s390_data_exception(env, s390_exc, retaddr);
85587626f8SRichard Henderson         }
86*fcb9e9f2SDavid Hildenbrand         /* nontrap condition - inexact handled differently */
87*fcb9e9f2SDavid Hildenbrand         env->fpc |= (s390_exc & ~S390_IEEE_MASK_INEXACT) << 16;
88*fcb9e9f2SDavid Hildenbrand     }
89*fcb9e9f2SDavid Hildenbrand 
90*fcb9e9f2SDavid Hildenbrand     /* inexact handling */
91*fcb9e9f2SDavid Hildenbrand     if (s390_exc & S390_IEEE_MASK_INEXACT) {
92*fcb9e9f2SDavid Hildenbrand         /* trap condition - overflow/underflow _not_ reported along */
93*fcb9e9f2SDavid Hildenbrand         if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
94*fcb9e9f2SDavid Hildenbrand             tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT,
95*fcb9e9f2SDavid Hildenbrand                                     retaddr);
96*fcb9e9f2SDavid Hildenbrand         }
97*fcb9e9f2SDavid Hildenbrand         /* nontrap condition */
98*fcb9e9f2SDavid Hildenbrand         env->fpc |= (s390_exc & S390_IEEE_MASK_INEXACT) << 16;
99*fcb9e9f2SDavid Hildenbrand     }
100587626f8SRichard Henderson }
101587626f8SRichard Henderson 
102449c0d70SBlue Swirl static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
103e72ca652SBlue Swirl {
104a47dddd7SAndreas Färber     S390CPU *cpu = s390_env_get_cpu(env);
105a47dddd7SAndreas Färber 
106e72ca652SBlue Swirl     switch (float_compare) {
107e72ca652SBlue Swirl     case float_relation_equal:
108e72ca652SBlue Swirl         return 0;
109e72ca652SBlue Swirl     case float_relation_less:
110e72ca652SBlue Swirl         return 1;
111e72ca652SBlue Swirl     case float_relation_greater:
112e72ca652SBlue Swirl         return 2;
113e72ca652SBlue Swirl     case float_relation_unordered:
114e72ca652SBlue Swirl         return 3;
115e72ca652SBlue Swirl     default:
116a47dddd7SAndreas Färber         cpu_abort(CPU(cpu), "unknown return value for float compare\n");
117e72ca652SBlue Swirl     }
118e72ca652SBlue Swirl }
119e72ca652SBlue Swirl 
120e72ca652SBlue Swirl /* condition codes for unary FP ops */
121e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v)
122e72ca652SBlue Swirl {
123e72ca652SBlue Swirl     if (float32_is_any_nan(v)) {
124e72ca652SBlue Swirl         return 3;
125e72ca652SBlue Swirl     } else if (float32_is_zero(v)) {
126e72ca652SBlue Swirl         return 0;
127e72ca652SBlue Swirl     } else if (float32_is_neg(v)) {
128e72ca652SBlue Swirl         return 1;
129e72ca652SBlue Swirl     } else {
130e72ca652SBlue Swirl         return 2;
131e72ca652SBlue Swirl     }
132e72ca652SBlue Swirl }
133e72ca652SBlue Swirl 
134e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v)
135e72ca652SBlue Swirl {
136e72ca652SBlue Swirl     if (float64_is_any_nan(v)) {
137e72ca652SBlue Swirl         return 3;
138e72ca652SBlue Swirl     } else if (float64_is_zero(v)) {
139e72ca652SBlue Swirl         return 0;
140e72ca652SBlue Swirl     } else if (float64_is_neg(v)) {
141e72ca652SBlue Swirl         return 1;
142e72ca652SBlue Swirl     } else {
143e72ca652SBlue Swirl         return 2;
144e72ca652SBlue Swirl     }
145e72ca652SBlue Swirl }
146e72ca652SBlue Swirl 
147587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v)
148e72ca652SBlue Swirl {
149e72ca652SBlue Swirl     if (float128_is_any_nan(v)) {
150e72ca652SBlue Swirl         return 3;
151e72ca652SBlue Swirl     } else if (float128_is_zero(v)) {
152e72ca652SBlue Swirl         return 0;
153e72ca652SBlue Swirl     } else if (float128_is_neg(v)) {
154e72ca652SBlue Swirl         return 1;
155e72ca652SBlue Swirl     } else {
156e72ca652SBlue Swirl         return 2;
157e72ca652SBlue Swirl     }
158e72ca652SBlue Swirl }
159e72ca652SBlue Swirl 
160587626f8SRichard Henderson /* 32-bit FP addition */
161587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
162e72ca652SBlue Swirl {
163587626f8SRichard Henderson     float32 ret = float32_add(f1, f2, &env->fpu_status);
164587626f8SRichard Henderson     handle_exceptions(env, GETPC());
165587626f8SRichard Henderson     return ret;
166e72ca652SBlue Swirl }
167e72ca652SBlue Swirl 
168587626f8SRichard Henderson /* 64-bit FP addition */
169587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
170e72ca652SBlue Swirl {
171587626f8SRichard Henderson     float64 ret = float64_add(f1, f2, &env->fpu_status);
172587626f8SRichard Henderson     handle_exceptions(env, GETPC());
173587626f8SRichard Henderson     return ret;
174587626f8SRichard Henderson }
175e72ca652SBlue Swirl 
176587626f8SRichard Henderson /* 128-bit FP addition */
177587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
178587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
179587626f8SRichard Henderson {
180587626f8SRichard Henderson     float128 ret = float128_add(make_float128(ah, al),
181587626f8SRichard Henderson                                 make_float128(bh, bl),
182587626f8SRichard Henderson                                 &env->fpu_status);
183587626f8SRichard Henderson     handle_exceptions(env, GETPC());
184587626f8SRichard Henderson     return RET128(ret);
185e72ca652SBlue Swirl }
186e72ca652SBlue Swirl 
1871a800a2dSRichard Henderson /* 32-bit FP subtraction */
1881a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
189e72ca652SBlue Swirl {
1901a800a2dSRichard Henderson     float32 ret = float32_sub(f1, f2, &env->fpu_status);
1911a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
1921a800a2dSRichard Henderson     return ret;
193e72ca652SBlue Swirl }
194e72ca652SBlue Swirl 
1951a800a2dSRichard Henderson /* 64-bit FP subtraction */
1961a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
197e72ca652SBlue Swirl {
1981a800a2dSRichard Henderson     float64 ret = float64_sub(f1, f2, &env->fpu_status);
1991a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
2001a800a2dSRichard Henderson     return ret;
2011a800a2dSRichard Henderson }
202e72ca652SBlue Swirl 
2031a800a2dSRichard Henderson /* 128-bit FP subtraction */
2041a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
2051a800a2dSRichard Henderson                      uint64_t bh, uint64_t bl)
2061a800a2dSRichard Henderson {
2071a800a2dSRichard Henderson     float128 ret = float128_sub(make_float128(ah, al),
2081a800a2dSRichard Henderson                                 make_float128(bh, bl),
2091a800a2dSRichard Henderson                                 &env->fpu_status);
2101a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
2111a800a2dSRichard Henderson     return RET128(ret);
212e72ca652SBlue Swirl }
213e72ca652SBlue Swirl 
214f08a5c31SRichard Henderson /* 32-bit FP division */
215f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
216e72ca652SBlue Swirl {
217f08a5c31SRichard Henderson     float32 ret = float32_div(f1, f2, &env->fpu_status);
218f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
219f08a5c31SRichard Henderson     return ret;
220e72ca652SBlue Swirl }
221e72ca652SBlue Swirl 
222f08a5c31SRichard Henderson /* 64-bit FP division */
223f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
224e72ca652SBlue Swirl {
225f08a5c31SRichard Henderson     float64 ret = float64_div(f1, f2, &env->fpu_status);
226f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
227f08a5c31SRichard Henderson     return ret;
228f08a5c31SRichard Henderson }
229e72ca652SBlue Swirl 
230f08a5c31SRichard Henderson /* 128-bit FP division */
231f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
232f08a5c31SRichard Henderson                      uint64_t bh, uint64_t bl)
233f08a5c31SRichard Henderson {
234f08a5c31SRichard Henderson     float128 ret = float128_div(make_float128(ah, al),
235f08a5c31SRichard Henderson                                 make_float128(bh, bl),
236f08a5c31SRichard Henderson                                 &env->fpu_status);
237f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
238f08a5c31SRichard Henderson     return RET128(ret);
239e72ca652SBlue Swirl }
240e72ca652SBlue Swirl 
24183b00736SRichard Henderson /* 32-bit FP multiplication */
24283b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
243e72ca652SBlue Swirl {
24483b00736SRichard Henderson     float32 ret = float32_mul(f1, f2, &env->fpu_status);
24583b00736SRichard Henderson     handle_exceptions(env, GETPC());
24683b00736SRichard Henderson     return ret;
247e72ca652SBlue Swirl }
248e72ca652SBlue Swirl 
24983b00736SRichard Henderson /* 64-bit FP multiplication */
25083b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
251e72ca652SBlue Swirl {
25283b00736SRichard Henderson     float64 ret = float64_mul(f1, f2, &env->fpu_status);
25383b00736SRichard Henderson     handle_exceptions(env, GETPC());
25483b00736SRichard Henderson     return ret;
25583b00736SRichard Henderson }
256e72ca652SBlue Swirl 
25783b00736SRichard Henderson /* 64/32-bit FP multiplication */
25883b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
25983b00736SRichard Henderson {
26083b00736SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
26183b00736SRichard Henderson     ret = float64_mul(f1, ret, &env->fpu_status);
26283b00736SRichard Henderson     handle_exceptions(env, GETPC());
26383b00736SRichard Henderson     return ret;
26483b00736SRichard Henderson }
26583b00736SRichard Henderson 
26683b00736SRichard Henderson /* 128-bit FP multiplication */
26783b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
26883b00736SRichard Henderson                      uint64_t bh, uint64_t bl)
26983b00736SRichard Henderson {
27083b00736SRichard Henderson     float128 ret = float128_mul(make_float128(ah, al),
27183b00736SRichard Henderson                                 make_float128(bh, bl),
27283b00736SRichard Henderson                                 &env->fpu_status);
27383b00736SRichard Henderson     handle_exceptions(env, GETPC());
27483b00736SRichard Henderson     return RET128(ret);
27583b00736SRichard Henderson }
27683b00736SRichard Henderson 
27783b00736SRichard Henderson /* 128/64-bit FP multiplication */
27883b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
27983b00736SRichard Henderson                       uint64_t f2)
28083b00736SRichard Henderson {
28183b00736SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
28283b00736SRichard Henderson     ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
28383b00736SRichard Henderson     handle_exceptions(env, GETPC());
28483b00736SRichard Henderson     return RET128(ret);
285e72ca652SBlue Swirl }
286e72ca652SBlue Swirl 
287e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */
288587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
289e72ca652SBlue Swirl {
290587626f8SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
291587626f8SRichard Henderson     handle_exceptions(env, GETPC());
292d0cfecb5SRichard Henderson     return ret;
293e72ca652SBlue Swirl }
294e72ca652SBlue Swirl 
295e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */
296587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
297e72ca652SBlue Swirl {
298587626f8SRichard Henderson     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
299587626f8SRichard Henderson     handle_exceptions(env, GETPC());
300d0cfecb5SRichard Henderson     return ret;
301e72ca652SBlue Swirl }
302e72ca652SBlue Swirl 
303e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */
304587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
305e72ca652SBlue Swirl {
306587626f8SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
307587626f8SRichard Henderson     handle_exceptions(env, GETPC());
308d0cfecb5SRichard Henderson     return RET128(ret);
309587626f8SRichard Henderson }
310e72ca652SBlue Swirl 
311587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */
312587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
313587626f8SRichard Henderson {
314587626f8SRichard Henderson     float128 ret = float32_to_float128(f2, &env->fpu_status);
315587626f8SRichard Henderson     handle_exceptions(env, GETPC());
316d0cfecb5SRichard Henderson     return RET128(ret);
317e72ca652SBlue Swirl }
318e72ca652SBlue Swirl 
319e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */
320587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
321e72ca652SBlue Swirl {
322587626f8SRichard Henderson     float32 ret = float64_to_float32(f2, &env->fpu_status);
323587626f8SRichard Henderson     handle_exceptions(env, GETPC());
324d0cfecb5SRichard Henderson     return ret;
325e72ca652SBlue Swirl }
326e72ca652SBlue Swirl 
327e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */
328587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
329e72ca652SBlue Swirl {
330587626f8SRichard Henderson     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
331587626f8SRichard Henderson     handle_exceptions(env, GETPC());
332d0cfecb5SRichard Henderson     return ret;
333e72ca652SBlue Swirl }
334e72ca652SBlue Swirl 
335587626f8SRichard Henderson /* 32-bit FP compare */
336587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
337e72ca652SBlue Swirl {
338587626f8SRichard Henderson     int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
339587626f8SRichard Henderson     handle_exceptions(env, GETPC());
340587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
341e72ca652SBlue Swirl }
342e72ca652SBlue Swirl 
343587626f8SRichard Henderson /* 64-bit FP compare */
344587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
345e72ca652SBlue Swirl {
346587626f8SRichard Henderson     int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
347587626f8SRichard Henderson     handle_exceptions(env, GETPC());
348587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
349e72ca652SBlue Swirl }
350e72ca652SBlue Swirl 
351587626f8SRichard Henderson /* 128-bit FP compare */
352587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
353587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
354e72ca652SBlue Swirl {
355587626f8SRichard Henderson     int cmp = float128_compare_quiet(make_float128(ah, al),
356587626f8SRichard Henderson                                      make_float128(bh, bl),
357587626f8SRichard Henderson                                      &env->fpu_status);
358587626f8SRichard Henderson     handle_exceptions(env, GETPC());
359587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
360e72ca652SBlue Swirl }
361e72ca652SBlue Swirl 
36268c8bd93SRichard Henderson static int swap_round_mode(CPUS390XState *env, int m3)
363e72ca652SBlue Swirl {
36468c8bd93SRichard Henderson     int ret = env->fpu_status.float_rounding_mode;
365e72ca652SBlue Swirl     switch (m3) {
366e72ca652SBlue Swirl     case 0:
367e72ca652SBlue Swirl         /* current mode */
368e72ca652SBlue Swirl         break;
369e72ca652SBlue Swirl     case 1:
370e72ca652SBlue Swirl         /* biased round no nearest */
371e72ca652SBlue Swirl     case 4:
372e72ca652SBlue Swirl         /* round to nearest */
373e72ca652SBlue Swirl         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
374e72ca652SBlue Swirl         break;
375e72ca652SBlue Swirl     case 5:
376e72ca652SBlue Swirl         /* round to zero */
377e72ca652SBlue Swirl         set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
378e72ca652SBlue Swirl         break;
379e72ca652SBlue Swirl     case 6:
380e72ca652SBlue Swirl         /* round to +inf */
381e72ca652SBlue Swirl         set_float_rounding_mode(float_round_up, &env->fpu_status);
382e72ca652SBlue Swirl         break;
383e72ca652SBlue Swirl     case 7:
384e72ca652SBlue Swirl         /* round to -inf */
385e72ca652SBlue Swirl         set_float_rounding_mode(float_round_down, &env->fpu_status);
386e72ca652SBlue Swirl         break;
387e72ca652SBlue Swirl     }
38868c8bd93SRichard Henderson     return ret;
389e72ca652SBlue Swirl }
390e72ca652SBlue Swirl 
391683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */
392683bb9a8SRichard Henderson uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
393683bb9a8SRichard Henderson {
394683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
395683bb9a8SRichard Henderson     float32 ret = int64_to_float32(v2, &env->fpu_status);
396683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
397683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
398683bb9a8SRichard Henderson     return ret;
399683bb9a8SRichard Henderson }
400683bb9a8SRichard Henderson 
401683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */
402683bb9a8SRichard Henderson uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
403683bb9a8SRichard Henderson {
404683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
405683bb9a8SRichard Henderson     float64 ret = int64_to_float64(v2, &env->fpu_status);
406683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
407683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
408683bb9a8SRichard Henderson     return ret;
409683bb9a8SRichard Henderson }
410683bb9a8SRichard Henderson 
411683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */
412683bb9a8SRichard Henderson uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
413683bb9a8SRichard Henderson {
414683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
415683bb9a8SRichard Henderson     float128 ret = int64_to_float128(v2, &env->fpu_status);
416683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
417683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
418683bb9a8SRichard Henderson     return RET128(ret);
419683bb9a8SRichard Henderson }
420683bb9a8SRichard Henderson 
4212112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */
4222112bf1bSRichard Henderson uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4232112bf1bSRichard Henderson {
4242112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
4252112bf1bSRichard Henderson     float32 ret = uint64_to_float32(v2, &env->fpu_status);
4262112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4272112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4282112bf1bSRichard Henderson     return ret;
4292112bf1bSRichard Henderson }
4302112bf1bSRichard Henderson 
4312112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */
4322112bf1bSRichard Henderson uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4332112bf1bSRichard Henderson {
4342112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
4352112bf1bSRichard Henderson     float64 ret = uint64_to_float64(v2, &env->fpu_status);
4362112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4372112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4382112bf1bSRichard Henderson     return ret;
4392112bf1bSRichard Henderson }
4402112bf1bSRichard Henderson 
4412112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */
4422112bf1bSRichard Henderson uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4432112bf1bSRichard Henderson {
4442112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
445d2d9feacSRichard Henderson     float128 ret = uint64_to_float128(v2, &env->fpu_status);
4462112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4472112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4482112bf1bSRichard Henderson     return RET128(ret);
4492112bf1bSRichard Henderson }
4502112bf1bSRichard Henderson 
451e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */
45268c8bd93SRichard Henderson uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
453e72ca652SBlue Swirl {
45468c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
45568c8bd93SRichard Henderson     int64_t ret = float32_to_int64(v2, &env->fpu_status);
45668c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
45768c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
45868c8bd93SRichard Henderson     return ret;
459e72ca652SBlue Swirl }
460e72ca652SBlue Swirl 
461e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */
46268c8bd93SRichard Henderson uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
463e72ca652SBlue Swirl {
46468c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
46568c8bd93SRichard Henderson     int64_t ret = float64_to_int64(v2, &env->fpu_status);
46668c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
46768c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
46868c8bd93SRichard Henderson     return ret;
469e72ca652SBlue Swirl }
470e72ca652SBlue Swirl 
471e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */
47268c8bd93SRichard Henderson uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
473e72ca652SBlue Swirl {
47468c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
47568c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
47668c8bd93SRichard Henderson     int64_t ret = float128_to_int64(v2, &env->fpu_status);
47768c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
47868c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
47968c8bd93SRichard Henderson     return ret;
480e72ca652SBlue Swirl }
481e72ca652SBlue Swirl 
482e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */
48368c8bd93SRichard Henderson uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
484e72ca652SBlue Swirl {
48568c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
48668c8bd93SRichard Henderson     int32_t ret = float32_to_int32(v2, &env->fpu_status);
48768c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
48868c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
48968c8bd93SRichard Henderson     return ret;
490e72ca652SBlue Swirl }
491e72ca652SBlue Swirl 
492e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */
49368c8bd93SRichard Henderson uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
494e72ca652SBlue Swirl {
49568c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
49668c8bd93SRichard Henderson     int32_t ret = float64_to_int32(v2, &env->fpu_status);
49768c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
49868c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
49968c8bd93SRichard Henderson     return ret;
500e72ca652SBlue Swirl }
501e72ca652SBlue Swirl 
502e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */
50368c8bd93SRichard Henderson uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
504e72ca652SBlue Swirl {
50568c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
50668c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
50768c8bd93SRichard Henderson     int32_t ret = float128_to_int32(v2, &env->fpu_status);
50868c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
50968c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
51068c8bd93SRichard Henderson     return ret;
511e72ca652SBlue Swirl }
512e72ca652SBlue Swirl 
5136ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */
5146ac1b45fSRichard Henderson uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5156ac1b45fSRichard Henderson {
5166ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5176ac1b45fSRichard Henderson     uint64_t ret;
5186ac1b45fSRichard Henderson     v2 = float32_to_float64(v2, &env->fpu_status);
5196ac1b45fSRichard Henderson     ret = float64_to_uint64(v2, &env->fpu_status);
5206ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5216ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5226ac1b45fSRichard Henderson     return ret;
5236ac1b45fSRichard Henderson }
5246ac1b45fSRichard Henderson 
5256ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */
5266ac1b45fSRichard Henderson uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5276ac1b45fSRichard Henderson {
5286ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5296ac1b45fSRichard Henderson     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
5306ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5316ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5326ac1b45fSRichard Henderson     return ret;
5336ac1b45fSRichard Henderson }
5346ac1b45fSRichard Henderson 
5356ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */
5366ac1b45fSRichard Henderson uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
5376ac1b45fSRichard Henderson {
5386ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5393af471f9SDavid Hildenbrand     uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
5406ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5416ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5426ac1b45fSRichard Henderson     return ret;
5436ac1b45fSRichard Henderson }
5446ac1b45fSRichard Henderson 
5456ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */
5466ac1b45fSRichard Henderson uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5476ac1b45fSRichard Henderson {
5486ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5496ac1b45fSRichard Henderson     uint32_t ret = float32_to_uint32(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 
5556ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */
5566ac1b45fSRichard Henderson uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5576ac1b45fSRichard Henderson {
5586ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5596ac1b45fSRichard Henderson     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
5606ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5616ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5626ac1b45fSRichard Henderson     return ret;
5636ac1b45fSRichard Henderson }
5646ac1b45fSRichard Henderson 
5656ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */
5666ac1b45fSRichard Henderson uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
5676ac1b45fSRichard Henderson {
5686ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5693af471f9SDavid Hildenbrand     uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
5706ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5716ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5726ac1b45fSRichard Henderson     return ret;
5736ac1b45fSRichard Henderson }
5746ac1b45fSRichard Henderson 
575ed0bceceSAurelien Jarno /* round to integer 32-bit */
576ed0bceceSAurelien Jarno uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
577ed0bceceSAurelien Jarno {
578ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
579ed0bceceSAurelien Jarno     float32 ret = float32_round_to_int(f2, &env->fpu_status);
580ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
581ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
582ed0bceceSAurelien Jarno     return ret;
583ed0bceceSAurelien Jarno }
584ed0bceceSAurelien Jarno 
585ed0bceceSAurelien Jarno /* round to integer 64-bit */
586ed0bceceSAurelien Jarno uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
587ed0bceceSAurelien Jarno {
588ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
589ed0bceceSAurelien Jarno     float64 ret = float64_round_to_int(f2, &env->fpu_status);
590ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
591ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
592ed0bceceSAurelien Jarno     return ret;
593ed0bceceSAurelien Jarno }
594ed0bceceSAurelien Jarno 
595ed0bceceSAurelien Jarno /* round to integer 128-bit */
596ed0bceceSAurelien Jarno uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
597ed0bceceSAurelien Jarno {
598ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
599ed0bceceSAurelien Jarno     float128 ret = float128_round_to_int(make_float128(ah, al),
600ed0bceceSAurelien Jarno                                          &env->fpu_status);
601ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
602ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
603ed0bceceSAurelien Jarno     return RET128(ret);
604ed0bceceSAurelien Jarno }
605ed0bceceSAurelien Jarno 
6069c8be598SAurelien Jarno /* 32-bit FP compare and signal */
6079c8be598SAurelien Jarno uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
6089c8be598SAurelien Jarno {
6099c8be598SAurelien Jarno     int cmp = float32_compare(f1, f2, &env->fpu_status);
6109c8be598SAurelien Jarno     handle_exceptions(env, GETPC());
6119c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
6129c8be598SAurelien Jarno }
6139c8be598SAurelien Jarno 
6149c8be598SAurelien Jarno /* 64-bit FP compare and signal */
6159c8be598SAurelien Jarno uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
6169c8be598SAurelien Jarno {
6179c8be598SAurelien Jarno     int cmp = float64_compare(f1, f2, &env->fpu_status);
6189c8be598SAurelien Jarno     handle_exceptions(env, GETPC());
6199c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
6209c8be598SAurelien Jarno }
6219c8be598SAurelien Jarno 
6229c8be598SAurelien Jarno /* 128-bit FP compare and signal */
6239c8be598SAurelien Jarno uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
6249c8be598SAurelien Jarno                      uint64_t bh, uint64_t bl)
6259c8be598SAurelien Jarno {
6269c8be598SAurelien Jarno     int cmp = float128_compare(make_float128(ah, al),
6279c8be598SAurelien Jarno                                make_float128(bh, bl),
6289c8be598SAurelien Jarno                                &env->fpu_status);
6299c8be598SAurelien Jarno     handle_exceptions(env, GETPC());
6309c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
6319c8be598SAurelien Jarno }
6329c8be598SAurelien Jarno 
633722bfec3SRichard Henderson /* 32-bit FP multiply and add */
634722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
635722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
636e72ca652SBlue Swirl {
637722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
638722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
639722bfec3SRichard Henderson     return ret;
640722bfec3SRichard Henderson }
641e72ca652SBlue Swirl 
642722bfec3SRichard Henderson /* 64-bit FP multiply and add */
643722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
644722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
645722bfec3SRichard Henderson {
646722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
647722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
648722bfec3SRichard Henderson     return ret;
649722bfec3SRichard Henderson }
650722bfec3SRichard Henderson 
651722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */
652722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
653722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
654722bfec3SRichard Henderson {
655722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
656e72ca652SBlue Swirl                                  &env->fpu_status);
657722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
658722bfec3SRichard Henderson     return ret;
659e72ca652SBlue Swirl }
660e72ca652SBlue Swirl 
661722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */
662722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
663722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
664e72ca652SBlue Swirl {
665722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
666e72ca652SBlue Swirl                                  &env->fpu_status);
667722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
668722bfec3SRichard Henderson     return ret;
669e72ca652SBlue Swirl }
670e72ca652SBlue Swirl 
671fc7cc951SDavid Hildenbrand /* The rightmost bit has the number 11. */
672fc7cc951SDavid Hildenbrand static inline uint16_t dcmask(int bit, bool neg)
673fc7cc951SDavid Hildenbrand {
674fc7cc951SDavid Hildenbrand     return 1 << (11 - bit - neg);
675fc7cc951SDavid Hildenbrand }
676fc7cc951SDavid Hildenbrand 
677fc7cc951SDavid Hildenbrand #define DEF_FLOAT_DCMASK(_TYPE) \
678fc7cc951SDavid Hildenbrand static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1)       \
679fc7cc951SDavid Hildenbrand {                                                                  \
680fc7cc951SDavid Hildenbrand     const bool neg = _TYPE##_is_neg(f1);                           \
681fc7cc951SDavid Hildenbrand                                                                    \
682fc7cc951SDavid Hildenbrand     /* Sorted by most common cases - only one class is possible */ \
683fc7cc951SDavid Hildenbrand     if (_TYPE##_is_normal(f1)) {                                   \
684fc7cc951SDavid Hildenbrand         return dcmask(2, neg);                                     \
685fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_zero(f1)) {                              \
686fc7cc951SDavid Hildenbrand         return dcmask(0, neg);                                     \
687fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_denormal(f1)) {                          \
688fc7cc951SDavid Hildenbrand         return dcmask(4, neg);                                     \
689fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_infinity(f1)) {                          \
690fc7cc951SDavid Hildenbrand         return dcmask(6, neg);                                     \
691fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) {       \
692fc7cc951SDavid Hildenbrand         return dcmask(8, neg);                                     \
693fc7cc951SDavid Hildenbrand     }                                                              \
694fc7cc951SDavid Hildenbrand     /* signaling nan, as last remaining case */                    \
695fc7cc951SDavid Hildenbrand     return dcmask(10, neg);                                        \
696fc7cc951SDavid Hildenbrand }
697fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float32)
698fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float64)
699fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float128)
700fc7cc951SDavid Hildenbrand 
701e72ca652SBlue Swirl /* test data class 32-bit */
702af39bc8cSAleksandar Markovic uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
703e72ca652SBlue Swirl {
704fc7cc951SDavid Hildenbrand     return (m2 & float32_dcmask(env, f1)) != 0;
705e72ca652SBlue Swirl }
706e72ca652SBlue Swirl 
707e72ca652SBlue Swirl /* test data class 64-bit */
708af39bc8cSAleksandar Markovic uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
709e72ca652SBlue Swirl {
710fc7cc951SDavid Hildenbrand     return (m2 & float64_dcmask(env, v1)) != 0;
711e72ca652SBlue Swirl }
712e72ca652SBlue Swirl 
713e72ca652SBlue Swirl /* test data class 128-bit */
714fc7cc951SDavid Hildenbrand uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
715e72ca652SBlue Swirl {
716fc7cc951SDavid Hildenbrand     return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0;
717e72ca652SBlue Swirl }
718e72ca652SBlue Swirl 
71916d7b2a4SRichard Henderson /* square root 32-bit */
72016d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
721e72ca652SBlue Swirl {
72216d7b2a4SRichard Henderson     float32 ret = float32_sqrt(f2, &env->fpu_status);
72316d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
72416d7b2a4SRichard Henderson     return ret;
72516d7b2a4SRichard Henderson }
72616d7b2a4SRichard Henderson 
72716d7b2a4SRichard Henderson /* square root 64-bit */
72816d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
72916d7b2a4SRichard Henderson {
73016d7b2a4SRichard Henderson     float64 ret = float64_sqrt(f2, &env->fpu_status);
73116d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
73216d7b2a4SRichard Henderson     return ret;
73316d7b2a4SRichard Henderson }
73416d7b2a4SRichard Henderson 
73516d7b2a4SRichard Henderson /* square root 128-bit */
73616d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
73716d7b2a4SRichard Henderson {
73816d7b2a4SRichard Henderson     float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
73916d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
74016d7b2a4SRichard Henderson     return RET128(ret);
741e72ca652SBlue Swirl }
7428379bfdbSRichard Henderson 
743411edc22SRichard Henderson static const int fpc_to_rnd[4] = {
7448379bfdbSRichard Henderson     float_round_nearest_even,
7458379bfdbSRichard Henderson     float_round_to_zero,
7468379bfdbSRichard Henderson     float_round_up,
7478379bfdbSRichard Henderson     float_round_down
7488379bfdbSRichard Henderson };
7498379bfdbSRichard Henderson 
750411edc22SRichard Henderson /* set fpc */
751411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
752411edc22SRichard Henderson {
7538379bfdbSRichard Henderson     /* Install everything in the main FPC.  */
7548379bfdbSRichard Henderson     env->fpc = fpc;
7558379bfdbSRichard Henderson 
7568379bfdbSRichard Henderson     /* Install the rounding mode in the shadow fpu_status.  */
757411edc22SRichard Henderson     set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
758411edc22SRichard Henderson }
759411edc22SRichard Henderson 
760411edc22SRichard Henderson /* set fpc and signal */
761411edc22SRichard Henderson void HELPER(sfas)(CPUS390XState *env, uint64_t val)
762411edc22SRichard Henderson {
763411edc22SRichard Henderson     uint32_t signalling = env->fpc;
764411edc22SRichard Henderson     uint32_t source = val;
765411edc22SRichard Henderson     uint32_t s390_exc;
766411edc22SRichard Henderson 
767411edc22SRichard Henderson     /* The contents of the source operand are placed in the FPC register;
768411edc22SRichard Henderson        then the flags in the FPC register are set to the logical OR of the
769411edc22SRichard Henderson        signalling flags and the source flags.  */
770411edc22SRichard Henderson     env->fpc = source | (signalling & 0x00ff0000);
771411edc22SRichard Henderson     set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
772411edc22SRichard Henderson 
773411edc22SRichard Henderson     /* If any signalling flag is 1 and the corresponding source mask
774411edc22SRichard Henderson        is also 1, a simulated-iee-exception trap occurs.  */
775411edc22SRichard Henderson     s390_exc = (signalling >> 16) & (source >> 24);
776411edc22SRichard Henderson     if (s390_exc) {
777bbf6ea3bSDavid Hildenbrand         tcg_s390_data_exception(env, s390_exc | 3, GETPC());
778411edc22SRichard Henderson     }
7798379bfdbSRichard Henderson }
780