xref: /qemu/target/s390x/tcg/fpu_helper.c (revision 8772bbe4e7cc7d67792440b0e7ea819e3cc930db)
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 
66fcb9e9f2SDavid Hildenbrand     /*
676d6ad1d1SDavid Hildenbrand      * IEEE-Underflow exception recognition exists if a tininess condition
686d6ad1d1SDavid Hildenbrand      * (underflow) exists and
696d6ad1d1SDavid Hildenbrand      * - The mask bit in the FPC is zero and the result is inexact
706d6ad1d1SDavid Hildenbrand      * - The mask bit in the FPC is one
716d6ad1d1SDavid Hildenbrand      * So tininess conditions that are not inexact don't trigger any
726d6ad1d1SDavid Hildenbrand      * underflow action in case the mask bit is not one.
736d6ad1d1SDavid Hildenbrand      */
746d6ad1d1SDavid Hildenbrand     if (!(s390_exc & S390_IEEE_MASK_INEXACT) &&
756d6ad1d1SDavid Hildenbrand         !((env->fpc >> 24) & S390_IEEE_MASK_UNDERFLOW)) {
766d6ad1d1SDavid Hildenbrand         s390_exc &= ~S390_IEEE_MASK_UNDERFLOW;
776d6ad1d1SDavid Hildenbrand     }
786d6ad1d1SDavid Hildenbrand 
796d6ad1d1SDavid Hildenbrand     /*
80fcb9e9f2SDavid Hildenbrand      * FIXME:
81fcb9e9f2SDavid Hildenbrand      * 1. Right now, all inexact conditions are inidicated as
82fcb9e9f2SDavid Hildenbrand      *    "truncated" (0) and never as "incremented" (1) in the DXC.
83fcb9e9f2SDavid Hildenbrand      * 2. Only traps due to invalid/divbyzero are suppressing. Other traps
84fcb9e9f2SDavid Hildenbrand      *    are completing, meaning the target register has to be written!
85fcb9e9f2SDavid Hildenbrand      *    This, however will mean that we have to write the register before
86fcb9e9f2SDavid Hildenbrand      *    triggering the trap - impossible right now.
87fcb9e9f2SDavid Hildenbrand      */
88587626f8SRichard Henderson 
89fcb9e9f2SDavid Hildenbrand     /*
90fcb9e9f2SDavid Hildenbrand      * invalid/divbyzero cannot coexist with other conditions.
91fcb9e9f2SDavid Hildenbrand      * overflow/underflow however can coexist with inexact, we have to
92fcb9e9f2SDavid Hildenbrand      * handle it separatly.
93fcb9e9f2SDavid Hildenbrand      */
94fcb9e9f2SDavid Hildenbrand     if (s390_exc & ~S390_IEEE_MASK_INEXACT) {
95fcb9e9f2SDavid Hildenbrand         if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
96fcb9e9f2SDavid Hildenbrand             /* trap condition - inexact reported along */
97bbf6ea3bSDavid Hildenbrand             tcg_s390_data_exception(env, s390_exc, retaddr);
98587626f8SRichard Henderson         }
99fcb9e9f2SDavid Hildenbrand         /* nontrap condition - inexact handled differently */
100fcb9e9f2SDavid Hildenbrand         env->fpc |= (s390_exc & ~S390_IEEE_MASK_INEXACT) << 16;
101fcb9e9f2SDavid Hildenbrand     }
102fcb9e9f2SDavid Hildenbrand 
103fcb9e9f2SDavid Hildenbrand     /* inexact handling */
104fcb9e9f2SDavid Hildenbrand     if (s390_exc & S390_IEEE_MASK_INEXACT) {
105fcb9e9f2SDavid Hildenbrand         /* trap condition - overflow/underflow _not_ reported along */
106fcb9e9f2SDavid Hildenbrand         if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
107fcb9e9f2SDavid Hildenbrand             tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT,
108fcb9e9f2SDavid Hildenbrand                                     retaddr);
109fcb9e9f2SDavid Hildenbrand         }
110fcb9e9f2SDavid Hildenbrand         /* nontrap condition */
111fcb9e9f2SDavid Hildenbrand         env->fpc |= (s390_exc & S390_IEEE_MASK_INEXACT) << 16;
112fcb9e9f2SDavid Hildenbrand     }
113587626f8SRichard Henderson }
114587626f8SRichard Henderson 
115449c0d70SBlue Swirl static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
116e72ca652SBlue Swirl {
117a47dddd7SAndreas Färber     S390CPU *cpu = s390_env_get_cpu(env);
118a47dddd7SAndreas Färber 
119e72ca652SBlue Swirl     switch (float_compare) {
120e72ca652SBlue Swirl     case float_relation_equal:
121e72ca652SBlue Swirl         return 0;
122e72ca652SBlue Swirl     case float_relation_less:
123e72ca652SBlue Swirl         return 1;
124e72ca652SBlue Swirl     case float_relation_greater:
125e72ca652SBlue Swirl         return 2;
126e72ca652SBlue Swirl     case float_relation_unordered:
127e72ca652SBlue Swirl         return 3;
128e72ca652SBlue Swirl     default:
129a47dddd7SAndreas Färber         cpu_abort(CPU(cpu), "unknown return value for float compare\n");
130e72ca652SBlue Swirl     }
131e72ca652SBlue Swirl }
132e72ca652SBlue Swirl 
133e72ca652SBlue Swirl /* condition codes for unary FP ops */
134e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v)
135e72ca652SBlue Swirl {
136e72ca652SBlue Swirl     if (float32_is_any_nan(v)) {
137e72ca652SBlue Swirl         return 3;
138e72ca652SBlue Swirl     } else if (float32_is_zero(v)) {
139e72ca652SBlue Swirl         return 0;
140e72ca652SBlue Swirl     } else if (float32_is_neg(v)) {
141e72ca652SBlue Swirl         return 1;
142e72ca652SBlue Swirl     } else {
143e72ca652SBlue Swirl         return 2;
144e72ca652SBlue Swirl     }
145e72ca652SBlue Swirl }
146e72ca652SBlue Swirl 
147e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v)
148e72ca652SBlue Swirl {
149e72ca652SBlue Swirl     if (float64_is_any_nan(v)) {
150e72ca652SBlue Swirl         return 3;
151e72ca652SBlue Swirl     } else if (float64_is_zero(v)) {
152e72ca652SBlue Swirl         return 0;
153e72ca652SBlue Swirl     } else if (float64_is_neg(v)) {
154e72ca652SBlue Swirl         return 1;
155e72ca652SBlue Swirl     } else {
156e72ca652SBlue Swirl         return 2;
157e72ca652SBlue Swirl     }
158e72ca652SBlue Swirl }
159e72ca652SBlue Swirl 
160587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v)
161e72ca652SBlue Swirl {
162e72ca652SBlue Swirl     if (float128_is_any_nan(v)) {
163e72ca652SBlue Swirl         return 3;
164e72ca652SBlue Swirl     } else if (float128_is_zero(v)) {
165e72ca652SBlue Swirl         return 0;
166e72ca652SBlue Swirl     } else if (float128_is_neg(v)) {
167e72ca652SBlue Swirl         return 1;
168e72ca652SBlue Swirl     } else {
169e72ca652SBlue Swirl         return 2;
170e72ca652SBlue Swirl     }
171e72ca652SBlue Swirl }
172e72ca652SBlue Swirl 
173587626f8SRichard Henderson /* 32-bit FP addition */
174587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
175e72ca652SBlue Swirl {
176587626f8SRichard Henderson     float32 ret = float32_add(f1, f2, &env->fpu_status);
177587626f8SRichard Henderson     handle_exceptions(env, GETPC());
178587626f8SRichard Henderson     return ret;
179e72ca652SBlue Swirl }
180e72ca652SBlue Swirl 
181587626f8SRichard Henderson /* 64-bit FP addition */
182587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
183e72ca652SBlue Swirl {
184587626f8SRichard Henderson     float64 ret = float64_add(f1, f2, &env->fpu_status);
185587626f8SRichard Henderson     handle_exceptions(env, GETPC());
186587626f8SRichard Henderson     return ret;
187587626f8SRichard Henderson }
188e72ca652SBlue Swirl 
189587626f8SRichard Henderson /* 128-bit FP addition */
190587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
191587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
192587626f8SRichard Henderson {
193587626f8SRichard Henderson     float128 ret = float128_add(make_float128(ah, al),
194587626f8SRichard Henderson                                 make_float128(bh, bl),
195587626f8SRichard Henderson                                 &env->fpu_status);
196587626f8SRichard Henderson     handle_exceptions(env, GETPC());
197587626f8SRichard Henderson     return RET128(ret);
198e72ca652SBlue Swirl }
199e72ca652SBlue Swirl 
2001a800a2dSRichard Henderson /* 32-bit FP subtraction */
2011a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
202e72ca652SBlue Swirl {
2031a800a2dSRichard Henderson     float32 ret = float32_sub(f1, f2, &env->fpu_status);
2041a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
2051a800a2dSRichard Henderson     return ret;
206e72ca652SBlue Swirl }
207e72ca652SBlue Swirl 
2081a800a2dSRichard Henderson /* 64-bit FP subtraction */
2091a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
210e72ca652SBlue Swirl {
2111a800a2dSRichard Henderson     float64 ret = float64_sub(f1, f2, &env->fpu_status);
2121a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
2131a800a2dSRichard Henderson     return ret;
2141a800a2dSRichard Henderson }
215e72ca652SBlue Swirl 
2161a800a2dSRichard Henderson /* 128-bit FP subtraction */
2171a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
2181a800a2dSRichard Henderson                      uint64_t bh, uint64_t bl)
2191a800a2dSRichard Henderson {
2201a800a2dSRichard Henderson     float128 ret = float128_sub(make_float128(ah, al),
2211a800a2dSRichard Henderson                                 make_float128(bh, bl),
2221a800a2dSRichard Henderson                                 &env->fpu_status);
2231a800a2dSRichard Henderson     handle_exceptions(env, GETPC());
2241a800a2dSRichard Henderson     return RET128(ret);
225e72ca652SBlue Swirl }
226e72ca652SBlue Swirl 
227f08a5c31SRichard Henderson /* 32-bit FP division */
228f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
229e72ca652SBlue Swirl {
230f08a5c31SRichard Henderson     float32 ret = float32_div(f1, f2, &env->fpu_status);
231f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
232f08a5c31SRichard Henderson     return ret;
233e72ca652SBlue Swirl }
234e72ca652SBlue Swirl 
235f08a5c31SRichard Henderson /* 64-bit FP division */
236f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
237e72ca652SBlue Swirl {
238f08a5c31SRichard Henderson     float64 ret = float64_div(f1, f2, &env->fpu_status);
239f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
240f08a5c31SRichard Henderson     return ret;
241f08a5c31SRichard Henderson }
242e72ca652SBlue Swirl 
243f08a5c31SRichard Henderson /* 128-bit FP division */
244f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
245f08a5c31SRichard Henderson                      uint64_t bh, uint64_t bl)
246f08a5c31SRichard Henderson {
247f08a5c31SRichard Henderson     float128 ret = float128_div(make_float128(ah, al),
248f08a5c31SRichard Henderson                                 make_float128(bh, bl),
249f08a5c31SRichard Henderson                                 &env->fpu_status);
250f08a5c31SRichard Henderson     handle_exceptions(env, GETPC());
251f08a5c31SRichard Henderson     return RET128(ret);
252e72ca652SBlue Swirl }
253e72ca652SBlue Swirl 
25483b00736SRichard Henderson /* 32-bit FP multiplication */
25583b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
256e72ca652SBlue Swirl {
25783b00736SRichard Henderson     float32 ret = float32_mul(f1, f2, &env->fpu_status);
25883b00736SRichard Henderson     handle_exceptions(env, GETPC());
25983b00736SRichard Henderson     return ret;
260e72ca652SBlue Swirl }
261e72ca652SBlue Swirl 
26283b00736SRichard Henderson /* 64-bit FP multiplication */
26383b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
264e72ca652SBlue Swirl {
26583b00736SRichard Henderson     float64 ret = float64_mul(f1, f2, &env->fpu_status);
26683b00736SRichard Henderson     handle_exceptions(env, GETPC());
26783b00736SRichard Henderson     return ret;
26883b00736SRichard Henderson }
269e72ca652SBlue Swirl 
27083b00736SRichard Henderson /* 64/32-bit FP multiplication */
27183b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
27283b00736SRichard Henderson {
27383b00736SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
27483b00736SRichard Henderson     ret = float64_mul(f1, ret, &env->fpu_status);
27583b00736SRichard Henderson     handle_exceptions(env, GETPC());
27683b00736SRichard Henderson     return ret;
27783b00736SRichard Henderson }
27883b00736SRichard Henderson 
27983b00736SRichard Henderson /* 128-bit FP multiplication */
28083b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
28183b00736SRichard Henderson                      uint64_t bh, uint64_t bl)
28283b00736SRichard Henderson {
28383b00736SRichard Henderson     float128 ret = float128_mul(make_float128(ah, al),
28483b00736SRichard Henderson                                 make_float128(bh, bl),
28583b00736SRichard Henderson                                 &env->fpu_status);
28683b00736SRichard Henderson     handle_exceptions(env, GETPC());
28783b00736SRichard Henderson     return RET128(ret);
28883b00736SRichard Henderson }
28983b00736SRichard Henderson 
29083b00736SRichard Henderson /* 128/64-bit FP multiplication */
29183b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
29283b00736SRichard Henderson                       uint64_t f2)
29383b00736SRichard Henderson {
29483b00736SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
29583b00736SRichard Henderson     ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
29683b00736SRichard Henderson     handle_exceptions(env, GETPC());
29783b00736SRichard Henderson     return RET128(ret);
298e72ca652SBlue Swirl }
299e72ca652SBlue Swirl 
300e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */
301587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
302e72ca652SBlue Swirl {
303587626f8SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
304587626f8SRichard Henderson     handle_exceptions(env, GETPC());
305d0cfecb5SRichard Henderson     return ret;
306e72ca652SBlue Swirl }
307e72ca652SBlue Swirl 
308e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */
309587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
310e72ca652SBlue Swirl {
311587626f8SRichard Henderson     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
312587626f8SRichard Henderson     handle_exceptions(env, GETPC());
313d0cfecb5SRichard Henderson     return ret;
314e72ca652SBlue Swirl }
315e72ca652SBlue Swirl 
316e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */
317587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
318e72ca652SBlue Swirl {
319587626f8SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
320587626f8SRichard Henderson     handle_exceptions(env, GETPC());
321d0cfecb5SRichard Henderson     return RET128(ret);
322587626f8SRichard Henderson }
323e72ca652SBlue Swirl 
324587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */
325587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
326587626f8SRichard Henderson {
327587626f8SRichard Henderson     float128 ret = float32_to_float128(f2, &env->fpu_status);
328587626f8SRichard Henderson     handle_exceptions(env, GETPC());
329d0cfecb5SRichard Henderson     return RET128(ret);
330e72ca652SBlue Swirl }
331e72ca652SBlue Swirl 
332e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */
333587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
334e72ca652SBlue Swirl {
335587626f8SRichard Henderson     float32 ret = float64_to_float32(f2, &env->fpu_status);
336587626f8SRichard Henderson     handle_exceptions(env, GETPC());
337d0cfecb5SRichard Henderson     return ret;
338e72ca652SBlue Swirl }
339e72ca652SBlue Swirl 
340e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */
341587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
342e72ca652SBlue Swirl {
343587626f8SRichard Henderson     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
344587626f8SRichard Henderson     handle_exceptions(env, GETPC());
345d0cfecb5SRichard Henderson     return ret;
346e72ca652SBlue Swirl }
347e72ca652SBlue Swirl 
348587626f8SRichard Henderson /* 32-bit FP compare */
349587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
350e72ca652SBlue Swirl {
351587626f8SRichard Henderson     int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
352587626f8SRichard Henderson     handle_exceptions(env, GETPC());
353587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
354e72ca652SBlue Swirl }
355e72ca652SBlue Swirl 
356587626f8SRichard Henderson /* 64-bit FP compare */
357587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
358e72ca652SBlue Swirl {
359587626f8SRichard Henderson     int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
360587626f8SRichard Henderson     handle_exceptions(env, GETPC());
361587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
362e72ca652SBlue Swirl }
363e72ca652SBlue Swirl 
364587626f8SRichard Henderson /* 128-bit FP compare */
365587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
366587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
367e72ca652SBlue Swirl {
368587626f8SRichard Henderson     int cmp = float128_compare_quiet(make_float128(ah, al),
369587626f8SRichard Henderson                                      make_float128(bh, bl),
370587626f8SRichard Henderson                                      &env->fpu_status);
371587626f8SRichard Henderson     handle_exceptions(env, GETPC());
372587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
373e72ca652SBlue Swirl }
374e72ca652SBlue Swirl 
37568c8bd93SRichard Henderson static int swap_round_mode(CPUS390XState *env, int m3)
376e72ca652SBlue Swirl {
37768c8bd93SRichard Henderson     int ret = env->fpu_status.float_rounding_mode;
378e72ca652SBlue Swirl     switch (m3) {
379e72ca652SBlue Swirl     case 0:
380e72ca652SBlue Swirl         /* current mode */
381e72ca652SBlue Swirl         break;
382e72ca652SBlue Swirl     case 1:
383e72ca652SBlue Swirl         /* biased round no nearest */
384e72ca652SBlue Swirl     case 4:
385e72ca652SBlue Swirl         /* round to nearest */
386e72ca652SBlue Swirl         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
387e72ca652SBlue Swirl         break;
388e72ca652SBlue Swirl     case 5:
389e72ca652SBlue Swirl         /* round to zero */
390e72ca652SBlue Swirl         set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
391e72ca652SBlue Swirl         break;
392e72ca652SBlue Swirl     case 6:
393e72ca652SBlue Swirl         /* round to +inf */
394e72ca652SBlue Swirl         set_float_rounding_mode(float_round_up, &env->fpu_status);
395e72ca652SBlue Swirl         break;
396e72ca652SBlue Swirl     case 7:
397e72ca652SBlue Swirl         /* round to -inf */
398e72ca652SBlue Swirl         set_float_rounding_mode(float_round_down, &env->fpu_status);
399e72ca652SBlue Swirl         break;
400e72ca652SBlue Swirl     }
40168c8bd93SRichard Henderson     return ret;
402e72ca652SBlue Swirl }
403e72ca652SBlue Swirl 
404683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */
405683bb9a8SRichard Henderson uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
406683bb9a8SRichard Henderson {
407683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
408683bb9a8SRichard Henderson     float32 ret = int64_to_float32(v2, &env->fpu_status);
409683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
410683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
411683bb9a8SRichard Henderson     return ret;
412683bb9a8SRichard Henderson }
413683bb9a8SRichard Henderson 
414683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */
415683bb9a8SRichard Henderson uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
416683bb9a8SRichard Henderson {
417683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
418683bb9a8SRichard Henderson     float64 ret = int64_to_float64(v2, &env->fpu_status);
419683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
420683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
421683bb9a8SRichard Henderson     return ret;
422683bb9a8SRichard Henderson }
423683bb9a8SRichard Henderson 
424683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */
425683bb9a8SRichard Henderson uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
426683bb9a8SRichard Henderson {
427683bb9a8SRichard Henderson     int hold = swap_round_mode(env, m3);
428683bb9a8SRichard Henderson     float128 ret = int64_to_float128(v2, &env->fpu_status);
429683bb9a8SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
430683bb9a8SRichard Henderson     handle_exceptions(env, GETPC());
431683bb9a8SRichard Henderson     return RET128(ret);
432683bb9a8SRichard Henderson }
433683bb9a8SRichard Henderson 
4342112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */
4352112bf1bSRichard Henderson uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4362112bf1bSRichard Henderson {
4372112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
4382112bf1bSRichard Henderson     float32 ret = uint64_to_float32(v2, &env->fpu_status);
4392112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4402112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4412112bf1bSRichard Henderson     return ret;
4422112bf1bSRichard Henderson }
4432112bf1bSRichard Henderson 
4442112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */
4452112bf1bSRichard Henderson uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4462112bf1bSRichard Henderson {
4472112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
4482112bf1bSRichard Henderson     float64 ret = uint64_to_float64(v2, &env->fpu_status);
4492112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4502112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4512112bf1bSRichard Henderson     return ret;
4522112bf1bSRichard Henderson }
4532112bf1bSRichard Henderson 
4542112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */
4552112bf1bSRichard Henderson uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
4562112bf1bSRichard Henderson {
4572112bf1bSRichard Henderson     int hold = swap_round_mode(env, m3);
458d2d9feacSRichard Henderson     float128 ret = uint64_to_float128(v2, &env->fpu_status);
4592112bf1bSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
4602112bf1bSRichard Henderson     handle_exceptions(env, GETPC());
4612112bf1bSRichard Henderson     return RET128(ret);
4622112bf1bSRichard Henderson }
4632112bf1bSRichard Henderson 
464e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */
46568c8bd93SRichard Henderson uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
466e72ca652SBlue Swirl {
46768c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
46868c8bd93SRichard Henderson     int64_t ret = float32_to_int64(v2, &env->fpu_status);
46968c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
47068c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
47168c8bd93SRichard Henderson     return ret;
472e72ca652SBlue Swirl }
473e72ca652SBlue Swirl 
474e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */
47568c8bd93SRichard Henderson uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
476e72ca652SBlue Swirl {
47768c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
47868c8bd93SRichard Henderson     int64_t ret = float64_to_int64(v2, &env->fpu_status);
47968c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
48068c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
48168c8bd93SRichard Henderson     return ret;
482e72ca652SBlue Swirl }
483e72ca652SBlue Swirl 
484e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */
48568c8bd93SRichard Henderson uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
486e72ca652SBlue Swirl {
48768c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
48868c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
48968c8bd93SRichard Henderson     int64_t ret = float128_to_int64(v2, &env->fpu_status);
49068c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
49168c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
49268c8bd93SRichard Henderson     return ret;
493e72ca652SBlue Swirl }
494e72ca652SBlue Swirl 
495e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */
49668c8bd93SRichard Henderson uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
497e72ca652SBlue Swirl {
49868c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
49968c8bd93SRichard Henderson     int32_t ret = float32_to_int32(v2, &env->fpu_status);
50068c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
50168c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
50268c8bd93SRichard Henderson     return ret;
503e72ca652SBlue Swirl }
504e72ca652SBlue Swirl 
505e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */
50668c8bd93SRichard Henderson uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
507e72ca652SBlue Swirl {
50868c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
50968c8bd93SRichard Henderson     int32_t ret = float64_to_int32(v2, &env->fpu_status);
51068c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
51168c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
51268c8bd93SRichard Henderson     return ret;
513e72ca652SBlue Swirl }
514e72ca652SBlue Swirl 
515e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */
51668c8bd93SRichard Henderson uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
517e72ca652SBlue Swirl {
51868c8bd93SRichard Henderson     int hold = swap_round_mode(env, m3);
51968c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
52068c8bd93SRichard Henderson     int32_t ret = float128_to_int32(v2, &env->fpu_status);
52168c8bd93SRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
52268c8bd93SRichard Henderson     handle_exceptions(env, GETPC());
52368c8bd93SRichard Henderson     return ret;
524e72ca652SBlue Swirl }
525e72ca652SBlue Swirl 
5266ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */
5276ac1b45fSRichard Henderson uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5286ac1b45fSRichard Henderson {
5296ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5306ac1b45fSRichard Henderson     uint64_t ret;
5316ac1b45fSRichard Henderson     v2 = float32_to_float64(v2, &env->fpu_status);
5326ac1b45fSRichard Henderson     ret = float64_to_uint64(v2, &env->fpu_status);
5336ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5346ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5356ac1b45fSRichard Henderson     return ret;
5366ac1b45fSRichard Henderson }
5376ac1b45fSRichard Henderson 
5386ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */
5396ac1b45fSRichard Henderson uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5406ac1b45fSRichard Henderson {
5416ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5426ac1b45fSRichard Henderson     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
5436ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5446ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5456ac1b45fSRichard Henderson     return ret;
5466ac1b45fSRichard Henderson }
5476ac1b45fSRichard Henderson 
5486ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */
5496ac1b45fSRichard Henderson uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
5506ac1b45fSRichard Henderson {
5516ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5523af471f9SDavid Hildenbrand     uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status);
5536ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5546ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5556ac1b45fSRichard Henderson     return ret;
5566ac1b45fSRichard Henderson }
5576ac1b45fSRichard Henderson 
5586ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */
5596ac1b45fSRichard Henderson uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5606ac1b45fSRichard Henderson {
5616ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5626ac1b45fSRichard Henderson     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
5636ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5646ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5656ac1b45fSRichard Henderson     return ret;
5666ac1b45fSRichard Henderson }
5676ac1b45fSRichard Henderson 
5686ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */
5696ac1b45fSRichard Henderson uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
5706ac1b45fSRichard Henderson {
5716ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5726ac1b45fSRichard Henderson     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
5736ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5746ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5756ac1b45fSRichard Henderson     return ret;
5766ac1b45fSRichard Henderson }
5776ac1b45fSRichard Henderson 
5786ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */
5796ac1b45fSRichard Henderson uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
5806ac1b45fSRichard Henderson {
5816ac1b45fSRichard Henderson     int hold = swap_round_mode(env, m3);
5823af471f9SDavid Hildenbrand     uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status);
5836ac1b45fSRichard Henderson     set_float_rounding_mode(hold, &env->fpu_status);
5846ac1b45fSRichard Henderson     handle_exceptions(env, GETPC());
5856ac1b45fSRichard Henderson     return ret;
5866ac1b45fSRichard Henderson }
5876ac1b45fSRichard Henderson 
588ed0bceceSAurelien Jarno /* round to integer 32-bit */
589ed0bceceSAurelien Jarno uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
590ed0bceceSAurelien Jarno {
591ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
592ed0bceceSAurelien Jarno     float32 ret = float32_round_to_int(f2, &env->fpu_status);
593ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
594ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
595ed0bceceSAurelien Jarno     return ret;
596ed0bceceSAurelien Jarno }
597ed0bceceSAurelien Jarno 
598ed0bceceSAurelien Jarno /* round to integer 64-bit */
599ed0bceceSAurelien Jarno uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3)
600ed0bceceSAurelien Jarno {
601ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
602ed0bceceSAurelien Jarno     float64 ret = float64_round_to_int(f2, &env->fpu_status);
603ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
604ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
605ed0bceceSAurelien Jarno     return ret;
606ed0bceceSAurelien Jarno }
607ed0bceceSAurelien Jarno 
608ed0bceceSAurelien Jarno /* round to integer 128-bit */
609ed0bceceSAurelien Jarno uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3)
610ed0bceceSAurelien Jarno {
611ed0bceceSAurelien Jarno     int hold = swap_round_mode(env, m3);
612ed0bceceSAurelien Jarno     float128 ret = float128_round_to_int(make_float128(ah, al),
613ed0bceceSAurelien Jarno                                          &env->fpu_status);
614ed0bceceSAurelien Jarno     set_float_rounding_mode(hold, &env->fpu_status);
615ed0bceceSAurelien Jarno     handle_exceptions(env, GETPC());
616ed0bceceSAurelien Jarno     return RET128(ret);
617ed0bceceSAurelien Jarno }
618ed0bceceSAurelien Jarno 
6199c8be598SAurelien Jarno /* 32-bit FP compare and signal */
6209c8be598SAurelien Jarno uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
6219c8be598SAurelien Jarno {
6229c8be598SAurelien Jarno     int cmp = float32_compare(f1, f2, &env->fpu_status);
6239c8be598SAurelien Jarno     handle_exceptions(env, GETPC());
6249c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
6259c8be598SAurelien Jarno }
6269c8be598SAurelien Jarno 
6279c8be598SAurelien Jarno /* 64-bit FP compare and signal */
6289c8be598SAurelien Jarno uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
6299c8be598SAurelien Jarno {
6309c8be598SAurelien Jarno     int cmp = float64_compare(f1, f2, &env->fpu_status);
6319c8be598SAurelien Jarno     handle_exceptions(env, GETPC());
6329c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
6339c8be598SAurelien Jarno }
6349c8be598SAurelien Jarno 
6359c8be598SAurelien Jarno /* 128-bit FP compare and signal */
6369c8be598SAurelien Jarno uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
6379c8be598SAurelien Jarno                      uint64_t bh, uint64_t bl)
6389c8be598SAurelien Jarno {
6399c8be598SAurelien Jarno     int cmp = float128_compare(make_float128(ah, al),
6409c8be598SAurelien Jarno                                make_float128(bh, bl),
6419c8be598SAurelien Jarno                                &env->fpu_status);
6429c8be598SAurelien Jarno     handle_exceptions(env, GETPC());
6439c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
6449c8be598SAurelien Jarno }
6459c8be598SAurelien Jarno 
646722bfec3SRichard Henderson /* 32-bit FP multiply and add */
647722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
648722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
649e72ca652SBlue Swirl {
650722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
651722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
652722bfec3SRichard Henderson     return ret;
653722bfec3SRichard Henderson }
654e72ca652SBlue Swirl 
655722bfec3SRichard Henderson /* 64-bit FP multiply and add */
656722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
657722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
658722bfec3SRichard Henderson {
659722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
660722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
661722bfec3SRichard Henderson     return ret;
662722bfec3SRichard Henderson }
663722bfec3SRichard Henderson 
664722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */
665722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
666722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
667722bfec3SRichard Henderson {
668722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
669e72ca652SBlue Swirl                                  &env->fpu_status);
670722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
671722bfec3SRichard Henderson     return ret;
672e72ca652SBlue Swirl }
673e72ca652SBlue Swirl 
674722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */
675722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
676722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
677e72ca652SBlue Swirl {
678722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
679e72ca652SBlue Swirl                                  &env->fpu_status);
680722bfec3SRichard Henderson     handle_exceptions(env, GETPC());
681722bfec3SRichard Henderson     return ret;
682e72ca652SBlue Swirl }
683e72ca652SBlue Swirl 
684fc7cc951SDavid Hildenbrand /* The rightmost bit has the number 11. */
685fc7cc951SDavid Hildenbrand static inline uint16_t dcmask(int bit, bool neg)
686fc7cc951SDavid Hildenbrand {
687fc7cc951SDavid Hildenbrand     return 1 << (11 - bit - neg);
688fc7cc951SDavid Hildenbrand }
689fc7cc951SDavid Hildenbrand 
690fc7cc951SDavid Hildenbrand #define DEF_FLOAT_DCMASK(_TYPE) \
691fc7cc951SDavid Hildenbrand static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1)       \
692fc7cc951SDavid Hildenbrand {                                                                  \
693fc7cc951SDavid Hildenbrand     const bool neg = _TYPE##_is_neg(f1);                           \
694fc7cc951SDavid Hildenbrand                                                                    \
695fc7cc951SDavid Hildenbrand     /* Sorted by most common cases - only one class is possible */ \
696fc7cc951SDavid Hildenbrand     if (_TYPE##_is_normal(f1)) {                                   \
697fc7cc951SDavid Hildenbrand         return dcmask(2, neg);                                     \
698fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_zero(f1)) {                              \
699fc7cc951SDavid Hildenbrand         return dcmask(0, neg);                                     \
700fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_denormal(f1)) {                          \
701fc7cc951SDavid Hildenbrand         return dcmask(4, neg);                                     \
702fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_infinity(f1)) {                          \
703fc7cc951SDavid Hildenbrand         return dcmask(6, neg);                                     \
704fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) {       \
705fc7cc951SDavid Hildenbrand         return dcmask(8, neg);                                     \
706fc7cc951SDavid Hildenbrand     }                                                              \
707fc7cc951SDavid Hildenbrand     /* signaling nan, as last remaining case */                    \
708fc7cc951SDavid Hildenbrand     return dcmask(10, neg);                                        \
709fc7cc951SDavid Hildenbrand }
710fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float32)
711fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float64)
712fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float128)
713fc7cc951SDavid Hildenbrand 
714e72ca652SBlue Swirl /* test data class 32-bit */
715af39bc8cSAleksandar Markovic uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
716e72ca652SBlue Swirl {
717fc7cc951SDavid Hildenbrand     return (m2 & float32_dcmask(env, f1)) != 0;
718e72ca652SBlue Swirl }
719e72ca652SBlue Swirl 
720e72ca652SBlue Swirl /* test data class 64-bit */
721af39bc8cSAleksandar Markovic uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
722e72ca652SBlue Swirl {
723fc7cc951SDavid Hildenbrand     return (m2 & float64_dcmask(env, v1)) != 0;
724e72ca652SBlue Swirl }
725e72ca652SBlue Swirl 
726e72ca652SBlue Swirl /* test data class 128-bit */
727fc7cc951SDavid Hildenbrand uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
728e72ca652SBlue Swirl {
729fc7cc951SDavid Hildenbrand     return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0;
730e72ca652SBlue Swirl }
731e72ca652SBlue Swirl 
73216d7b2a4SRichard Henderson /* square root 32-bit */
73316d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
734e72ca652SBlue Swirl {
73516d7b2a4SRichard Henderson     float32 ret = float32_sqrt(f2, &env->fpu_status);
73616d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
73716d7b2a4SRichard Henderson     return ret;
73816d7b2a4SRichard Henderson }
73916d7b2a4SRichard Henderson 
74016d7b2a4SRichard Henderson /* square root 64-bit */
74116d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
74216d7b2a4SRichard Henderson {
74316d7b2a4SRichard Henderson     float64 ret = float64_sqrt(f2, &env->fpu_status);
74416d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
74516d7b2a4SRichard Henderson     return ret;
74616d7b2a4SRichard Henderson }
74716d7b2a4SRichard Henderson 
74816d7b2a4SRichard Henderson /* square root 128-bit */
74916d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
75016d7b2a4SRichard Henderson {
75116d7b2a4SRichard Henderson     float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
75216d7b2a4SRichard Henderson     handle_exceptions(env, GETPC());
75316d7b2a4SRichard Henderson     return RET128(ret);
754e72ca652SBlue Swirl }
7558379bfdbSRichard Henderson 
756411edc22SRichard Henderson static const int fpc_to_rnd[4] = {
7578379bfdbSRichard Henderson     float_round_nearest_even,
7588379bfdbSRichard Henderson     float_round_to_zero,
7598379bfdbSRichard Henderson     float_round_up,
7608379bfdbSRichard Henderson     float_round_down
7618379bfdbSRichard Henderson };
7628379bfdbSRichard Henderson 
763411edc22SRichard Henderson /* set fpc */
764411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
765411edc22SRichard Henderson {
7668379bfdbSRichard Henderson     /* Install everything in the main FPC.  */
7678379bfdbSRichard Henderson     env->fpc = fpc;
7688379bfdbSRichard Henderson 
7698379bfdbSRichard Henderson     /* Install the rounding mode in the shadow fpu_status.  */
770411edc22SRichard Henderson     set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
771411edc22SRichard Henderson }
772411edc22SRichard Henderson 
773411edc22SRichard Henderson /* set fpc and signal */
774f66a0ecfSDavid Hildenbrand void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
775411edc22SRichard Henderson {
776411edc22SRichard Henderson     uint32_t signalling = env->fpc;
777411edc22SRichard Henderson     uint32_t s390_exc;
778411edc22SRichard Henderson 
779f66a0ecfSDavid Hildenbrand     /*
780f66a0ecfSDavid Hildenbrand      * FPC is set to the FPC operand with a bitwise OR of the signalling
781f66a0ecfSDavid Hildenbrand      * flags.
782f66a0ecfSDavid Hildenbrand      */
783f66a0ecfSDavid Hildenbrand     env->fpc = fpc | (signalling & 0x00ff0000);
784f66a0ecfSDavid Hildenbrand     set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
785411edc22SRichard Henderson 
786f66a0ecfSDavid Hildenbrand     /*
787f66a0ecfSDavid Hildenbrand      * If any signaling flag is enabled in the new FPC mask, a
788f66a0ecfSDavid Hildenbrand      * simulated-iee-exception exception occurs.
789f66a0ecfSDavid Hildenbrand      */
790f66a0ecfSDavid Hildenbrand     s390_exc = (signalling >> 16) & (fpc >> 24);
791411edc22SRichard Henderson     if (s390_exc) {
792*8772bbe4SDavid Hildenbrand         if (s390_exc & S390_IEEE_MASK_INVALID) {
793*8772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_INVALID;
794*8772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) {
795*8772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_DIVBYZERO;
796*8772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) {
797*8772bbe4SDavid Hildenbrand             s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT);
798*8772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) {
799*8772bbe4SDavid Hildenbrand             s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT);
800*8772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_INEXACT) {
801*8772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_INEXACT;
802*8772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_QUANTUM) {
803*8772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_QUANTUM;
804*8772bbe4SDavid Hildenbrand         }
805bbf6ea3bSDavid Hildenbrand         tcg_s390_data_exception(env, s390_exc | 3, GETPC());
806411edc22SRichard Henderson     }
8078379bfdbSRichard Henderson }
808