xref: /qemu/target/s390x/tcg/fpu_helper.c (revision 44ee69ea16bd0390082ed88d4e82d6cea3a18b46)
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"
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.  */
53cf97f9ffSDavid Hildenbrand static void handle_exceptions(CPUS390XState *env, bool XxC, 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
92*44ee69eaSThomas Huth      * handle it separately.
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 */
104cf97f9ffSDavid Hildenbrand     if (s390_exc & S390_IEEE_MASK_INEXACT && !XxC) {
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 
11571bfd65cSRichard Henderson int float_comp_to_cc(CPUS390XState *env, FloatRelation float_compare)
116e72ca652SBlue Swirl {
117e72ca652SBlue Swirl     switch (float_compare) {
118e72ca652SBlue Swirl     case float_relation_equal:
119e72ca652SBlue Swirl         return 0;
120e72ca652SBlue Swirl     case float_relation_less:
121e72ca652SBlue Swirl         return 1;
122e72ca652SBlue Swirl     case float_relation_greater:
123e72ca652SBlue Swirl         return 2;
124e72ca652SBlue Swirl     case float_relation_unordered:
125e72ca652SBlue Swirl         return 3;
126e72ca652SBlue Swirl     default:
127dc79e928SRichard Henderson         cpu_abort(env_cpu(env), "unknown return value for float compare\n");
128e72ca652SBlue Swirl     }
129e72ca652SBlue Swirl }
130e72ca652SBlue Swirl 
131e72ca652SBlue Swirl /* condition codes for unary FP ops */
132e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v)
133e72ca652SBlue Swirl {
134e72ca652SBlue Swirl     if (float32_is_any_nan(v)) {
135e72ca652SBlue Swirl         return 3;
136e72ca652SBlue Swirl     } else if (float32_is_zero(v)) {
137e72ca652SBlue Swirl         return 0;
138e72ca652SBlue Swirl     } else if (float32_is_neg(v)) {
139e72ca652SBlue Swirl         return 1;
140e72ca652SBlue Swirl     } else {
141e72ca652SBlue Swirl         return 2;
142e72ca652SBlue Swirl     }
143e72ca652SBlue Swirl }
144e72ca652SBlue Swirl 
145e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v)
146e72ca652SBlue Swirl {
147e72ca652SBlue Swirl     if (float64_is_any_nan(v)) {
148e72ca652SBlue Swirl         return 3;
149e72ca652SBlue Swirl     } else if (float64_is_zero(v)) {
150e72ca652SBlue Swirl         return 0;
151e72ca652SBlue Swirl     } else if (float64_is_neg(v)) {
152e72ca652SBlue Swirl         return 1;
153e72ca652SBlue Swirl     } else {
154e72ca652SBlue Swirl         return 2;
155e72ca652SBlue Swirl     }
156e72ca652SBlue Swirl }
157e72ca652SBlue Swirl 
158587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v)
159e72ca652SBlue Swirl {
160e72ca652SBlue Swirl     if (float128_is_any_nan(v)) {
161e72ca652SBlue Swirl         return 3;
162e72ca652SBlue Swirl     } else if (float128_is_zero(v)) {
163e72ca652SBlue Swirl         return 0;
164e72ca652SBlue Swirl     } else if (float128_is_neg(v)) {
165e72ca652SBlue Swirl         return 1;
166e72ca652SBlue Swirl     } else {
167e72ca652SBlue Swirl         return 2;
168e72ca652SBlue Swirl     }
169e72ca652SBlue Swirl }
170e72ca652SBlue Swirl 
17128761057SUlrich Weigand /* condition codes for FP to integer conversion ops */
17228761057SUlrich Weigand static uint32_t set_cc_conv_f32(float32 v, float_status *stat)
17328761057SUlrich Weigand {
17428761057SUlrich Weigand     if (stat->float_exception_flags & float_flag_invalid) {
17528761057SUlrich Weigand         return 3;
17628761057SUlrich Weigand     } else {
17728761057SUlrich Weigand         return set_cc_nz_f32(v);
17828761057SUlrich Weigand     }
17928761057SUlrich Weigand }
18028761057SUlrich Weigand 
18128761057SUlrich Weigand static uint32_t set_cc_conv_f64(float64 v, float_status *stat)
18228761057SUlrich Weigand {
18328761057SUlrich Weigand     if (stat->float_exception_flags & float_flag_invalid) {
18428761057SUlrich Weigand         return 3;
18528761057SUlrich Weigand     } else {
18628761057SUlrich Weigand         return set_cc_nz_f64(v);
18728761057SUlrich Weigand     }
18828761057SUlrich Weigand }
18928761057SUlrich Weigand 
19028761057SUlrich Weigand static uint32_t set_cc_conv_f128(float128 v, float_status *stat)
19128761057SUlrich Weigand {
19228761057SUlrich Weigand     if (stat->float_exception_flags & float_flag_invalid) {
19328761057SUlrich Weigand         return 3;
19428761057SUlrich Weigand     } else {
19528761057SUlrich Weigand         return set_cc_nz_f128(v);
19628761057SUlrich Weigand     }
19728761057SUlrich Weigand }
19828761057SUlrich Weigand 
199dce0a58fSDavid Hildenbrand static inline uint8_t round_from_m34(uint32_t m34)
200dce0a58fSDavid Hildenbrand {
201dce0a58fSDavid Hildenbrand     return extract32(m34, 0, 4);
202dce0a58fSDavid Hildenbrand }
203dce0a58fSDavid Hildenbrand 
204dce0a58fSDavid Hildenbrand static inline bool xxc_from_m34(uint32_t m34)
205dce0a58fSDavid Hildenbrand {
206dce0a58fSDavid Hildenbrand     /* XxC is bit 1 of m4 */
207dce0a58fSDavid Hildenbrand     return extract32(m34, 4 + 3 - 1, 1);
208dce0a58fSDavid Hildenbrand }
209dce0a58fSDavid Hildenbrand 
210587626f8SRichard Henderson /* 32-bit FP addition */
211587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
212e72ca652SBlue Swirl {
213587626f8SRichard Henderson     float32 ret = float32_add(f1, f2, &env->fpu_status);
214cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
215587626f8SRichard Henderson     return ret;
216e72ca652SBlue Swirl }
217e72ca652SBlue Swirl 
218587626f8SRichard Henderson /* 64-bit FP addition */
219587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
220e72ca652SBlue Swirl {
221587626f8SRichard Henderson     float64 ret = float64_add(f1, f2, &env->fpu_status);
222cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
223587626f8SRichard Henderson     return ret;
224587626f8SRichard Henderson }
225e72ca652SBlue Swirl 
226587626f8SRichard Henderson /* 128-bit FP addition */
227587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
228587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
229587626f8SRichard Henderson {
230587626f8SRichard Henderson     float128 ret = float128_add(make_float128(ah, al),
231587626f8SRichard Henderson                                 make_float128(bh, bl),
232587626f8SRichard Henderson                                 &env->fpu_status);
233cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
234587626f8SRichard Henderson     return RET128(ret);
235e72ca652SBlue Swirl }
236e72ca652SBlue Swirl 
2371a800a2dSRichard Henderson /* 32-bit FP subtraction */
2381a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
239e72ca652SBlue Swirl {
2401a800a2dSRichard Henderson     float32 ret = float32_sub(f1, f2, &env->fpu_status);
241cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
2421a800a2dSRichard Henderson     return ret;
243e72ca652SBlue Swirl }
244e72ca652SBlue Swirl 
2451a800a2dSRichard Henderson /* 64-bit FP subtraction */
2461a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
247e72ca652SBlue Swirl {
2481a800a2dSRichard Henderson     float64 ret = float64_sub(f1, f2, &env->fpu_status);
249cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
2501a800a2dSRichard Henderson     return ret;
2511a800a2dSRichard Henderson }
252e72ca652SBlue Swirl 
2531a800a2dSRichard Henderson /* 128-bit FP subtraction */
2541a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
2551a800a2dSRichard Henderson                      uint64_t bh, uint64_t bl)
2561a800a2dSRichard Henderson {
2571a800a2dSRichard Henderson     float128 ret = float128_sub(make_float128(ah, al),
2581a800a2dSRichard Henderson                                 make_float128(bh, bl),
2591a800a2dSRichard Henderson                                 &env->fpu_status);
260cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
2611a800a2dSRichard Henderson     return RET128(ret);
262e72ca652SBlue Swirl }
263e72ca652SBlue Swirl 
264f08a5c31SRichard Henderson /* 32-bit FP division */
265f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
266e72ca652SBlue Swirl {
267f08a5c31SRichard Henderson     float32 ret = float32_div(f1, f2, &env->fpu_status);
268cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
269f08a5c31SRichard Henderson     return ret;
270e72ca652SBlue Swirl }
271e72ca652SBlue Swirl 
272f08a5c31SRichard Henderson /* 64-bit FP division */
273f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
274e72ca652SBlue Swirl {
275f08a5c31SRichard Henderson     float64 ret = float64_div(f1, f2, &env->fpu_status);
276cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
277f08a5c31SRichard Henderson     return ret;
278f08a5c31SRichard Henderson }
279e72ca652SBlue Swirl 
280f08a5c31SRichard Henderson /* 128-bit FP division */
281f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
282f08a5c31SRichard Henderson                      uint64_t bh, uint64_t bl)
283f08a5c31SRichard Henderson {
284f08a5c31SRichard Henderson     float128 ret = float128_div(make_float128(ah, al),
285f08a5c31SRichard Henderson                                 make_float128(bh, bl),
286f08a5c31SRichard Henderson                                 &env->fpu_status);
287cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
288f08a5c31SRichard Henderson     return RET128(ret);
289e72ca652SBlue Swirl }
290e72ca652SBlue Swirl 
29183b00736SRichard Henderson /* 32-bit FP multiplication */
29283b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
293e72ca652SBlue Swirl {
29483b00736SRichard Henderson     float32 ret = float32_mul(f1, f2, &env->fpu_status);
295cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
29683b00736SRichard Henderson     return ret;
297e72ca652SBlue Swirl }
298e72ca652SBlue Swirl 
29983b00736SRichard Henderson /* 64-bit FP multiplication */
30083b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
301e72ca652SBlue Swirl {
30283b00736SRichard Henderson     float64 ret = float64_mul(f1, f2, &env->fpu_status);
303cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
30483b00736SRichard Henderson     return ret;
30583b00736SRichard Henderson }
306e72ca652SBlue Swirl 
30783b00736SRichard Henderson /* 64/32-bit FP multiplication */
30883b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
30983b00736SRichard Henderson {
31083b00736SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
31183b00736SRichard Henderson     ret = float64_mul(f1, ret, &env->fpu_status);
312cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
31383b00736SRichard Henderson     return ret;
31483b00736SRichard Henderson }
31583b00736SRichard Henderson 
31683b00736SRichard Henderson /* 128-bit FP multiplication */
31783b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
31883b00736SRichard Henderson                      uint64_t bh, uint64_t bl)
31983b00736SRichard Henderson {
32083b00736SRichard Henderson     float128 ret = float128_mul(make_float128(ah, al),
32183b00736SRichard Henderson                                 make_float128(bh, bl),
32283b00736SRichard Henderson                                 &env->fpu_status);
323cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
32483b00736SRichard Henderson     return RET128(ret);
32583b00736SRichard Henderson }
32683b00736SRichard Henderson 
32783b00736SRichard Henderson /* 128/64-bit FP multiplication */
32883b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
32983b00736SRichard Henderson                       uint64_t f2)
33083b00736SRichard Henderson {
33183b00736SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
33283b00736SRichard Henderson     ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
333cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
33483b00736SRichard Henderson     return RET128(ret);
335e72ca652SBlue Swirl }
336e72ca652SBlue Swirl 
337e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */
338587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
339e72ca652SBlue Swirl {
340587626f8SRichard Henderson     float64 ret = float32_to_float64(f2, &env->fpu_status);
341cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
342d0cfecb5SRichard Henderson     return ret;
343e72ca652SBlue Swirl }
344e72ca652SBlue Swirl 
345e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */
346bdcfcd44SDavid Hildenbrand uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
347bdcfcd44SDavid Hildenbrand                       uint32_t m34)
348e72ca652SBlue Swirl {
349bdcfcd44SDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
350587626f8SRichard Henderson     float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
351bdcfcd44SDavid Hildenbrand 
352bdcfcd44SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
353bdcfcd44SDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
354d0cfecb5SRichard Henderson     return ret;
355e72ca652SBlue Swirl }
356e72ca652SBlue Swirl 
357e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */
358587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
359e72ca652SBlue Swirl {
360587626f8SRichard Henderson     float128 ret = float64_to_float128(f2, &env->fpu_status);
361cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
362d0cfecb5SRichard Henderson     return RET128(ret);
363587626f8SRichard Henderson }
364e72ca652SBlue Swirl 
365587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */
366587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
367587626f8SRichard Henderson {
368587626f8SRichard Henderson     float128 ret = float32_to_float128(f2, &env->fpu_status);
369cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
370d0cfecb5SRichard Henderson     return RET128(ret);
371e72ca652SBlue Swirl }
372e72ca652SBlue Swirl 
373e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */
374bdcfcd44SDavid Hildenbrand uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
375e72ca652SBlue Swirl {
376bdcfcd44SDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
377587626f8SRichard Henderson     float32 ret = float64_to_float32(f2, &env->fpu_status);
378bdcfcd44SDavid Hildenbrand 
379bdcfcd44SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
380bdcfcd44SDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
381d0cfecb5SRichard Henderson     return ret;
382e72ca652SBlue Swirl }
383e72ca652SBlue Swirl 
384e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */
385bdcfcd44SDavid Hildenbrand uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al,
386bdcfcd44SDavid Hildenbrand                       uint32_t m34)
387e72ca652SBlue Swirl {
388bdcfcd44SDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
389587626f8SRichard Henderson     float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
390bdcfcd44SDavid Hildenbrand 
391bdcfcd44SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
392bdcfcd44SDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
393d0cfecb5SRichard Henderson     return ret;
394e72ca652SBlue Swirl }
395e72ca652SBlue Swirl 
396587626f8SRichard Henderson /* 32-bit FP compare */
397587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
398e72ca652SBlue Swirl {
39971bfd65cSRichard Henderson     FloatRelation cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
400cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
401587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
402e72ca652SBlue Swirl }
403e72ca652SBlue Swirl 
404587626f8SRichard Henderson /* 64-bit FP compare */
405587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
406e72ca652SBlue Swirl {
40771bfd65cSRichard Henderson     FloatRelation cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
408cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
409587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
410e72ca652SBlue Swirl }
411e72ca652SBlue Swirl 
412587626f8SRichard Henderson /* 128-bit FP compare */
413587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
414587626f8SRichard Henderson                      uint64_t bh, uint64_t bl)
415e72ca652SBlue Swirl {
41671bfd65cSRichard Henderson     FloatRelation cmp = float128_compare_quiet(make_float128(ah, al),
417587626f8SRichard Henderson                                                make_float128(bh, bl),
418587626f8SRichard Henderson                                                &env->fpu_status);
419cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
420587626f8SRichard Henderson     return float_comp_to_cc(env, cmp);
421e72ca652SBlue Swirl }
422e72ca652SBlue Swirl 
423c0ee7015SDavid Hildenbrand int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
424e72ca652SBlue Swirl {
42568c8bd93SRichard Henderson     int ret = env->fpu_status.float_rounding_mode;
426b12b103eSDavid Hildenbrand 
427e72ca652SBlue Swirl     switch (m3) {
428e72ca652SBlue Swirl     case 0:
429e72ca652SBlue Swirl         /* current mode */
430e72ca652SBlue Swirl         break;
431e72ca652SBlue Swirl     case 1:
432b12b103eSDavid Hildenbrand         /* round to nearest with ties away from 0 */
433b12b103eSDavid Hildenbrand         set_float_rounding_mode(float_round_ties_away, &env->fpu_status);
434b12b103eSDavid Hildenbrand         break;
435b12b103eSDavid Hildenbrand     case 3:
436b12b103eSDavid Hildenbrand         /* round to prepare for shorter precision */
437b12b103eSDavid Hildenbrand         set_float_rounding_mode(float_round_to_odd, &env->fpu_status);
438b12b103eSDavid Hildenbrand         break;
439e72ca652SBlue Swirl     case 4:
440b12b103eSDavid Hildenbrand         /* round to nearest with ties to even */
441e72ca652SBlue Swirl         set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
442e72ca652SBlue Swirl         break;
443e72ca652SBlue Swirl     case 5:
444e72ca652SBlue Swirl         /* round to zero */
445e72ca652SBlue Swirl         set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
446e72ca652SBlue Swirl         break;
447e72ca652SBlue Swirl     case 6:
448e72ca652SBlue Swirl         /* round to +inf */
449e72ca652SBlue Swirl         set_float_rounding_mode(float_round_up, &env->fpu_status);
450e72ca652SBlue Swirl         break;
451e72ca652SBlue Swirl     case 7:
452e72ca652SBlue Swirl         /* round to -inf */
453e72ca652SBlue Swirl         set_float_rounding_mode(float_round_down, &env->fpu_status);
454e72ca652SBlue Swirl         break;
455b12b103eSDavid Hildenbrand     default:
456b12b103eSDavid Hildenbrand         g_assert_not_reached();
457e72ca652SBlue Swirl     }
45868c8bd93SRichard Henderson     return ret;
459e72ca652SBlue Swirl }
460e72ca652SBlue Swirl 
461c0ee7015SDavid Hildenbrand void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode)
462c0ee7015SDavid Hildenbrand {
463c0ee7015SDavid Hildenbrand     set_float_rounding_mode(old_mode, &env->fpu_status);
464c0ee7015SDavid Hildenbrand }
465c0ee7015SDavid Hildenbrand 
466683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */
467dce0a58fSDavid Hildenbrand uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m34)
468683bb9a8SRichard Henderson {
469dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
470683bb9a8SRichard Henderson     float32 ret = int64_to_float32(v2, &env->fpu_status);
471c0ee7015SDavid Hildenbrand 
472c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
473dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
474683bb9a8SRichard Henderson     return ret;
475683bb9a8SRichard Henderson }
476683bb9a8SRichard Henderson 
477683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */
478dce0a58fSDavid Hildenbrand uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
479683bb9a8SRichard Henderson {
480dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
481683bb9a8SRichard Henderson     float64 ret = int64_to_float64(v2, &env->fpu_status);
482c0ee7015SDavid Hildenbrand 
483c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
484dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
485683bb9a8SRichard Henderson     return ret;
486683bb9a8SRichard Henderson }
487683bb9a8SRichard Henderson 
488683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */
489dce0a58fSDavid Hildenbrand uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m34)
490683bb9a8SRichard Henderson {
491dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
492683bb9a8SRichard Henderson     float128 ret = int64_to_float128(v2, &env->fpu_status);
493c0ee7015SDavid Hildenbrand 
494c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
495dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
496683bb9a8SRichard Henderson     return RET128(ret);
497683bb9a8SRichard Henderson }
498683bb9a8SRichard Henderson 
4992112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */
500dce0a58fSDavid Hildenbrand uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
5012112bf1bSRichard Henderson {
502dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
5032112bf1bSRichard Henderson     float32 ret = uint64_to_float32(v2, &env->fpu_status);
504c0ee7015SDavid Hildenbrand 
505c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
506dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
5072112bf1bSRichard Henderson     return ret;
5082112bf1bSRichard Henderson }
5092112bf1bSRichard Henderson 
5102112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */
511dce0a58fSDavid Hildenbrand uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
5122112bf1bSRichard Henderson {
513dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
5142112bf1bSRichard Henderson     float64 ret = uint64_to_float64(v2, &env->fpu_status);
515c0ee7015SDavid Hildenbrand 
516c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
517dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
5182112bf1bSRichard Henderson     return ret;
5192112bf1bSRichard Henderson }
5202112bf1bSRichard Henderson 
5212112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */
522dce0a58fSDavid Hildenbrand uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
5232112bf1bSRichard Henderson {
524dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
525d2d9feacSRichard Henderson     float128 ret = uint64_to_float128(v2, &env->fpu_status);
526c0ee7015SDavid Hildenbrand 
527c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
528dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
5292112bf1bSRichard Henderson     return RET128(ret);
5302112bf1bSRichard Henderson }
5312112bf1bSRichard Henderson 
532e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */
533dce0a58fSDavid Hildenbrand uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
534e72ca652SBlue Swirl {
535dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
53668c8bd93SRichard Henderson     int64_t ret = float32_to_int64(v2, &env->fpu_status);
53728761057SUlrich Weigand     uint32_t cc = set_cc_conv_f32(v2, &env->fpu_status);
538c0ee7015SDavid Hildenbrand 
539c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
540dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
54128761057SUlrich Weigand     env->cc_op = cc;
5420a3be7beSDavid Hildenbrand     if (float32_is_any_nan(v2)) {
5430a3be7beSDavid Hildenbrand         return INT64_MIN;
5440a3be7beSDavid Hildenbrand     }
54568c8bd93SRichard Henderson     return ret;
546e72ca652SBlue Swirl }
547e72ca652SBlue Swirl 
548e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */
549dce0a58fSDavid Hildenbrand uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
550e72ca652SBlue Swirl {
551dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
55268c8bd93SRichard Henderson     int64_t ret = float64_to_int64(v2, &env->fpu_status);
55328761057SUlrich Weigand     uint32_t cc = set_cc_conv_f64(v2, &env->fpu_status);
554c0ee7015SDavid Hildenbrand 
555c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
556dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
55728761057SUlrich Weigand     env->cc_op = cc;
5580a3be7beSDavid Hildenbrand     if (float64_is_any_nan(v2)) {
5590a3be7beSDavid Hildenbrand         return INT64_MIN;
5600a3be7beSDavid Hildenbrand     }
56168c8bd93SRichard Henderson     return ret;
562e72ca652SBlue Swirl }
563e72ca652SBlue Swirl 
564e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */
565dce0a58fSDavid Hildenbrand uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
566e72ca652SBlue Swirl {
567dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
56868c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
56968c8bd93SRichard Henderson     int64_t ret = float128_to_int64(v2, &env->fpu_status);
57028761057SUlrich Weigand     uint32_t cc = set_cc_conv_f128(v2, &env->fpu_status);
571c0ee7015SDavid Hildenbrand 
572c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
573dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
57428761057SUlrich Weigand     env->cc_op = cc;
5750a3be7beSDavid Hildenbrand     if (float128_is_any_nan(v2)) {
5760a3be7beSDavid Hildenbrand         return INT64_MIN;
5770a3be7beSDavid Hildenbrand     }
57868c8bd93SRichard Henderson     return ret;
579e72ca652SBlue Swirl }
580e72ca652SBlue Swirl 
581e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */
582dce0a58fSDavid Hildenbrand uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
583e72ca652SBlue Swirl {
584dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
58568c8bd93SRichard Henderson     int32_t ret = float32_to_int32(v2, &env->fpu_status);
58628761057SUlrich Weigand     uint32_t cc = set_cc_conv_f32(v2, &env->fpu_status);
587c0ee7015SDavid Hildenbrand 
588c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
589dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
59028761057SUlrich Weigand     env->cc_op = cc;
5910a3be7beSDavid Hildenbrand     if (float32_is_any_nan(v2)) {
5920a3be7beSDavid Hildenbrand         return INT32_MIN;
5930a3be7beSDavid Hildenbrand     }
59468c8bd93SRichard Henderson     return ret;
595e72ca652SBlue Swirl }
596e72ca652SBlue Swirl 
597e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */
598dce0a58fSDavid Hildenbrand uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
599e72ca652SBlue Swirl {
600dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
60168c8bd93SRichard Henderson     int32_t ret = float64_to_int32(v2, &env->fpu_status);
60228761057SUlrich Weigand     uint32_t cc = set_cc_conv_f64(v2, &env->fpu_status);
603c0ee7015SDavid Hildenbrand 
604c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
605dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
60628761057SUlrich Weigand     env->cc_op = cc;
6070a3be7beSDavid Hildenbrand     if (float64_is_any_nan(v2)) {
6080a3be7beSDavid Hildenbrand         return INT32_MIN;
6090a3be7beSDavid Hildenbrand     }
61068c8bd93SRichard Henderson     return ret;
611e72ca652SBlue Swirl }
612e72ca652SBlue Swirl 
613e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */
614dce0a58fSDavid Hildenbrand uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
615e72ca652SBlue Swirl {
616dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
61768c8bd93SRichard Henderson     float128 v2 = make_float128(h, l);
61868c8bd93SRichard Henderson     int32_t ret = float128_to_int32(v2, &env->fpu_status);
61928761057SUlrich Weigand     uint32_t cc = set_cc_conv_f128(v2, &env->fpu_status);
620c0ee7015SDavid Hildenbrand 
621c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
622dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
62328761057SUlrich Weigand     env->cc_op = cc;
6240a3be7beSDavid Hildenbrand     if (float128_is_any_nan(v2)) {
6250a3be7beSDavid Hildenbrand         return INT32_MIN;
6260a3be7beSDavid Hildenbrand     }
62768c8bd93SRichard Henderson     return ret;
628e72ca652SBlue Swirl }
629e72ca652SBlue Swirl 
6306ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */
631dce0a58fSDavid Hildenbrand uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
6326ac1b45fSRichard Henderson {
633dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6340a3be7beSDavid Hildenbrand     uint64_t ret = float32_to_uint64(v2, &env->fpu_status);
63528761057SUlrich Weigand     uint32_t cc = set_cc_conv_f32(v2, &env->fpu_status);
63628761057SUlrich Weigand 
637c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
638dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
63928761057SUlrich Weigand     env->cc_op = cc;
6400a3be7beSDavid Hildenbrand     if (float32_is_any_nan(v2)) {
6410a3be7beSDavid Hildenbrand         return 0;
6420a3be7beSDavid Hildenbrand     }
6436ac1b45fSRichard Henderson     return ret;
6446ac1b45fSRichard Henderson }
6456ac1b45fSRichard Henderson 
6466ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */
647dce0a58fSDavid Hildenbrand uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
6486ac1b45fSRichard Henderson {
649dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6506ac1b45fSRichard Henderson     uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
65128761057SUlrich Weigand     uint32_t cc = set_cc_conv_f64(v2, &env->fpu_status);
652c0ee7015SDavid Hildenbrand 
653c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
654dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
65528761057SUlrich Weigand     env->cc_op = cc;
6560a3be7beSDavid Hildenbrand     if (float64_is_any_nan(v2)) {
6570a3be7beSDavid Hildenbrand         return 0;
6580a3be7beSDavid Hildenbrand     }
6596ac1b45fSRichard Henderson     return ret;
6606ac1b45fSRichard Henderson }
6616ac1b45fSRichard Henderson 
6626ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */
663dce0a58fSDavid Hildenbrand uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
6646ac1b45fSRichard Henderson {
665dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
66628761057SUlrich Weigand     float128 v2 = make_float128(h, l);
66728761057SUlrich Weigand     uint64_t ret = float128_to_uint64(v2, &env->fpu_status);
66828761057SUlrich Weigand     uint32_t cc = set_cc_conv_f128(v2, &env->fpu_status);
669c0ee7015SDavid Hildenbrand 
670c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
671dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
67228761057SUlrich Weigand     env->cc_op = cc;
67328761057SUlrich Weigand     if (float128_is_any_nan(v2)) {
6740a3be7beSDavid Hildenbrand         return 0;
6750a3be7beSDavid Hildenbrand     }
6766ac1b45fSRichard Henderson     return ret;
6776ac1b45fSRichard Henderson }
6786ac1b45fSRichard Henderson 
6796ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */
680dce0a58fSDavid Hildenbrand uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
6816ac1b45fSRichard Henderson {
682dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6836ac1b45fSRichard Henderson     uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
68428761057SUlrich Weigand     uint32_t cc = set_cc_conv_f32(v2, &env->fpu_status);
685c0ee7015SDavid Hildenbrand 
686c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
687dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
68828761057SUlrich Weigand     env->cc_op = cc;
6890a3be7beSDavid Hildenbrand     if (float32_is_any_nan(v2)) {
6900a3be7beSDavid Hildenbrand         return 0;
6910a3be7beSDavid Hildenbrand     }
6926ac1b45fSRichard Henderson     return ret;
6936ac1b45fSRichard Henderson }
6946ac1b45fSRichard Henderson 
6956ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */
696dce0a58fSDavid Hildenbrand uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34)
6976ac1b45fSRichard Henderson {
698dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
6996ac1b45fSRichard Henderson     uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
70028761057SUlrich Weigand     uint32_t cc = set_cc_conv_f64(v2, &env->fpu_status);
701c0ee7015SDavid Hildenbrand 
702c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
703dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
70428761057SUlrich Weigand     env->cc_op = cc;
7050a3be7beSDavid Hildenbrand     if (float64_is_any_nan(v2)) {
7060a3be7beSDavid Hildenbrand         return 0;
7070a3be7beSDavid Hildenbrand     }
7086ac1b45fSRichard Henderson     return ret;
7096ac1b45fSRichard Henderson }
7106ac1b45fSRichard Henderson 
7116ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */
712dce0a58fSDavid Hildenbrand uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34)
7136ac1b45fSRichard Henderson {
714dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
71528761057SUlrich Weigand     float128 v2 = make_float128(h, l);
71628761057SUlrich Weigand     uint32_t ret = float128_to_uint32(v2, &env->fpu_status);
71728761057SUlrich Weigand     uint32_t cc = set_cc_conv_f128(v2, &env->fpu_status);
718c0ee7015SDavid Hildenbrand 
719c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
720dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
72128761057SUlrich Weigand     env->cc_op = cc;
72228761057SUlrich Weigand     if (float128_is_any_nan(v2)) {
7230a3be7beSDavid Hildenbrand         return 0;
7240a3be7beSDavid Hildenbrand     }
7256ac1b45fSRichard Henderson     return ret;
7266ac1b45fSRichard Henderson }
7276ac1b45fSRichard Henderson 
728ed0bceceSAurelien Jarno /* round to integer 32-bit */
729dce0a58fSDavid Hildenbrand uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
730ed0bceceSAurelien Jarno {
731dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
732ed0bceceSAurelien Jarno     float32 ret = float32_round_to_int(f2, &env->fpu_status);
733c0ee7015SDavid Hildenbrand 
734c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
735dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
736ed0bceceSAurelien Jarno     return ret;
737ed0bceceSAurelien Jarno }
738ed0bceceSAurelien Jarno 
739ed0bceceSAurelien Jarno /* round to integer 64-bit */
740dce0a58fSDavid Hildenbrand uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m34)
741ed0bceceSAurelien Jarno {
742dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
743ed0bceceSAurelien Jarno     float64 ret = float64_round_to_int(f2, &env->fpu_status);
744c0ee7015SDavid Hildenbrand 
745c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
746dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
747ed0bceceSAurelien Jarno     return ret;
748ed0bceceSAurelien Jarno }
749ed0bceceSAurelien Jarno 
750ed0bceceSAurelien Jarno /* round to integer 128-bit */
751dce0a58fSDavid Hildenbrand uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al,
752dce0a58fSDavid Hildenbrand                       uint32_t m34)
753ed0bceceSAurelien Jarno {
754dce0a58fSDavid Hildenbrand     int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34));
755ed0bceceSAurelien Jarno     float128 ret = float128_round_to_int(make_float128(ah, al),
756ed0bceceSAurelien Jarno                                          &env->fpu_status);
757cf97f9ffSDavid Hildenbrand 
758c0ee7015SDavid Hildenbrand     s390_restore_bfp_rounding_mode(env, old_mode);
759dce0a58fSDavid Hildenbrand     handle_exceptions(env, xxc_from_m34(m34), GETPC());
760ed0bceceSAurelien Jarno     return RET128(ret);
761ed0bceceSAurelien Jarno }
762ed0bceceSAurelien Jarno 
7639c8be598SAurelien Jarno /* 32-bit FP compare and signal */
7649c8be598SAurelien Jarno uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
7659c8be598SAurelien Jarno {
76671bfd65cSRichard Henderson     FloatRelation cmp = float32_compare(f1, f2, &env->fpu_status);
767cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
7689c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
7699c8be598SAurelien Jarno }
7709c8be598SAurelien Jarno 
7719c8be598SAurelien Jarno /* 64-bit FP compare and signal */
7729c8be598SAurelien Jarno uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
7739c8be598SAurelien Jarno {
77471bfd65cSRichard Henderson     FloatRelation cmp = float64_compare(f1, f2, &env->fpu_status);
775cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
7769c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
7779c8be598SAurelien Jarno }
7789c8be598SAurelien Jarno 
7799c8be598SAurelien Jarno /* 128-bit FP compare and signal */
7809c8be598SAurelien Jarno uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
7819c8be598SAurelien Jarno                      uint64_t bh, uint64_t bl)
7829c8be598SAurelien Jarno {
78371bfd65cSRichard Henderson     FloatRelation cmp = float128_compare(make_float128(ah, al),
7849c8be598SAurelien Jarno                                          make_float128(bh, bl),
7859c8be598SAurelien Jarno                                          &env->fpu_status);
786cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
7879c8be598SAurelien Jarno     return float_comp_to_cc(env, cmp);
7889c8be598SAurelien Jarno }
7899c8be598SAurelien Jarno 
790722bfec3SRichard Henderson /* 32-bit FP multiply and add */
791722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
792722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
793e72ca652SBlue Swirl {
794722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
795cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
796722bfec3SRichard Henderson     return ret;
797722bfec3SRichard Henderson }
798e72ca652SBlue Swirl 
799722bfec3SRichard Henderson /* 64-bit FP multiply and add */
800722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
801722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
802722bfec3SRichard Henderson {
803722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
804cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
805722bfec3SRichard Henderson     return ret;
806722bfec3SRichard Henderson }
807722bfec3SRichard Henderson 
808722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */
809722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
810722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
811722bfec3SRichard Henderson {
812722bfec3SRichard Henderson     float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
813e72ca652SBlue Swirl                                  &env->fpu_status);
814cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
815722bfec3SRichard Henderson     return ret;
816e72ca652SBlue Swirl }
817e72ca652SBlue Swirl 
818722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */
819722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
820722bfec3SRichard Henderson                       uint64_t f2, uint64_t f3)
821e72ca652SBlue Swirl {
822722bfec3SRichard Henderson     float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
823e72ca652SBlue Swirl                                  &env->fpu_status);
824cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
825722bfec3SRichard Henderson     return ret;
826e72ca652SBlue Swirl }
827e72ca652SBlue Swirl 
828fc7cc951SDavid Hildenbrand /* The rightmost bit has the number 11. */
829fc7cc951SDavid Hildenbrand static inline uint16_t dcmask(int bit, bool neg)
830fc7cc951SDavid Hildenbrand {
831fc7cc951SDavid Hildenbrand     return 1 << (11 - bit - neg);
832fc7cc951SDavid Hildenbrand }
833fc7cc951SDavid Hildenbrand 
834fc7cc951SDavid Hildenbrand #define DEF_FLOAT_DCMASK(_TYPE) \
835aae65009SDavid Hildenbrand uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1)              \
836fc7cc951SDavid Hildenbrand {                                                                  \
837fc7cc951SDavid Hildenbrand     const bool neg = _TYPE##_is_neg(f1);                           \
838fc7cc951SDavid Hildenbrand                                                                    \
839fc7cc951SDavid Hildenbrand     /* Sorted by most common cases - only one class is possible */ \
840fc7cc951SDavid Hildenbrand     if (_TYPE##_is_normal(f1)) {                                   \
841fc7cc951SDavid Hildenbrand         return dcmask(2, neg);                                     \
842fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_zero(f1)) {                              \
843fc7cc951SDavid Hildenbrand         return dcmask(0, neg);                                     \
844fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_denormal(f1)) {                          \
845fc7cc951SDavid Hildenbrand         return dcmask(4, neg);                                     \
846fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_infinity(f1)) {                          \
847fc7cc951SDavid Hildenbrand         return dcmask(6, neg);                                     \
848fc7cc951SDavid Hildenbrand     } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) {       \
849fc7cc951SDavid Hildenbrand         return dcmask(8, neg);                                     \
850fc7cc951SDavid Hildenbrand     }                                                              \
851fc7cc951SDavid Hildenbrand     /* signaling nan, as last remaining case */                    \
852fc7cc951SDavid Hildenbrand     return dcmask(10, neg);                                        \
853fc7cc951SDavid Hildenbrand }
854fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float32)
855fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float64)
856fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float128)
857fc7cc951SDavid Hildenbrand 
858e72ca652SBlue Swirl /* test data class 32-bit */
859af39bc8cSAleksandar Markovic uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
860e72ca652SBlue Swirl {
861fc7cc951SDavid Hildenbrand     return (m2 & float32_dcmask(env, f1)) != 0;
862e72ca652SBlue Swirl }
863e72ca652SBlue Swirl 
864e72ca652SBlue Swirl /* test data class 64-bit */
865af39bc8cSAleksandar Markovic uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
866e72ca652SBlue Swirl {
867fc7cc951SDavid Hildenbrand     return (m2 & float64_dcmask(env, v1)) != 0;
868e72ca652SBlue Swirl }
869e72ca652SBlue Swirl 
870e72ca652SBlue Swirl /* test data class 128-bit */
871fc7cc951SDavid Hildenbrand uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2)
872e72ca652SBlue Swirl {
873fc7cc951SDavid Hildenbrand     return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0;
874e72ca652SBlue Swirl }
875e72ca652SBlue Swirl 
87616d7b2a4SRichard Henderson /* square root 32-bit */
87716d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
878e72ca652SBlue Swirl {
87916d7b2a4SRichard Henderson     float32 ret = float32_sqrt(f2, &env->fpu_status);
880cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
88116d7b2a4SRichard Henderson     return ret;
88216d7b2a4SRichard Henderson }
88316d7b2a4SRichard Henderson 
88416d7b2a4SRichard Henderson /* square root 64-bit */
88516d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
88616d7b2a4SRichard Henderson {
88716d7b2a4SRichard Henderson     float64 ret = float64_sqrt(f2, &env->fpu_status);
888cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
88916d7b2a4SRichard Henderson     return ret;
89016d7b2a4SRichard Henderson }
89116d7b2a4SRichard Henderson 
89216d7b2a4SRichard Henderson /* square root 128-bit */
89316d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
89416d7b2a4SRichard Henderson {
89516d7b2a4SRichard Henderson     float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
896cf97f9ffSDavid Hildenbrand     handle_exceptions(env, false, GETPC());
89716d7b2a4SRichard Henderson     return RET128(ret);
898e72ca652SBlue Swirl }
8998379bfdbSRichard Henderson 
9002aea83c6SDavid Hildenbrand static const int fpc_to_rnd[8] = {
9018379bfdbSRichard Henderson     float_round_nearest_even,
9028379bfdbSRichard Henderson     float_round_to_zero,
9038379bfdbSRichard Henderson     float_round_up,
9042aea83c6SDavid Hildenbrand     float_round_down,
9052aea83c6SDavid Hildenbrand     -1,
9062aea83c6SDavid Hildenbrand     -1,
9072aea83c6SDavid Hildenbrand     -1,
9082aea83c6SDavid Hildenbrand     float_round_to_odd,
9098379bfdbSRichard Henderson };
9108379bfdbSRichard Henderson 
911411edc22SRichard Henderson /* set fpc */
912411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
913411edc22SRichard Henderson {
9142aea83c6SDavid Hildenbrand     if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
9152aea83c6SDavid Hildenbrand         (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
9161e36aee6SRichard Henderson         tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
9172aea83c6SDavid Hildenbrand     }
9182aea83c6SDavid Hildenbrand 
9198379bfdbSRichard Henderson     /* Install everything in the main FPC.  */
9208379bfdbSRichard Henderson     env->fpc = fpc;
9218379bfdbSRichard Henderson 
9228379bfdbSRichard Henderson     /* Install the rounding mode in the shadow fpu_status.  */
9232aea83c6SDavid Hildenbrand     set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
924411edc22SRichard Henderson }
925411edc22SRichard Henderson 
926411edc22SRichard Henderson /* set fpc and signal */
927f66a0ecfSDavid Hildenbrand void HELPER(sfas)(CPUS390XState *env, uint64_t fpc)
928411edc22SRichard Henderson {
929411edc22SRichard Henderson     uint32_t signalling = env->fpc;
930411edc22SRichard Henderson     uint32_t s390_exc;
931411edc22SRichard Henderson 
9322aea83c6SDavid Hildenbrand     if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u ||
9332aea83c6SDavid Hildenbrand         (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
9341e36aee6SRichard Henderson         tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
9352aea83c6SDavid Hildenbrand     }
9362aea83c6SDavid Hildenbrand 
937f66a0ecfSDavid Hildenbrand     /*
938f66a0ecfSDavid Hildenbrand      * FPC is set to the FPC operand with a bitwise OR of the signalling
939f66a0ecfSDavid Hildenbrand      * flags.
940f66a0ecfSDavid Hildenbrand      */
941f66a0ecfSDavid Hildenbrand     env->fpc = fpc | (signalling & 0x00ff0000);
9422aea83c6SDavid Hildenbrand     set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
943411edc22SRichard Henderson 
944f66a0ecfSDavid Hildenbrand     /*
945f66a0ecfSDavid Hildenbrand      * If any signaling flag is enabled in the new FPC mask, a
946f66a0ecfSDavid Hildenbrand      * simulated-iee-exception exception occurs.
947f66a0ecfSDavid Hildenbrand      */
948f66a0ecfSDavid Hildenbrand     s390_exc = (signalling >> 16) & (fpc >> 24);
949411edc22SRichard Henderson     if (s390_exc) {
9508772bbe4SDavid Hildenbrand         if (s390_exc & S390_IEEE_MASK_INVALID) {
9518772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_INVALID;
9528772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) {
9538772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_DIVBYZERO;
9548772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) {
9558772bbe4SDavid Hildenbrand             s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT);
9568772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) {
9578772bbe4SDavid Hildenbrand             s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT);
9588772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_INEXACT) {
9598772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_INEXACT;
9608772bbe4SDavid Hildenbrand         } else if (s390_exc & S390_IEEE_MASK_QUANTUM) {
9618772bbe4SDavid Hildenbrand             s390_exc = S390_IEEE_MASK_QUANTUM;
9628772bbe4SDavid Hildenbrand         }
963bbf6ea3bSDavid Hildenbrand         tcg_s390_data_exception(env, s390_exc | 3, GETPC());
964411edc22SRichard Henderson     }
9658379bfdbSRichard Henderson }
966b9c737f5SDavid Hildenbrand 
967b9c737f5SDavid Hildenbrand /* set bfp rounding mode */
968b9c737f5SDavid Hildenbrand void HELPER(srnm)(CPUS390XState *env, uint64_t rnd)
969b9c737f5SDavid Hildenbrand {
970b9c737f5SDavid Hildenbrand     if (rnd > 0x7 || fpc_to_rnd[rnd & 0x7] == -1) {
9711e36aee6SRichard Henderson         tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
972b9c737f5SDavid Hildenbrand     }
973b9c737f5SDavid Hildenbrand 
974b9c737f5SDavid Hildenbrand     env->fpc = deposit32(env->fpc, 0, 3, rnd);
975b9c737f5SDavid Hildenbrand     set_float_rounding_mode(fpc_to_rnd[rnd & 0x7], &env->fpu_status);
976b9c737f5SDavid Hildenbrand }
977