xref: /qemu/target/s390x/tcg/fpu_helper.c (revision 84307cd6027c4602913177ff09aeefa4743b7234)
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"
23b6b47223SCho, Yu-Chen #include "s390x-internal.h"
24bbf6ea3bSDavid Hildenbrand #include "tcg_s390x.h"
252ef6175aSRichard Henderson #include "exec/helper-proto.h"
2624f91e81SAlex Bennée #include "fpu/softfloat.h"
27e72ca652SBlue Swirl 
28e72ca652SBlue Swirl /* #define DEBUG_HELPER */
29e72ca652SBlue Swirl #ifdef DEBUG_HELPER
30e72ca652SBlue Swirl #define HELPER_LOG(x...) qemu_log(x)
31e72ca652SBlue Swirl #else
32e72ca652SBlue Swirl #define HELPER_LOG(x...)
33e72ca652SBlue Swirl #endif
34e72ca652SBlue Swirl 
RET128(float128 f)35ee5e866fSRichard Henderson static inline Int128 RET128(float128 f)
36ee5e866fSRichard Henderson {
37ee5e866fSRichard Henderson     return int128_make128(f.low, f.high);
38ee5e866fSRichard Henderson }
39587626f8SRichard Henderson 
ARG128(Int128 i)402b91240fSRichard Henderson static inline float128 ARG128(Int128 i)
412b91240fSRichard Henderson {
422b91240fSRichard Henderson     return make_float128(int128_gethi(i), int128_getlo(i));
432b91240fSRichard Henderson }
442b91240fSRichard Henderson 
s390_softfloat_exc_to_ieee(unsigned int exc)454b70fc54SDavid Hildenbrand uint8_t s390_softfloat_exc_to_ieee(unsigned int exc)
464b70fc54SDavid Hildenbrand {
474b70fc54SDavid Hildenbrand     uint8_t s390_exc = 0;
484b70fc54SDavid Hildenbrand 
494b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_invalid) ? S390_IEEE_MASK_INVALID : 0;
504b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0;
514b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0;
524b70fc54SDavid Hildenbrand     s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0;
5353684e34SIlya Leoshkevich     s390_exc |= (exc & (float_flag_inexact | float_flag_invalid_cvti)) ?
5453684e34SIlya Leoshkevich                 S390_IEEE_MASK_INEXACT : 0;
554b70fc54SDavid Hildenbrand 
564b70fc54SDavid Hildenbrand     return s390_exc;
574b70fc54SDavid Hildenbrand }
58587626f8SRichard Henderson 
59587626f8SRichard Henderson /* Should be called after any operation that may raise IEEE exceptions.  */
handle_exceptions(CPUS390XState * env,bool XxC,uintptr_t retaddr)60cf97f9ffSDavid Hildenbrand static void handle_exceptions(CPUS390XState *env, bool XxC, uintptr_t retaddr)
61587626f8SRichard Henderson {
62587626f8SRichard Henderson     unsigned s390_exc, qemu_exc;
63587626f8SRichard Henderson 
64587626f8SRichard Henderson     /* Get the exceptions raised by the current operation.  Reset the
65587626f8SRichard Henderson        fpu_status contents so that the next operation has a clean slate.  */
66587626f8SRichard Henderson     qemu_exc = env->fpu_status.float_exception_flags;
67587626f8SRichard Henderson     if (qemu_exc == 0) {
68587626f8SRichard Henderson         return;
69587626f8SRichard Henderson     }
70587626f8SRichard Henderson     env->fpu_status.float_exception_flags = 0;
714b70fc54SDavid Hildenbrand     s390_exc = s390_softfloat_exc_to_ieee(qemu_exc);
72587626f8SRichard Henderson 
73fcb9e9f2SDavid Hildenbrand     /*
746d6ad1d1SDavid Hildenbrand      * IEEE-Underflow exception recognition exists if a tininess condition
756d6ad1d1SDavid Hildenbrand      * (underflow) exists and
766d6ad1d1SDavid Hildenbrand      * - The mask bit in the FPC is zero and the result is inexact
776d6ad1d1SDavid Hildenbrand      * - The mask bit in the FPC is one
786d6ad1d1SDavid Hildenbrand      * So tininess conditions that are not inexact don't trigger any
796d6ad1d1SDavid Hildenbrand      * underflow action in case the mask bit is not one.
806d6ad1d1SDavid Hildenbrand      */
816d6ad1d1SDavid Hildenbrand     if (!(s390_exc & S390_IEEE_MASK_INEXACT) &&
826d6ad1d1SDavid Hildenbrand         !((env->fpc >> 24) & S390_IEEE_MASK_UNDERFLOW)) {
836d6ad1d1SDavid Hildenbrand         s390_exc &= ~S390_IEEE_MASK_UNDERFLOW;
846d6ad1d1SDavid Hildenbrand     }
856d6ad1d1SDavid Hildenbrand 
866d6ad1d1SDavid Hildenbrand     /*
87fcb9e9f2SDavid Hildenbrand      * FIXME:
88cced0d65SMichael Tokarev      * 1. Right now, all inexact conditions are indicated as
89fcb9e9f2SDavid Hildenbrand      *    "truncated" (0) and never as "incremented" (1) in the DXC.
90fcb9e9f2SDavid Hildenbrand      * 2. Only traps due to invalid/divbyzero are suppressing. Other traps
91fcb9e9f2SDavid Hildenbrand      *    are completing, meaning the target register has to be written!
92fcb9e9f2SDavid Hildenbrand      *    This, however will mean that we have to write the register before
93fcb9e9f2SDavid Hildenbrand      *    triggering the trap - impossible right now.
94fcb9e9f2SDavid Hildenbrand      */
95587626f8SRichard Henderson 
96fcb9e9f2SDavid Hildenbrand     /*
97fcb9e9f2SDavid Hildenbrand      * invalid/divbyzero cannot coexist with other conditions.
98fcb9e9f2SDavid Hildenbrand      * overflow/underflow however can coexist with inexact, we have to
9944ee69eaSThomas Huth      * handle it separately.
100fcb9e9f2SDavid Hildenbrand      */
101fcb9e9f2SDavid Hildenbrand     if (s390_exc & ~S390_IEEE_MASK_INEXACT) {
102fcb9e9f2SDavid Hildenbrand         if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
103fcb9e9f2SDavid Hildenbrand             /* trap condition - inexact reported along */
104bbf6ea3bSDavid Hildenbrand             tcg_s390_data_exception(env, s390_exc, retaddr);
105587626f8SRichard Henderson         }
106fcb9e9f2SDavid Hildenbrand         /* nontrap condition - inexact handled differently */
107fcb9e9f2SDavid Hildenbrand         env->fpc |= (s390_exc & ~S390_IEEE_MASK_INEXACT) << 16;
108fcb9e9f2SDavid Hildenbrand     }
109fcb9e9f2SDavid Hildenbrand 
110fcb9e9f2SDavid Hildenbrand     /* inexact handling */
111cf97f9ffSDavid Hildenbrand     if (s390_exc & S390_IEEE_MASK_INEXACT && !XxC) {
112fcb9e9f2SDavid Hildenbrand         /* trap condition - overflow/underflow _not_ reported along */
113fcb9e9f2SDavid Hildenbrand         if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) {
114fcb9e9f2SDavid Hildenbrand             tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT,
115fcb9e9f2SDavid Hildenbrand                                     retaddr);
116fcb9e9f2SDavid Hildenbrand         }
117fcb9e9f2SDavid Hildenbrand         /* nontrap condition */
118fcb9e9f2SDavid Hildenbrand         env->fpc |= (s390_exc & S390_IEEE_MASK_INEXACT) << 16;
119fcb9e9f2SDavid Hildenbrand     }
120587626f8SRichard Henderson }
121587626f8SRichard Henderson 
float_comp_to_cc(CPUS390XState * env,FloatRelation float_compare)12271bfd65cSRichard Henderson int float_comp_to_cc(CPUS390XState *env, FloatRelation float_compare)
123e72ca652SBlue Swirl {
124e72ca652SBlue Swirl     switch (float_compare) {
125e72ca652SBlue Swirl     case float_relation_equal:
126e72ca652SBlue Swirl         return 0;
127e72ca652SBlue Swirl     case float_relation_less:
128e72ca652SBlue Swirl         return 1;
129e72ca652SBlue Swirl     case float_relation_greater:
130e72ca652SBlue Swirl         return 2;
131e72ca652SBlue Swirl     case float_relation_unordered:
132e72ca652SBlue Swirl         return 3;
133e72ca652SBlue Swirl     default:
134dc79e928SRichard Henderson         cpu_abort(env_cpu(env), "unknown return value for float compare\n");
135e72ca652SBlue Swirl     }
136e72ca652SBlue Swirl }
137e72ca652SBlue Swirl 
138e72ca652SBlue Swirl /* condition codes for unary FP ops */
set_cc_nz_f32(float32 v)139e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v)
140e72ca652SBlue Swirl {
141e72ca652SBlue Swirl     if (float32_is_any_nan(v)) {
142e72ca652SBlue Swirl         return 3;
143e72ca652SBlue Swirl     } else if (float32_is_zero(v)) {
144e72ca652SBlue Swirl         return 0;
145e72ca652SBlue Swirl     } else if (float32_is_neg(v)) {
146e72ca652SBlue Swirl         return 1;
147e72ca652SBlue Swirl     } else {
148e72ca652SBlue Swirl         return 2;
149e72ca652SBlue Swirl     }
150e72ca652SBlue Swirl }
151e72ca652SBlue Swirl 
set_cc_nz_f64(float64 v)152e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v)
153e72ca652SBlue Swirl {
154e72ca652SBlue Swirl     if (float64_is_any_nan(v)) {
155e72ca652SBlue Swirl         return 3;
156e72ca652SBlue Swirl     } else if (float64_is_zero(v)) {
157e72ca652SBlue Swirl         return 0;
158e72ca652SBlue Swirl     } else if (float64_is_neg(v)) {
159e72ca652SBlue Swirl         return 1;
160e72ca652SBlue Swirl     } else {
161e72ca652SBlue Swirl         return 2;
162e72ca652SBlue Swirl     }
163e72ca652SBlue Swirl }
164e72ca652SBlue Swirl 
set_cc_nz_f128(float128 v)165587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v)
166e72ca652SBlue Swirl {
167e72ca652SBlue Swirl     if (float128_is_any_nan(v)) {
168e72ca652SBlue Swirl         return 3;
169e72ca652SBlue Swirl     } else if (float128_is_zero(v)) {
170e72ca652SBlue Swirl         return 0;
171e72ca652SBlue Swirl     } else if (float128_is_neg(v)) {
172e72ca652SBlue Swirl         return 1;
173e72ca652SBlue Swirl     } else {
174e72ca652SBlue Swirl         return 2;
175e72ca652SBlue Swirl     }
176e72ca652SBlue Swirl }
177e72ca652SBlue Swirl 
17828761057SUlrich Weigand /* condition codes for FP to integer conversion ops */
set_cc_conv_f32(float32 v,float_status * stat)17928761057SUlrich Weigand static uint32_t set_cc_conv_f32(float32 v, float_status *stat)
18028761057SUlrich Weigand {
18128761057SUlrich Weigand     if (stat->float_exception_flags & float_flag_invalid) {
18228761057SUlrich Weigand         return 3;
18328761057SUlrich Weigand     } else {
18428761057SUlrich Weigand         return set_cc_nz_f32(v);
18528761057SUlrich Weigand     }
18628761057SUlrich Weigand }
18728761057SUlrich Weigand 
set_cc_conv_f64(float64 v,float_status * stat)18828761057SUlrich Weigand static uint32_t set_cc_conv_f64(float64 v, float_status *stat)
18928761057SUlrich Weigand {
19028761057SUlrich Weigand     if (stat->float_exception_flags & float_flag_invalid) {
19128761057SUlrich Weigand         return 3;
19228761057SUlrich Weigand     } else {
19328761057SUlrich Weigand         return set_cc_nz_f64(v);
19428761057SUlrich Weigand     }
19528761057SUlrich Weigand }
19628761057SUlrich Weigand 
set_cc_conv_f128(float128 v,float_status * stat)19728761057SUlrich Weigand static uint32_t set_cc_conv_f128(float128 v, float_status *stat)
19828761057SUlrich Weigand {
19928761057SUlrich Weigand     if (stat->float_exception_flags & float_flag_invalid) {
20028761057SUlrich Weigand         return 3;
20128761057SUlrich Weigand     } else {
20228761057SUlrich Weigand         return set_cc_nz_f128(v);
20328761057SUlrich Weigand     }
20428761057SUlrich Weigand }
20528761057SUlrich Weigand 
round_from_m34(uint32_t m34)206dce0a58fSDavid Hildenbrand static inline uint8_t round_from_m34(uint32_t m34)
207dce0a58fSDavid Hildenbrand {
208dce0a58fSDavid Hildenbrand     return extract32(m34, 0, 4);
209dce0a58fSDavid Hildenbrand }
210dce0a58fSDavid Hildenbrand 
xxc_from_m34(uint32_t m34)211dce0a58fSDavid Hildenbrand static inline bool xxc_from_m34(uint32_t m34)
212dce0a58fSDavid Hildenbrand {
213dce0a58fSDavid Hildenbrand     /* XxC is bit 1 of m4 */
214dce0a58fSDavid Hildenbrand     return extract32(m34, 4 + 3 - 1, 1);
215dce0a58fSDavid Hildenbrand }
216dce0a58fSDavid Hildenbrand 
217587626f8SRichard Henderson /* 32-bit FP addition */
HELPER(aeb)218587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
219e72ca652SBlue Swirl {
220587626f8SRichard Henderson     float32 ret = float32_add(f1, f2, &env->fpu_status);
221cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
222587626f8SRichard Henderson     return ret;
223e72ca652SBlue Swirl }
224e72ca652SBlue Swirl 
225587626f8SRichard Henderson /* 64-bit FP addition */
HELPER(adb)226587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
227e72ca652SBlue Swirl {
228587626f8SRichard Henderson     float64 ret = float64_add(f1, f2, &env->fpu_status);
229cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
230587626f8SRichard Henderson     return ret;
231587626f8SRichard Henderson }
232e72ca652SBlue Swirl 
233587626f8SRichard Henderson /* 128-bit FP addition */
HELPER(axb)2342b91240fSRichard Henderson Int128 HELPER(axb)(CPUS390XState *env, Int128 a, Int128 b)
235587626f8SRichard Henderson {
2362b91240fSRichard Henderson     float128 ret = float128_add(ARG128(a), ARG128(b), &env->fpu_status);
237cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
238587626f8SRichard Henderson     return RET128(ret);
239e72ca652SBlue Swirl }
240e72ca652SBlue Swirl 
2411a800a2dSRichard Henderson /* 32-bit FP subtraction */
HELPER(seb)2421a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
243e72ca652SBlue Swirl {
2441a800a2dSRichard Henderson     float32 ret = float32_sub(f1, f2, &env->fpu_status);
245cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
2461a800a2dSRichard Henderson     return ret;
247e72ca652SBlue Swirl }
248e72ca652SBlue Swirl 
2491a800a2dSRichard Henderson /* 64-bit FP subtraction */
HELPER(sdb)2501a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
251e72ca652SBlue Swirl {
2521a800a2dSRichard Henderson     float64 ret = float64_sub(f1, f2, &env->fpu_status);
253cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
2541a800a2dSRichard Henderson     return ret;
2551a800a2dSRichard Henderson }
256e72ca652SBlue Swirl 
2571a800a2dSRichard Henderson /* 128-bit FP subtraction */
HELPER(sxb)2582b91240fSRichard Henderson Int128 HELPER(sxb)(CPUS390XState *env, Int128 a, Int128 b)
2591a800a2dSRichard Henderson {
2602b91240fSRichard Henderson     float128 ret = float128_sub(ARG128(a), ARG128(b), &env->fpu_status);
261cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
2621a800a2dSRichard Henderson     return RET128(ret);
263e72ca652SBlue Swirl }
264e72ca652SBlue Swirl 
265f08a5c31SRichard Henderson /* 32-bit FP division */
HELPER(deb)266f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
267e72ca652SBlue Swirl {
268f08a5c31SRichard Henderson     float32 ret = float32_div(f1, f2, &env->fpu_status);
269cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
270f08a5c31SRichard Henderson     return ret;
271e72ca652SBlue Swirl }
272e72ca652SBlue Swirl 
273f08a5c31SRichard Henderson /* 64-bit FP division */
HELPER(ddb)274f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
275e72ca652SBlue Swirl {
276f08a5c31SRichard Henderson     float64 ret = float64_div(f1, f2, &env->fpu_status);
277cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
278f08a5c31SRichard Henderson     return ret;
279f08a5c31SRichard Henderson }
280e72ca652SBlue Swirl 
281f08a5c31SRichard Henderson /* 128-bit FP division */
HELPER(dxb)2822b91240fSRichard Henderson Int128 HELPER(dxb)(CPUS390XState *env, Int128 a, Int128 b)
283f08a5c31SRichard Henderson {
2842b91240fSRichard Henderson     float128 ret = float128_div(ARG128(a), ARG128(b), &env->fpu_status);
285cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
286f08a5c31SRichard Henderson     return RET128(ret);
287e72ca652SBlue Swirl }
288e72ca652SBlue Swirl 
28983b00736SRichard Henderson /* 32-bit FP multiplication */
HELPER(meeb)29083b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
291e72ca652SBlue Swirl {
29283b00736SRichard Henderson     float32 ret = float32_mul(f1, f2, &env->fpu_status);
293cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
29483b00736SRichard Henderson     return ret;
295e72ca652SBlue Swirl }
296e72ca652SBlue Swirl 
29783b00736SRichard Henderson /* 64-bit FP multiplication */
HELPER(mdb)29883b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
299e72ca652SBlue Swirl {
30083b00736SRichard Henderson     float64 ret = float64_mul(f1, f2, &env->fpu_status);
301cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
30283b00736SRichard Henderson     return ret;
30383b00736SRichard Henderson }
304e72ca652SBlue Swirl 
30583b00736SRichard Henderson /* 64/32-bit FP multiplication */
HELPER(mdeb)30683b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
30783b00736SRichard Henderson {
308fed9a4feSIlya Leoshkevich     float64 f1_64 = float32_to_float64(f1, &env->fpu_status);
30983b00736SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
310fed9a4feSIlya Leoshkevich     ret = float64_mul(f1_64, ret, &env->fpu_status);
311cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
31283b00736SRichard Henderson     return ret;
31383b00736SRichard Henderson }
31483b00736SRichard Henderson 
31583b00736SRichard Henderson /* 128-bit FP multiplication */
HELPER(mxb)3162b91240fSRichard Henderson Int128 HELPER(mxb)(CPUS390XState *env, Int128 a, Int128 b)
31783b00736SRichard Henderson {
3182b91240fSRichard Henderson     float128 ret = float128_mul(ARG128(a), ARG128(b), &env->fpu_status);
319cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
32083b00736SRichard Henderson     return RET128(ret);
32183b00736SRichard Henderson }
32283b00736SRichard Henderson 
32383b00736SRichard Henderson /* 128/64-bit FP multiplication */
HELPER(mxdb)324a7f4add7SIlya Leoshkevich Int128 HELPER(mxdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
32583b00736SRichard Henderson {
326a7f4add7SIlya Leoshkevich     float128 f1_128 = float64_to_float128(f1, &env->fpu_status);
32783b00736SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
328a7f4add7SIlya Leoshkevich     ret = float128_mul(f1_128, ret, &env->fpu_status);
329cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
33083b00736SRichard Henderson     return RET128(ret);
331e72ca652SBlue Swirl }
332e72ca652SBlue Swirl 
333e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */
HELPER(ldeb)334587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
335e72ca652SBlue Swirl {
336587626f8SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
337cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
338d0cfecb5SRichard Henderson     return ret;
339e72ca652SBlue Swirl }
340e72ca652SBlue Swirl 
341e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */
HELPER(ldxb)3422b91240fSRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, Int128 a, uint32_t m34)
343e72ca652SBlue Swirl {
344bdcfcd44SDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
3452b91240fSRichard Henderson     float64 ret = float128_to_float64(ARG128(a), &env->fpu_status);
346bdcfcd44SDavid Hildenbrand 
347bdcfcd44SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
348bdcfcd44SDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
349d0cfecb5SRichard Henderson     return ret;
350e72ca652SBlue Swirl }
351e72ca652SBlue Swirl 
352e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */
HELPER(lxdb)353ee5e866fSRichard Henderson Int128 HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
354e72ca652SBlue Swirl {
355587626f8SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
356cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
357d0cfecb5SRichard Henderson     return RET128(ret);
358587626f8SRichard Henderson }
359e72ca652SBlue Swirl 
360587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */
HELPER(lxeb)361ee5e866fSRichard Henderson Int128 HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
362587626f8SRichard Henderson {
363587626f8SRichard Henderson     float128 ret = float32_to_float128(f2, &env->fpu_status);
364cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
365d0cfecb5SRichard Henderson     return RET128(ret);
366e72ca652SBlue Swirl }
367e72ca652SBlue Swirl 
368e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */
HELPER(ledb)369bdcfcd44SDavid Hildenbrand uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
370e72ca652SBlue Swirl {
371bdcfcd44SDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
372587626f8SRichard Henderson     float32 ret = float64_to_float32(f2, &env->fpu_status);
373bdcfcd44SDavid Hildenbrand 
374bdcfcd44SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
375bdcfcd44SDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
376d0cfecb5SRichard Henderson     return ret;
377e72ca652SBlue Swirl }
378e72ca652SBlue Swirl 
379e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */
HELPER(lexb)3802b91240fSRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, Int128 a, uint32_t m34)
381e72ca652SBlue Swirl {
382bdcfcd44SDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
3832b91240fSRichard Henderson     float32 ret = float128_to_float32(ARG128(a), &env->fpu_status);
384bdcfcd44SDavid Hildenbrand 
385bdcfcd44SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
386bdcfcd44SDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
387d0cfecb5SRichard Henderson     return ret;
388e72ca652SBlue Swirl }
389e72ca652SBlue Swirl 
390587626f8SRichard Henderson /* 32-bit FP compare */
HELPER(ceb)391587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
392e72ca652SBlue Swirl {
39371bfd65cSRichard Henderson     FloatRelation cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
394cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
395587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
396e72ca652SBlue Swirl }
397e72ca652SBlue Swirl 
398587626f8SRichard Henderson /* 64-bit FP compare */
HELPER(cdb)399587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
400e72ca652SBlue Swirl {
40171bfd65cSRichard Henderson     FloatRelation cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
402cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
403587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
404e72ca652SBlue Swirl }
405e72ca652SBlue Swirl 
406587626f8SRichard Henderson /* 128-bit FP compare */
HELPER(cxb)4072b91240fSRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, Int128 a, Int128 b)
408e72ca652SBlue Swirl {
4092b91240fSRichard Henderson     FloatRelation cmp = float128_compare_quiet(ARG128(a), ARG128(b),
410587626f8SRichard Henderson                                                &env->fpu_status);
411cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
412587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
413e72ca652SBlue Swirl }
414e72ca652SBlue Swirl 
s390_swap_bfp_rounding_mode(CPUS390XState * env,int m3)415c0ee7015SDavid Hildenbrand int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
416e72ca652SBlue Swirl {
41768c8bd93SRichard Henderson     int ret = env->fpu_status.float_rounding_mode;
418b12b103eSDavid Hildenbrand 
419e72ca652SBlue Swirl     switch (m3) {
420e72ca652SBlue Swirl     case 0:
421e72ca652SBlue Swirl         /* current mode */
422e72ca652SBlue Swirl         break;
423e72ca652SBlue Swirl     case 1:
424b12b103eSDavid Hildenbrand         /* round to nearest with ties away from 0 */
425b12b103eSDavid Hildenbrand         set_float_rounding_mode(float_round_ties_away, &env->fpu_status);
426b12b103eSDavid Hildenbrand         break;
427b12b103eSDavid Hildenbrand     case 3:
428b12b103eSDavid Hildenbrand         /* round to prepare for shorter precision */
429b12b103eSDavid Hildenbrand         set_float_rounding_mode(float_round_to_odd, &env->fpu_status);
430b12b103eSDavid Hildenbrand         break;
431e72ca652SBlue Swirl     case 4:
432b12b103eSDavid Hildenbrand         /* round to nearest with ties to even */
433e72ca652SBlue Swirl         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
434e72ca652SBlue Swirl         break;
435e72ca652SBlue Swirl     case 5:
436e72ca652SBlue Swirl         /* round to zero */
437e72ca652SBlue Swirl         set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
438e72ca652SBlue Swirl         break;
439e72ca652SBlue Swirl     case 6:
440e72ca652SBlue Swirl         /* round to +inf */
441e72ca652SBlue Swirl         set_float_rounding_mode(float_round_up, &env->fpu_status);
442e72ca652SBlue Swirl         break;
443e72ca652SBlue Swirl     case 7:
444e72ca652SBlue Swirl         /* round to -inf */
445e72ca652SBlue Swirl         set_float_rounding_mode(float_round_down, &env->fpu_status);
446e72ca652SBlue Swirl         break;
447b12b103eSDavid Hildenbrand     default:
448b12b103eSDavid Hildenbrand         g_assert_not_reached();
449e72ca652SBlue Swirl     }
45068c8bd93SRichard Henderson     return ret;
451e72ca652SBlue Swirl }
452e72ca652SBlue Swirl 
s390_restore_bfp_rounding_mode(CPUS390XState * env,int old_mode)453c0ee7015SDavid Hildenbrand void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode)
454c0ee7015SDavid Hildenbrand {
455c0ee7015SDavid Hildenbrand     set_float_rounding_mode(old_mode, &env->fpu_status);
456c0ee7015SDavid Hildenbrand }
457c0ee7015SDavid Hildenbrand 
458683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */
HELPER(cegb)459dce0a58fSDavid Hildenbrand uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m34)
460683bb9a8SRichard Henderson {
461dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
462683bb9a8SRichard Henderson     float32 ret = int64_to_float32(v2, &env->fpu_status);
463c0ee7015SDavid Hildenbrand 
464c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
465dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
466683bb9a8SRichard Henderson     return ret;
467683bb9a8SRichard Henderson }
468683bb9a8SRichard Henderson 
469683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */
HELPER(cdgb)470dce0a58fSDavid Hildenbrand uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
471683bb9a8SRichard Henderson {
472dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
473683bb9a8SRichard Henderson     float64 ret = int64_to_float64(v2, &env->fpu_status);
474c0ee7015SDavid Hildenbrand 
475c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
476dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
477683bb9a8SRichard Henderson     return ret;
478683bb9a8SRichard Henderson }
479683bb9a8SRichard Henderson 
480683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */
HELPER(cxgb)481ee5e866fSRichard Henderson Int128 HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
482683bb9a8SRichard Henderson {
483dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
484683bb9a8SRichard Henderson     float128 ret = int64_to_float128(v2, &env->fpu_status);
485c0ee7015SDavid Hildenbrand 
486c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
487dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
488683bb9a8SRichard Henderson     return RET128(ret);
489683bb9a8SRichard Henderson }
490683bb9a8SRichard Henderson 
4912112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */
HELPER(celgb)492dce0a58fSDavid Hildenbrand uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
4932112bf1bSRichard Henderson {
494dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
4952112bf1bSRichard Henderson     float32 ret = uint64_to_float32(v2, &env->fpu_status);
496c0ee7015SDavid Hildenbrand 
497c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
498dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
4992112bf1bSRichard Henderson     return ret;
5002112bf1bSRichard Henderson }
5012112bf1bSRichard Henderson 
5022112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */
HELPER(cdlgb)503dce0a58fSDavid Hildenbrand uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
5042112bf1bSRichard Henderson {
505dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
5062112bf1bSRichard Henderson     float64 ret = uint64_to_float64(v2, &env->fpu_status);
507c0ee7015SDavid Hildenbrand 
508c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
509dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
5102112bf1bSRichard Henderson     return ret;
5112112bf1bSRichard Henderson }
5122112bf1bSRichard Henderson 
5132112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */
HELPER(cxlgb)514ee5e866fSRichard Henderson Int128 HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
5152112bf1bSRichard Henderson {
516dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
517d2d9feacSRichard Henderson     float128 ret = uint64_to_float128(v2, &env->fpu_status);
518c0ee7015SDavid Hildenbrand 
519c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
520dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
5212112bf1bSRichard Henderson     return RET128(ret);
5222112bf1bSRichard Henderson }
5232112bf1bSRichard Henderson 
524e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */
HELPER(cgeb)525dce0a58fSDavid Hildenbrand uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
526e72ca652SBlue Swirl {
527dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
52868c8bd93SRichard Henderson     int64_t ret = float32_to_int64(v2, &env->fpu_status);
52928761057SUlrich Weigand     uint32_t cc = set_cc_conv_f32(v2, &env->fpu_status);
530c0ee7015SDavid Hildenbrand 
531c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
532dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
53328761057SUlrich Weigand     env->cc_op = cc;
5340a3be7beSDavid Hildenbrand     if (float32_is_any_nan(v2)) {
5350a3be7beSDavid Hildenbrand         return INT64_MIN;
5360a3be7beSDavid Hildenbrand     }
53768c8bd93SRichard Henderson     return ret;
538e72ca652SBlue Swirl }
539e72ca652SBlue Swirl 
540e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */
HELPER(cgdb)541dce0a58fSDavid Hildenbrand uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
542e72ca652SBlue Swirl {
543dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
54468c8bd93SRichard Henderson     int64_t ret = float64_to_int64(v2, &env->fpu_status);
54528761057SUlrich Weigand     uint32_t cc = set_cc_conv_f64(v2, &env->fpu_status);
546c0ee7015SDavid Hildenbrand 
547c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
548dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
54928761057SUlrich Weigand     env->cc_op = cc;
5500a3be7beSDavid Hildenbrand     if (float64_is_any_nan(v2)) {
5510a3be7beSDavid Hildenbrand         return INT64_MIN;
5520a3be7beSDavid Hildenbrand     }
55368c8bd93SRichard Henderson     return ret;
554e72ca652SBlue Swirl }
555e72ca652SBlue Swirl 
556e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */
HELPER(cgxb)5572b91240fSRichard Henderson uint64_t HELPER(cgxb)(CPUS390XState *env, Int128 i2, uint32_t m34)
558e72ca652SBlue Swirl {
559dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
5602b91240fSRichard Henderson     float128 v2 = ARG128(i2);
56168c8bd93SRichard Henderson     int64_t ret = float128_to_int64(v2, &env->fpu_status);
56228761057SUlrich Weigand     uint32_t cc = set_cc_conv_f128(v2, &env->fpu_status);
563c0ee7015SDavid Hildenbrand 
564c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
565dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
56628761057SUlrich Weigand     env->cc_op = cc;
5670a3be7beSDavid Hildenbrand     if (float128_is_any_nan(v2)) {
5680a3be7beSDavid Hildenbrand         return INT64_MIN;
5690a3be7beSDavid Hildenbrand     }
57068c8bd93SRichard Henderson     return ret;
571e72ca652SBlue Swirl }
572e72ca652SBlue Swirl 
573e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */
HELPER(cfeb)574dce0a58fSDavid Hildenbrand uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
575e72ca652SBlue Swirl {
576dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
57768c8bd93SRichard Henderson     int32_t ret = float32_to_int32(v2, &env->fpu_status);
57828761057SUlrich Weigand     uint32_t cc = set_cc_conv_f32(v2, &env->fpu_status);
579c0ee7015SDavid Hildenbrand 
580c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
581dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
58228761057SUlrich Weigand     env->cc_op = cc;
5830a3be7beSDavid Hildenbrand     if (float32_is_any_nan(v2)) {
5840a3be7beSDavid Hildenbrand         return INT32_MIN;
5850a3be7beSDavid Hildenbrand     }
58668c8bd93SRichard Henderson     return ret;
587e72ca652SBlue Swirl }
588e72ca652SBlue Swirl 
589e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */
HELPER(cfdb)590dce0a58fSDavid Hildenbrand uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
591e72ca652SBlue Swirl {
592dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
59368c8bd93SRichard Henderson     int32_t ret = float64_to_int32(v2, &env->fpu_status);
59428761057SUlrich Weigand     uint32_t cc = set_cc_conv_f64(v2, &env->fpu_status);
595c0ee7015SDavid Hildenbrand 
596c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
597dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
59828761057SUlrich Weigand     env->cc_op = cc;
5990a3be7beSDavid Hildenbrand     if (float64_is_any_nan(v2)) {
6000a3be7beSDavid Hildenbrand         return INT32_MIN;
6010a3be7beSDavid Hildenbrand     }
60268c8bd93SRichard Henderson     return ret;
603e72ca652SBlue Swirl }
604e72ca652SBlue Swirl 
605e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */
HELPER(cfxb)6062b91240fSRichard Henderson uint64_t HELPER(cfxb)(CPUS390XState *env, Int128 i2, uint32_t m34)
607e72ca652SBlue Swirl {
608dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6092b91240fSRichard Henderson     float128 v2 = ARG128(i2);
61068c8bd93SRichard Henderson     int32_t ret = float128_to_int32(v2, &env->fpu_status);
61128761057SUlrich Weigand     uint32_t cc = set_cc_conv_f128(v2, &env->fpu_status);
612c0ee7015SDavid Hildenbrand 
613c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
614dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
61528761057SUlrich Weigand     env->cc_op = cc;
6160a3be7beSDavid Hildenbrand     if (float128_is_any_nan(v2)) {
6170a3be7beSDavid Hildenbrand         return INT32_MIN;
6180a3be7beSDavid Hildenbrand     }
61968c8bd93SRichard Henderson     return ret;
620e72ca652SBlue Swirl }
621e72ca652SBlue Swirl 
6226ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */
HELPER(clgeb)623dce0a58fSDavid Hildenbrand uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
6246ac1b45fSRichard Henderson {
625dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6260a3be7beSDavid Hildenbrand     uint64_t ret = float32_to_uint64(v2, &env->fpu_status);
62728761057SUlrich Weigand     uint32_t cc = set_cc_conv_f32(v2, &env->fpu_status);
62828761057SUlrich Weigand 
629c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
630dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
63128761057SUlrich Weigand     env->cc_op = cc;
6320a3be7beSDavid Hildenbrand     if (float32_is_any_nan(v2)) {
6330a3be7beSDavid Hildenbrand         return 0;
6340a3be7beSDavid Hildenbrand     }
6356ac1b45fSRichard Henderson     return ret;
6366ac1b45fSRichard Henderson }
6376ac1b45fSRichard Henderson 
6386ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */
HELPER(clgdb)639dce0a58fSDavid Hildenbrand uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
6406ac1b45fSRichard Henderson {
641dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6426ac1b45fSRichard Henderson     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
64328761057SUlrich Weigand     uint32_t cc = set_cc_conv_f64(v2, &env->fpu_status);
644c0ee7015SDavid Hildenbrand 
645c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
646dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
64728761057SUlrich Weigand     env->cc_op = cc;
6480a3be7beSDavid Hildenbrand     if (float64_is_any_nan(v2)) {
6490a3be7beSDavid Hildenbrand         return 0;
6500a3be7beSDavid Hildenbrand     }
6516ac1b45fSRichard Henderson     return ret;
6526ac1b45fSRichard Henderson }
6536ac1b45fSRichard Henderson 
6546ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */
HELPER(clgxb)6552b91240fSRichard Henderson uint64_t HELPER(clgxb)(CPUS390XState *env, Int128 i2, uint32_t m34)
6566ac1b45fSRichard Henderson {
657dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6582b91240fSRichard Henderson     float128 v2 = ARG128(i2);
65928761057SUlrich Weigand     uint64_t ret = float128_to_uint64(v2, &env->fpu_status);
66028761057SUlrich Weigand     uint32_t cc = set_cc_conv_f128(v2, &env->fpu_status);
661c0ee7015SDavid Hildenbrand 
662c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
663dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
66428761057SUlrich Weigand     env->cc_op = cc;
66528761057SUlrich Weigand     if (float128_is_any_nan(v2)) {
6660a3be7beSDavid Hildenbrand         return 0;
6670a3be7beSDavid Hildenbrand     }
6686ac1b45fSRichard Henderson     return ret;
6696ac1b45fSRichard Henderson }
6706ac1b45fSRichard Henderson 
6716ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */
HELPER(clfeb)672dce0a58fSDavid Hildenbrand uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
6736ac1b45fSRichard Henderson {
674dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6756ac1b45fSRichard Henderson     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
67628761057SUlrich Weigand     uint32_t cc = set_cc_conv_f32(v2, &env->fpu_status);
677c0ee7015SDavid Hildenbrand 
678c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
679dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
68028761057SUlrich Weigand     env->cc_op = cc;
6810a3be7beSDavid Hildenbrand     if (float32_is_any_nan(v2)) {
6820a3be7beSDavid Hildenbrand         return 0;
6830a3be7beSDavid Hildenbrand     }
6846ac1b45fSRichard Henderson     return ret;
6856ac1b45fSRichard Henderson }
6866ac1b45fSRichard Henderson 
6876ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */
HELPER(clfdb)688dce0a58fSDavid Hildenbrand uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
6896ac1b45fSRichard Henderson {
690dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6916ac1b45fSRichard Henderson     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
69228761057SUlrich Weigand     uint32_t cc = set_cc_conv_f64(v2, &env->fpu_status);
693c0ee7015SDavid Hildenbrand 
694c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
695dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
69628761057SUlrich Weigand     env->cc_op = cc;
6970a3be7beSDavid Hildenbrand     if (float64_is_any_nan(v2)) {
6980a3be7beSDavid Hildenbrand         return 0;
6990a3be7beSDavid Hildenbrand     }
7006ac1b45fSRichard Henderson     return ret;
7016ac1b45fSRichard Henderson }
7026ac1b45fSRichard Henderson 
7036ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */
HELPER(clfxb)7042b91240fSRichard Henderson uint64_t HELPER(clfxb)(CPUS390XState *env, Int128 i2, uint32_t m34)
7056ac1b45fSRichard Henderson {
706dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
7072b91240fSRichard Henderson     float128 v2 = ARG128(i2);
70828761057SUlrich Weigand     uint32_t ret = float128_to_uint32(v2, &env->fpu_status);
70928761057SUlrich Weigand     uint32_t cc = set_cc_conv_f128(v2, &env->fpu_status);
710c0ee7015SDavid Hildenbrand 
711c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
712dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
71328761057SUlrich Weigand     env->cc_op = cc;
71428761057SUlrich Weigand     if (float128_is_any_nan(v2)) {
7150a3be7beSDavid Hildenbrand         return 0;
7160a3be7beSDavid Hildenbrand     }
7176ac1b45fSRichard Henderson     return ret;
7186ac1b45fSRichard Henderson }
7196ac1b45fSRichard Henderson 
720ed0bceceSAurelien Jarno /* round to integer 32-bit */
HELPER(fieb)721dce0a58fSDavid Hildenbrand uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
722ed0bceceSAurelien Jarno {
723dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
724ed0bceceSAurelien Jarno     float32 ret = float32_round_to_int(f2, &env->fpu_status);
725c0ee7015SDavid Hildenbrand 
726c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
727dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
728ed0bceceSAurelien Jarno     return ret;
729ed0bceceSAurelien Jarno }
730ed0bceceSAurelien Jarno 
731ed0bceceSAurelien Jarno /* round to integer 64-bit */
HELPER(fidb)732dce0a58fSDavid Hildenbrand uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
733ed0bceceSAurelien Jarno {
734dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
735ed0bceceSAurelien Jarno     float64 ret = float64_round_to_int(f2, &env->fpu_status);
736c0ee7015SDavid Hildenbrand 
737c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
738dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
739ed0bceceSAurelien Jarno     return ret;
740ed0bceceSAurelien Jarno }
741ed0bceceSAurelien Jarno 
742ed0bceceSAurelien Jarno /* round to integer 128-bit */
HELPER(fixb)7432b91240fSRichard Henderson Int128 HELPER(fixb)(CPUS390XState *env, Int128 a, uint32_t m34)
744ed0bceceSAurelien Jarno {
745dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
7462b91240fSRichard Henderson     float128 ret = float128_round_to_int(ARG128(a), &env->fpu_status);
747cf97f9ffSDavid Hildenbrand 
748c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
749dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
750ed0bceceSAurelien Jarno     return RET128(ret);
751ed0bceceSAurelien Jarno }
752ed0bceceSAurelien Jarno 
7539c8be598SAurelien Jarno /* 32-bit FP compare and signal */
HELPER(keb)7549c8be598SAurelien Jarno uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
7559c8be598SAurelien Jarno {
75671bfd65cSRichard Henderson     FloatRelation cmp = float32_compare(f1, f2, &env->fpu_status);
757cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
7589c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
7599c8be598SAurelien Jarno }
7609c8be598SAurelien Jarno 
7619c8be598SAurelien Jarno /* 64-bit FP compare and signal */
HELPER(kdb)7629c8be598SAurelien Jarno uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
7639c8be598SAurelien Jarno {
76471bfd65cSRichard Henderson     FloatRelation cmp = float64_compare(f1, f2, &env->fpu_status);
765cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
7669c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
7679c8be598SAurelien Jarno }
7689c8be598SAurelien Jarno 
7699c8be598SAurelien Jarno /* 128-bit FP compare and signal */
HELPER(kxb)7702b91240fSRichard Henderson uint32_t HELPER(kxb)(CPUS390XState *env, Int128 a, Int128 b)
7719c8be598SAurelien Jarno {
7722b91240fSRichard Henderson     FloatRelation cmp = float128_compare(ARG128(a), ARG128(b),
7739c8be598SAurelien Jarno                                          &env->fpu_status);
774cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
7759c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
7769c8be598SAurelien Jarno }
7779c8be598SAurelien Jarno 
778722bfec3SRichard Henderson /* 32-bit FP multiply and add */
HELPER(maeb)779722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
780722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
781e72ca652SBlue Swirl {
782*e1f1ccb8SIlya Leoshkevich     float32 ret = float32_muladd(f3, f2, f1, 0, &env->fpu_status);
783cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
784722bfec3SRichard Henderson     return ret;
785722bfec3SRichard Henderson }
786e72ca652SBlue Swirl 
787722bfec3SRichard Henderson /* 64-bit FP multiply and add */
HELPER(madb)788722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
789722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
790722bfec3SRichard Henderson {
791*e1f1ccb8SIlya Leoshkevich     float64 ret = float64_muladd(f3, f2, f1, 0, &env->fpu_status);
792cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
793722bfec3SRichard Henderson     return ret;
794722bfec3SRichard Henderson }
795722bfec3SRichard Henderson 
796722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */
HELPER(mseb)797722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
798722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
799722bfec3SRichard Henderson {
800*e1f1ccb8SIlya Leoshkevich     float32 ret = float32_muladd(f3, f2, f1, float_muladd_negate_c,
801e72ca652SBlue Swirl                                  &env->fpu_status);
802cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
803722bfec3SRichard Henderson     return ret;
804e72ca652SBlue Swirl }
805e72ca652SBlue Swirl 
806722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */
HELPER(msdb)807722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
808722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
809e72ca652SBlue Swirl {
810*e1f1ccb8SIlya Leoshkevich     float64 ret = float64_muladd(f3, f2, f1, float_muladd_negate_c,
811e72ca652SBlue Swirl                                  &env->fpu_status);
812cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
813722bfec3SRichard Henderson     return ret;
814e72ca652SBlue Swirl }
815e72ca652SBlue Swirl 
816fc7cc951SDavid Hildenbrand /* The rightmost bit has the number 11. */
dcmask(int bit,bool neg)817fc7cc951SDavid Hildenbrand static inline uint16_t dcmask(int bit, bool neg)
818fc7cc951SDavid Hildenbrand {
819fc7cc951SDavid Hildenbrand     return 1 << (11 - bit - neg);
820fc7cc951SDavid Hildenbrand }
821fc7cc951SDavid Hildenbrand 
822fc7cc951SDavid Hildenbrand #define DEF_FLOAT_DCMASK(_TYPE) \
823aae65009SDavid Hildenbrand uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1)              \
824fc7cc951SDavid Hildenbrand {                                                                  \
825fc7cc951SDavid Hildenbrand     const bool neg = _TYPE##_is_neg(f1);                           \
826fc7cc951SDavid Hildenbrand                                                                    \
827fc7cc951SDavid Hildenbrand     /* Sorted by most common cases - only one class is possible */ \
828fc7cc951SDavid Hildenbrand     if (_TYPE##_is_normal(f1)) {                                   \
829fc7cc951SDavid Hildenbrand         return dcmask(2, neg);                                     \
830fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_zero(f1)) {                              \
831fc7cc951SDavid Hildenbrand         return dcmask(0, neg);                                     \
832fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_denormal(f1)) {                          \
833fc7cc951SDavid Hildenbrand         return dcmask(4, neg);                                     \
834fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_infinity(f1)) {                          \
835fc7cc951SDavid Hildenbrand         return dcmask(6, neg);                                     \
836fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) {       \
837fc7cc951SDavid Hildenbrand         return dcmask(8, neg);                                     \
838fc7cc951SDavid Hildenbrand     }                                                              \
839fc7cc951SDavid Hildenbrand     /* signaling nan, as last remaining case */                    \
840fc7cc951SDavid Hildenbrand     return dcmask(10, neg);                                        \
841fc7cc951SDavid Hildenbrand }
842fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float32)
DEF_FLOAT_DCMASK(float64)843fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float64)
844fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float128)
845fc7cc951SDavid Hildenbrand 
846e72ca652SBlue Swirl /* test data class 32-bit */
847af39bc8cSAleksandar Markovic uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
848e72ca652SBlue Swirl {
849fc7cc951SDavid Hildenbrand     return (m2 & float32_dcmask(env, f1)) != 0;
850e72ca652SBlue Swirl }
851e72ca652SBlue Swirl 
852e72ca652SBlue Swirl /* test data class 64-bit */
HELPER(tcdb)853af39bc8cSAleksandar Markovic uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
854e72ca652SBlue Swirl {
855fc7cc951SDavid Hildenbrand     return (m2 & float64_dcmask(env, v1)) != 0;
856e72ca652SBlue Swirl }
857e72ca652SBlue Swirl 
858e72ca652SBlue Swirl /* test data class 128-bit */
HELPER(tcxb)8592b91240fSRichard Henderson uint32_t HELPER(tcxb)(CPUS390XState *env, Int128 a, uint64_t m2)
860e72ca652SBlue Swirl {
8612b91240fSRichard Henderson     return (m2 & float128_dcmask(env, ARG128(a))) != 0;
862e72ca652SBlue Swirl }
863e72ca652SBlue Swirl 
86416d7b2a4SRichard Henderson /* square root 32-bit */
HELPER(sqeb)86516d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
866e72ca652SBlue Swirl {
86716d7b2a4SRichard Henderson     float32 ret = float32_sqrt(f2, &env->fpu_status);
868cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
86916d7b2a4SRichard Henderson     return ret;
87016d7b2a4SRichard Henderson }
87116d7b2a4SRichard Henderson 
87216d7b2a4SRichard Henderson /* square root 64-bit */
HELPER(sqdb)87316d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
87416d7b2a4SRichard Henderson {
87516d7b2a4SRichard Henderson     float64 ret = float64_sqrt(f2, &env->fpu_status);
876cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
87716d7b2a4SRichard Henderson     return ret;
87816d7b2a4SRichard Henderson }
87916d7b2a4SRichard Henderson 
88016d7b2a4SRichard Henderson /* square root 128-bit */
HELPER(sqxb)8812b91240fSRichard Henderson Int128 HELPER(sqxb)(CPUS390XState *env, Int128 a)
88216d7b2a4SRichard Henderson {
8832b91240fSRichard Henderson     float128 ret = float128_sqrt(ARG128(a), &env->fpu_status);
884cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
88516d7b2a4SRichard Henderson     return RET128(ret);
886e72ca652SBlue Swirl }
8878379bfdbSRichard Henderson 
8882aea83c6SDavid Hildenbrand static const int fpc_to_rnd[8] = {
8898379bfdbSRichard Henderson     float_round_nearest_even,
8908379bfdbSRichard Henderson     float_round_to_zero,
8918379bfdbSRichard Henderson     float_round_up,
8922aea83c6SDavid Hildenbrand     float_round_down,
8932aea83c6SDavid Hildenbrand     -1,
8942aea83c6SDavid Hildenbrand     -1,
8952aea83c6SDavid Hildenbrand     -1,
8962aea83c6SDavid Hildenbrand     float_round_to_odd,
8978379bfdbSRichard Henderson };
8988379bfdbSRichard Henderson 
899411edc22SRichard Henderson /* set fpc */
HELPER(sfpc)900411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
901411edc22SRichard Henderson {
9022aea83c6SDavid Hildenbrand     if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
9032aea83c6SDavid Hildenbrand         (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
9041e36aee6SRichard Henderson         tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
9052aea83c6SDavid Hildenbrand     }
9062aea83c6SDavid Hildenbrand 
9078379bfdbSRichard Henderson     /* Install everything in the main FPC.  */
9088379bfdbSRichard Henderson     env->fpc = fpc;
9098379bfdbSRichard Henderson 
9108379bfdbSRichard Henderson     /* Install the rounding mode in the shadow fpu_status.  */
9112aea83c6SDavid Hildenbrand     set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
912411edc22SRichard Henderson }
913411edc22SRichard Henderson 
914411edc22SRichard Henderson /* set fpc and signal */
HELPER(sfas)915f66a0ecfSDavid Hildenbrand void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
916411edc22SRichard Henderson {
917411edc22SRichard Henderson     uint32_t signalling = env->fpc;
918411edc22SRichard Henderson     uint32_t s390_exc;
919411edc22SRichard Henderson 
9202aea83c6SDavid Hildenbrand     if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
9212aea83c6SDavid Hildenbrand         (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
9221e36aee6SRichard Henderson         tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
9232aea83c6SDavid Hildenbrand     }
9242aea83c6SDavid Hildenbrand 
925f66a0ecfSDavid Hildenbrand     /*
926f66a0ecfSDavid Hildenbrand      * FPC is set to the FPC operand with a bitwise OR of the signalling
927f66a0ecfSDavid Hildenbrand      * flags.
928f66a0ecfSDavid Hildenbrand      */
929f66a0ecfSDavid Hildenbrand     env->fpc = fpc | (signalling & 0x00ff0000);
9302aea83c6SDavid Hildenbrand     set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
931411edc22SRichard Henderson 
932f66a0ecfSDavid Hildenbrand     /*
933f66a0ecfSDavid Hildenbrand      * If any signaling flag is enabled in the new FPC mask, a
934f66a0ecfSDavid Hildenbrand      * simulated-iee-exception exception occurs.
935f66a0ecfSDavid Hildenbrand      */
936f66a0ecfSDavid Hildenbrand     s390_exc = (signalling >> 16) & (fpc >> 24);
937411edc22SRichard Henderson     if (s390_exc) {
9388772bbe4SDavid Hildenbrand         if (s390_exc & S390_IEEE_MASK_INVALID) {
9398772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_INVALID;
9408772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) {
9418772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_DIVBYZERO;
9428772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) {
9438772bbe4SDavid Hildenbrand             s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT);
9448772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) {
9458772bbe4SDavid Hildenbrand             s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT);
9468772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_INEXACT) {
9478772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_INEXACT;
9488772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_QUANTUM) {
9498772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_QUANTUM;
9508772bbe4SDavid Hildenbrand         }
951bbf6ea3bSDavid Hildenbrand         tcg_s390_data_exception(env, s390_exc | 3, GETPC());
952411edc22SRichard Henderson     }
9538379bfdbSRichard Henderson }
954b9c737f5SDavid Hildenbrand 
955b9c737f5SDavid Hildenbrand /* set bfp rounding mode */
HELPER(srnm)956b9c737f5SDavid Hildenbrand void HELPER(srnm)(CPUS390XState *env, uint64_t rnd)
957b9c737f5SDavid Hildenbrand {
958b9c737f5SDavid Hildenbrand     if (rnd > 0x7 || fpc_to_rnd[rnd & 0x7] == -1) {
9591e36aee6SRichard Henderson         tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
960b9c737f5SDavid Hildenbrand     }
961b9c737f5SDavid Hildenbrand 
962b9c737f5SDavid Hildenbrand     env->fpc = deposit32(env->fpc, 0, 3, rnd);
963b9c737f5SDavid Hildenbrand     set_float_rounding_mode(fpc_to_rnd[rnd & 0x7], &env->fpu_status);
964b9c737f5SDavid Hildenbrand }
965