1e72ca652SBlue Swirl /* 2e72ca652SBlue Swirl * S/390 FPU helper routines 3e72ca652SBlue Swirl * 4e72ca652SBlue Swirl * Copyright (c) 2009 Ulrich Hecht 5e72ca652SBlue Swirl * Copyright (c) 2009 Alexander Graf 6e72ca652SBlue Swirl * 7e72ca652SBlue Swirl * This library is free software; you can redistribute it and/or 8e72ca652SBlue Swirl * modify it under the terms of the GNU Lesser General Public 9e72ca652SBlue Swirl * License as published by the Free Software Foundation; either 1041c6a6ddSThomas Huth * version 2.1 of the License, or (at your option) any later version. 11e72ca652SBlue Swirl * 12e72ca652SBlue Swirl * This library is distributed in the hope that it will be useful, 13e72ca652SBlue Swirl * but WITHOUT ANY WARRANTY; without even the implied warranty of 14e72ca652SBlue Swirl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15e72ca652SBlue Swirl * Lesser General Public License for more details. 16e72ca652SBlue Swirl * 17e72ca652SBlue Swirl * You should have received a copy of the GNU Lesser General Public 18e72ca652SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19e72ca652SBlue Swirl */ 20e72ca652SBlue Swirl 219615495aSPeter Maydell #include "qemu/osdep.h" 22e72ca652SBlue Swirl #include "cpu.h" 234e58b838SDavid Hildenbrand #include "internal.h" 24bbf6ea3bSDavid Hildenbrand #include "tcg_s390x.h" 2563c91552SPaolo Bonzini #include "exec/exec-all.h" 26f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h" 272ef6175aSRichard Henderson #include "exec/helper-proto.h" 2824f91e81SAlex Bennée #include "fpu/softfloat.h" 29e72ca652SBlue Swirl 30e72ca652SBlue Swirl /* #define DEBUG_HELPER */ 31e72ca652SBlue Swirl #ifdef DEBUG_HELPER 32e72ca652SBlue Swirl #define HELPER_LOG(x...) qemu_log(x) 33e72ca652SBlue Swirl #else 34e72ca652SBlue Swirl #define HELPER_LOG(x...) 35e72ca652SBlue Swirl #endif 36e72ca652SBlue Swirl 37587626f8SRichard Henderson #define RET128(F) (env->retxl = F.low, F.high) 38587626f8SRichard Henderson 394b70fc54SDavid Hildenbrand uint8_t s390_softfloat_exc_to_ieee(unsigned int exc) 404b70fc54SDavid Hildenbrand { 414b70fc54SDavid Hildenbrand uint8_t s390_exc = 0; 424b70fc54SDavid Hildenbrand 434b70fc54SDavid Hildenbrand s390_exc |= (exc & float_flag_invalid) ? S390_IEEE_MASK_INVALID : 0; 444b70fc54SDavid Hildenbrand s390_exc |= (exc & float_flag_divbyzero) ? S390_IEEE_MASK_DIVBYZERO : 0; 454b70fc54SDavid Hildenbrand s390_exc |= (exc & float_flag_overflow) ? S390_IEEE_MASK_OVERFLOW : 0; 464b70fc54SDavid Hildenbrand s390_exc |= (exc & float_flag_underflow) ? S390_IEEE_MASK_UNDERFLOW : 0; 474b70fc54SDavid Hildenbrand s390_exc |= (exc & float_flag_inexact) ? S390_IEEE_MASK_INEXACT : 0; 484b70fc54SDavid Hildenbrand 494b70fc54SDavid Hildenbrand return s390_exc; 504b70fc54SDavid Hildenbrand } 51587626f8SRichard Henderson 52587626f8SRichard Henderson /* Should be called after any operation that may raise IEEE exceptions. */ 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 92fcb9e9f2SDavid Hildenbrand * handle it separatly. 93fcb9e9f2SDavid Hildenbrand */ 94fcb9e9f2SDavid Hildenbrand if (s390_exc & ~S390_IEEE_MASK_INEXACT) { 95fcb9e9f2SDavid Hildenbrand if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) { 96fcb9e9f2SDavid Hildenbrand /* trap condition - inexact reported along */ 97bbf6ea3bSDavid Hildenbrand tcg_s390_data_exception(env, s390_exc, retaddr); 98587626f8SRichard Henderson } 99fcb9e9f2SDavid Hildenbrand /* nontrap condition - inexact handled differently */ 100fcb9e9f2SDavid Hildenbrand env->fpc |= (s390_exc & ~S390_IEEE_MASK_INEXACT) << 16; 101fcb9e9f2SDavid Hildenbrand } 102fcb9e9f2SDavid Hildenbrand 103fcb9e9f2SDavid Hildenbrand /* inexact handling */ 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 115449c0d70SBlue Swirl static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) 116e72ca652SBlue Swirl { 117a47dddd7SAndreas Färber S390CPU *cpu = s390_env_get_cpu(env); 118a47dddd7SAndreas Färber 119e72ca652SBlue Swirl switch (float_compare) { 120e72ca652SBlue Swirl case float_relation_equal: 121e72ca652SBlue Swirl return 0; 122e72ca652SBlue Swirl case float_relation_less: 123e72ca652SBlue Swirl return 1; 124e72ca652SBlue Swirl case float_relation_greater: 125e72ca652SBlue Swirl return 2; 126e72ca652SBlue Swirl case float_relation_unordered: 127e72ca652SBlue Swirl return 3; 128e72ca652SBlue Swirl default: 129a47dddd7SAndreas Färber cpu_abort(CPU(cpu), "unknown return value for float compare\n"); 130e72ca652SBlue Swirl } 131e72ca652SBlue Swirl } 132e72ca652SBlue Swirl 133e72ca652SBlue Swirl /* condition codes for unary FP ops */ 134e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v) 135e72ca652SBlue Swirl { 136e72ca652SBlue Swirl if (float32_is_any_nan(v)) { 137e72ca652SBlue Swirl return 3; 138e72ca652SBlue Swirl } else if (float32_is_zero(v)) { 139e72ca652SBlue Swirl return 0; 140e72ca652SBlue Swirl } else if (float32_is_neg(v)) { 141e72ca652SBlue Swirl return 1; 142e72ca652SBlue Swirl } else { 143e72ca652SBlue Swirl return 2; 144e72ca652SBlue Swirl } 145e72ca652SBlue Swirl } 146e72ca652SBlue Swirl 147e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v) 148e72ca652SBlue Swirl { 149e72ca652SBlue Swirl if (float64_is_any_nan(v)) { 150e72ca652SBlue Swirl return 3; 151e72ca652SBlue Swirl } else if (float64_is_zero(v)) { 152e72ca652SBlue Swirl return 0; 153e72ca652SBlue Swirl } else if (float64_is_neg(v)) { 154e72ca652SBlue Swirl return 1; 155e72ca652SBlue Swirl } else { 156e72ca652SBlue Swirl return 2; 157e72ca652SBlue Swirl } 158e72ca652SBlue Swirl } 159e72ca652SBlue Swirl 160587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v) 161e72ca652SBlue Swirl { 162e72ca652SBlue Swirl if (float128_is_any_nan(v)) { 163e72ca652SBlue Swirl return 3; 164e72ca652SBlue Swirl } else if (float128_is_zero(v)) { 165e72ca652SBlue Swirl return 0; 166e72ca652SBlue Swirl } else if (float128_is_neg(v)) { 167e72ca652SBlue Swirl return 1; 168e72ca652SBlue Swirl } else { 169e72ca652SBlue Swirl return 2; 170e72ca652SBlue Swirl } 171e72ca652SBlue Swirl } 172e72ca652SBlue Swirl 173dce0a58fSDavid Hildenbrand static inline uint8_t round_from_m34(uint32_t m34) 174dce0a58fSDavid Hildenbrand { 175dce0a58fSDavid Hildenbrand return extract32(m34, 0, 4); 176dce0a58fSDavid Hildenbrand } 177dce0a58fSDavid Hildenbrand 178dce0a58fSDavid Hildenbrand static inline bool xxc_from_m34(uint32_t m34) 179dce0a58fSDavid Hildenbrand { 180dce0a58fSDavid Hildenbrand /* XxC is bit 1 of m4 */ 181dce0a58fSDavid Hildenbrand return extract32(m34, 4 + 3 - 1, 1); 182dce0a58fSDavid Hildenbrand } 183dce0a58fSDavid Hildenbrand 184587626f8SRichard Henderson /* 32-bit FP addition */ 185587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 186e72ca652SBlue Swirl { 187587626f8SRichard Henderson float32 ret = float32_add(f1, f2, &env->fpu_status); 188cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 189587626f8SRichard Henderson return ret; 190e72ca652SBlue Swirl } 191e72ca652SBlue Swirl 192587626f8SRichard Henderson /* 64-bit FP addition */ 193587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 194e72ca652SBlue Swirl { 195587626f8SRichard Henderson float64 ret = float64_add(f1, f2, &env->fpu_status); 196cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 197587626f8SRichard Henderson return ret; 198587626f8SRichard Henderson } 199e72ca652SBlue Swirl 200587626f8SRichard Henderson /* 128-bit FP addition */ 201587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al, 202587626f8SRichard Henderson uint64_t bh, uint64_t bl) 203587626f8SRichard Henderson { 204587626f8SRichard Henderson float128 ret = float128_add(make_float128(ah, al), 205587626f8SRichard Henderson make_float128(bh, bl), 206587626f8SRichard Henderson &env->fpu_status); 207cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 208587626f8SRichard Henderson return RET128(ret); 209e72ca652SBlue Swirl } 210e72ca652SBlue Swirl 2111a800a2dSRichard Henderson /* 32-bit FP subtraction */ 2121a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 213e72ca652SBlue Swirl { 2141a800a2dSRichard Henderson float32 ret = float32_sub(f1, f2, &env->fpu_status); 215cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 2161a800a2dSRichard Henderson return ret; 217e72ca652SBlue Swirl } 218e72ca652SBlue Swirl 2191a800a2dSRichard Henderson /* 64-bit FP subtraction */ 2201a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 221e72ca652SBlue Swirl { 2221a800a2dSRichard Henderson float64 ret = float64_sub(f1, f2, &env->fpu_status); 223cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 2241a800a2dSRichard Henderson return ret; 2251a800a2dSRichard Henderson } 226e72ca652SBlue Swirl 2271a800a2dSRichard Henderson /* 128-bit FP subtraction */ 2281a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 2291a800a2dSRichard Henderson uint64_t bh, uint64_t bl) 2301a800a2dSRichard Henderson { 2311a800a2dSRichard Henderson float128 ret = float128_sub(make_float128(ah, al), 2321a800a2dSRichard Henderson make_float128(bh, bl), 2331a800a2dSRichard Henderson &env->fpu_status); 234cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 2351a800a2dSRichard Henderson return RET128(ret); 236e72ca652SBlue Swirl } 237e72ca652SBlue Swirl 238f08a5c31SRichard Henderson /* 32-bit FP division */ 239f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 240e72ca652SBlue Swirl { 241f08a5c31SRichard Henderson float32 ret = float32_div(f1, f2, &env->fpu_status); 242cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 243f08a5c31SRichard Henderson return ret; 244e72ca652SBlue Swirl } 245e72ca652SBlue Swirl 246f08a5c31SRichard Henderson /* 64-bit FP division */ 247f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 248e72ca652SBlue Swirl { 249f08a5c31SRichard Henderson float64 ret = float64_div(f1, f2, &env->fpu_status); 250cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 251f08a5c31SRichard Henderson return ret; 252f08a5c31SRichard Henderson } 253e72ca652SBlue Swirl 254f08a5c31SRichard Henderson /* 128-bit FP division */ 255f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 256f08a5c31SRichard Henderson uint64_t bh, uint64_t bl) 257f08a5c31SRichard Henderson { 258f08a5c31SRichard Henderson float128 ret = float128_div(make_float128(ah, al), 259f08a5c31SRichard Henderson make_float128(bh, bl), 260f08a5c31SRichard Henderson &env->fpu_status); 261cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 262f08a5c31SRichard Henderson return RET128(ret); 263e72ca652SBlue Swirl } 264e72ca652SBlue Swirl 26583b00736SRichard Henderson /* 32-bit FP multiplication */ 26683b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 267e72ca652SBlue Swirl { 26883b00736SRichard Henderson float32 ret = float32_mul(f1, f2, &env->fpu_status); 269cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 27083b00736SRichard Henderson return ret; 271e72ca652SBlue Swirl } 272e72ca652SBlue Swirl 27383b00736SRichard Henderson /* 64-bit FP multiplication */ 27483b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 275e72ca652SBlue Swirl { 27683b00736SRichard Henderson float64 ret = float64_mul(f1, f2, &env->fpu_status); 277cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 27883b00736SRichard Henderson return ret; 27983b00736SRichard Henderson } 280e72ca652SBlue Swirl 28183b00736SRichard Henderson /* 64/32-bit FP multiplication */ 28283b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 28383b00736SRichard Henderson { 28483b00736SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 28583b00736SRichard Henderson ret = float64_mul(f1, ret, &env->fpu_status); 286cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 28783b00736SRichard Henderson return ret; 28883b00736SRichard Henderson } 28983b00736SRichard Henderson 29083b00736SRichard Henderson /* 128-bit FP multiplication */ 29183b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 29283b00736SRichard Henderson uint64_t bh, uint64_t bl) 29383b00736SRichard Henderson { 29483b00736SRichard Henderson float128 ret = float128_mul(make_float128(ah, al), 29583b00736SRichard Henderson make_float128(bh, bl), 29683b00736SRichard Henderson &env->fpu_status); 297cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 29883b00736SRichard Henderson return RET128(ret); 29983b00736SRichard Henderson } 30083b00736SRichard Henderson 30183b00736SRichard Henderson /* 128/64-bit FP multiplication */ 30283b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al, 30383b00736SRichard Henderson uint64_t f2) 30483b00736SRichard Henderson { 30583b00736SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 30683b00736SRichard Henderson ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status); 307cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 30883b00736SRichard Henderson return RET128(ret); 309e72ca652SBlue Swirl } 310e72ca652SBlue Swirl 311e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */ 312587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2) 313e72ca652SBlue Swirl { 314587626f8SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 315cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 316d0cfecb5SRichard Henderson return ret; 317e72ca652SBlue Swirl } 318e72ca652SBlue Swirl 319e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */ 320*bdcfcd44SDavid Hildenbrand uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 321*bdcfcd44SDavid Hildenbrand uint32_t m34) 322e72ca652SBlue Swirl { 323*bdcfcd44SDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 324587626f8SRichard Henderson float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); 325*bdcfcd44SDavid Hildenbrand 326*bdcfcd44SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 327*bdcfcd44SDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 328d0cfecb5SRichard Henderson return ret; 329e72ca652SBlue Swirl } 330e72ca652SBlue Swirl 331e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */ 332587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) 333e72ca652SBlue Swirl { 334587626f8SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 335cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 336d0cfecb5SRichard Henderson return RET128(ret); 337587626f8SRichard Henderson } 338e72ca652SBlue Swirl 339587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */ 340587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) 341587626f8SRichard Henderson { 342587626f8SRichard Henderson float128 ret = float32_to_float128(f2, &env->fpu_status); 343cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 344d0cfecb5SRichard Henderson return RET128(ret); 345e72ca652SBlue Swirl } 346e72ca652SBlue Swirl 347e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */ 348*bdcfcd44SDavid Hildenbrand uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2, uint32_t m34) 349e72ca652SBlue Swirl { 350*bdcfcd44SDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 351587626f8SRichard Henderson float32 ret = float64_to_float32(f2, &env->fpu_status); 352*bdcfcd44SDavid Hildenbrand 353*bdcfcd44SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 354*bdcfcd44SDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 355d0cfecb5SRichard Henderson return ret; 356e72ca652SBlue Swirl } 357e72ca652SBlue Swirl 358e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */ 359*bdcfcd44SDavid Hildenbrand uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al, 360*bdcfcd44SDavid Hildenbrand uint32_t m34) 361e72ca652SBlue Swirl { 362*bdcfcd44SDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 363587626f8SRichard Henderson float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); 364*bdcfcd44SDavid Hildenbrand 365*bdcfcd44SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 366*bdcfcd44SDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 367d0cfecb5SRichard Henderson return ret; 368e72ca652SBlue Swirl } 369e72ca652SBlue Swirl 370587626f8SRichard Henderson /* 32-bit FP compare */ 371587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 372e72ca652SBlue Swirl { 373587626f8SRichard Henderson int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); 374cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 375587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 376e72ca652SBlue Swirl } 377e72ca652SBlue Swirl 378587626f8SRichard Henderson /* 64-bit FP compare */ 379587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 380e72ca652SBlue Swirl { 381587626f8SRichard Henderson int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); 382cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 383587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 384e72ca652SBlue Swirl } 385e72ca652SBlue Swirl 386587626f8SRichard Henderson /* 128-bit FP compare */ 387587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 388587626f8SRichard Henderson uint64_t bh, uint64_t bl) 389e72ca652SBlue Swirl { 390587626f8SRichard Henderson int cmp = float128_compare_quiet(make_float128(ah, al), 391587626f8SRichard Henderson make_float128(bh, bl), 392587626f8SRichard Henderson &env->fpu_status); 393cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 394587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 395e72ca652SBlue Swirl } 396e72ca652SBlue Swirl 397c0ee7015SDavid Hildenbrand int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3) 398e72ca652SBlue Swirl { 39968c8bd93SRichard Henderson int ret = env->fpu_status.float_rounding_mode; 400e72ca652SBlue Swirl switch (m3) { 401e72ca652SBlue Swirl case 0: 402e72ca652SBlue Swirl /* current mode */ 403e72ca652SBlue Swirl break; 404e72ca652SBlue Swirl case 1: 405e72ca652SBlue Swirl /* biased round no nearest */ 406e72ca652SBlue Swirl case 4: 407e72ca652SBlue Swirl /* round to nearest */ 408e72ca652SBlue Swirl set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); 409e72ca652SBlue Swirl break; 410e72ca652SBlue Swirl case 5: 411e72ca652SBlue Swirl /* round to zero */ 412e72ca652SBlue Swirl set_float_rounding_mode(float_round_to_zero, &env->fpu_status); 413e72ca652SBlue Swirl break; 414e72ca652SBlue Swirl case 6: 415e72ca652SBlue Swirl /* round to +inf */ 416e72ca652SBlue Swirl set_float_rounding_mode(float_round_up, &env->fpu_status); 417e72ca652SBlue Swirl break; 418e72ca652SBlue Swirl case 7: 419e72ca652SBlue Swirl /* round to -inf */ 420e72ca652SBlue Swirl set_float_rounding_mode(float_round_down, &env->fpu_status); 421e72ca652SBlue Swirl break; 422e72ca652SBlue Swirl } 42368c8bd93SRichard Henderson return ret; 424e72ca652SBlue Swirl } 425e72ca652SBlue Swirl 426c0ee7015SDavid Hildenbrand void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode) 427c0ee7015SDavid Hildenbrand { 428c0ee7015SDavid Hildenbrand set_float_rounding_mode(old_mode, &env->fpu_status); 429c0ee7015SDavid Hildenbrand } 430c0ee7015SDavid Hildenbrand 431683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */ 432dce0a58fSDavid Hildenbrand uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m34) 433683bb9a8SRichard Henderson { 434dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 435683bb9a8SRichard Henderson float32 ret = int64_to_float32(v2, &env->fpu_status); 436c0ee7015SDavid Hildenbrand 437c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 438dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 439683bb9a8SRichard Henderson return ret; 440683bb9a8SRichard Henderson } 441683bb9a8SRichard Henderson 442683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */ 443dce0a58fSDavid Hildenbrand uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m34) 444683bb9a8SRichard Henderson { 445dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 446683bb9a8SRichard Henderson float64 ret = int64_to_float64(v2, &env->fpu_status); 447c0ee7015SDavid Hildenbrand 448c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 449dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 450683bb9a8SRichard Henderson return ret; 451683bb9a8SRichard Henderson } 452683bb9a8SRichard Henderson 453683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */ 454dce0a58fSDavid Hildenbrand uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m34) 455683bb9a8SRichard Henderson { 456dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 457683bb9a8SRichard Henderson float128 ret = int64_to_float128(v2, &env->fpu_status); 458c0ee7015SDavid Hildenbrand 459c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 460dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 461683bb9a8SRichard Henderson return RET128(ret); 462683bb9a8SRichard Henderson } 463683bb9a8SRichard Henderson 4642112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */ 465dce0a58fSDavid Hildenbrand uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 4662112bf1bSRichard Henderson { 467dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 4682112bf1bSRichard Henderson float32 ret = uint64_to_float32(v2, &env->fpu_status); 469c0ee7015SDavid Hildenbrand 470c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 471dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 4722112bf1bSRichard Henderson return ret; 4732112bf1bSRichard Henderson } 4742112bf1bSRichard Henderson 4752112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */ 476dce0a58fSDavid Hildenbrand uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 4772112bf1bSRichard Henderson { 478dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 4792112bf1bSRichard Henderson float64 ret = uint64_to_float64(v2, &env->fpu_status); 480c0ee7015SDavid Hildenbrand 481c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 482dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 4832112bf1bSRichard Henderson return ret; 4842112bf1bSRichard Henderson } 4852112bf1bSRichard Henderson 4862112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */ 487dce0a58fSDavid Hildenbrand uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 4882112bf1bSRichard Henderson { 489dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 490d2d9feacSRichard Henderson float128 ret = uint64_to_float128(v2, &env->fpu_status); 491c0ee7015SDavid Hildenbrand 492c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 493dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 4942112bf1bSRichard Henderson return RET128(ret); 4952112bf1bSRichard Henderson } 4962112bf1bSRichard Henderson 497e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */ 498dce0a58fSDavid Hildenbrand uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 499e72ca652SBlue Swirl { 500dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 50168c8bd93SRichard Henderson int64_t ret = float32_to_int64(v2, &env->fpu_status); 502c0ee7015SDavid Hildenbrand 503c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 504dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 50568c8bd93SRichard Henderson return ret; 506e72ca652SBlue Swirl } 507e72ca652SBlue Swirl 508e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */ 509dce0a58fSDavid Hildenbrand uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 510e72ca652SBlue Swirl { 511dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 51268c8bd93SRichard Henderson int64_t ret = float64_to_int64(v2, &env->fpu_status); 513c0ee7015SDavid Hildenbrand 514c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 515dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 51668c8bd93SRichard Henderson return ret; 517e72ca652SBlue Swirl } 518e72ca652SBlue Swirl 519e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */ 520dce0a58fSDavid Hildenbrand uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34) 521e72ca652SBlue Swirl { 522dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 52368c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 52468c8bd93SRichard Henderson int64_t ret = float128_to_int64(v2, &env->fpu_status); 525c0ee7015SDavid Hildenbrand 526c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 527dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 52868c8bd93SRichard Henderson return ret; 529e72ca652SBlue Swirl } 530e72ca652SBlue Swirl 531e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */ 532dce0a58fSDavid Hildenbrand uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 533e72ca652SBlue Swirl { 534dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 53568c8bd93SRichard Henderson int32_t ret = float32_to_int32(v2, &env->fpu_status); 536c0ee7015SDavid Hildenbrand 537c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 538dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 53968c8bd93SRichard Henderson return ret; 540e72ca652SBlue Swirl } 541e72ca652SBlue Swirl 542e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */ 543dce0a58fSDavid Hildenbrand uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 544e72ca652SBlue Swirl { 545dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 54668c8bd93SRichard Henderson int32_t ret = float64_to_int32(v2, &env->fpu_status); 547c0ee7015SDavid Hildenbrand 548c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 549dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 55068c8bd93SRichard Henderson return ret; 551e72ca652SBlue Swirl } 552e72ca652SBlue Swirl 553e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */ 554dce0a58fSDavid Hildenbrand uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34) 555e72ca652SBlue Swirl { 556dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 55768c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 55868c8bd93SRichard Henderson int32_t ret = float128_to_int32(v2, &env->fpu_status); 559c0ee7015SDavid Hildenbrand 560c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 561dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 56268c8bd93SRichard Henderson return ret; 563e72ca652SBlue Swirl } 564e72ca652SBlue Swirl 5656ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */ 566dce0a58fSDavid Hildenbrand uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 5676ac1b45fSRichard Henderson { 568dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 5696ac1b45fSRichard Henderson uint64_t ret; 570c0ee7015SDavid Hildenbrand 5716ac1b45fSRichard Henderson v2 = float32_to_float64(v2, &env->fpu_status); 5726ac1b45fSRichard Henderson ret = float64_to_uint64(v2, &env->fpu_status); 573c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 574dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 5756ac1b45fSRichard Henderson return ret; 5766ac1b45fSRichard Henderson } 5776ac1b45fSRichard Henderson 5786ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */ 579dce0a58fSDavid Hildenbrand uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 5806ac1b45fSRichard Henderson { 581dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 5826ac1b45fSRichard Henderson uint64_t ret = float64_to_uint64(v2, &env->fpu_status); 583c0ee7015SDavid Hildenbrand 584c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 585dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 5866ac1b45fSRichard Henderson return ret; 5876ac1b45fSRichard Henderson } 5886ac1b45fSRichard Henderson 5896ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */ 590dce0a58fSDavid Hildenbrand uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34) 5916ac1b45fSRichard Henderson { 592dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 5933af471f9SDavid Hildenbrand uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status); 594c0ee7015SDavid Hildenbrand 595c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 596dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 5976ac1b45fSRichard Henderson return ret; 5986ac1b45fSRichard Henderson } 5996ac1b45fSRichard Henderson 6006ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */ 601dce0a58fSDavid Hildenbrand uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 6026ac1b45fSRichard Henderson { 603dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 6046ac1b45fSRichard Henderson uint32_t ret = float32_to_uint32(v2, &env->fpu_status); 605c0ee7015SDavid Hildenbrand 606c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 607dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 6086ac1b45fSRichard Henderson return ret; 6096ac1b45fSRichard Henderson } 6106ac1b45fSRichard Henderson 6116ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */ 612dce0a58fSDavid Hildenbrand uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 6136ac1b45fSRichard Henderson { 614dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 6156ac1b45fSRichard Henderson uint32_t ret = float64_to_uint32(v2, &env->fpu_status); 616c0ee7015SDavid Hildenbrand 617c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 618dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 6196ac1b45fSRichard Henderson return ret; 6206ac1b45fSRichard Henderson } 6216ac1b45fSRichard Henderson 6226ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */ 623dce0a58fSDavid Hildenbrand uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34) 6246ac1b45fSRichard Henderson { 625dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 6263af471f9SDavid Hildenbrand uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status); 627c0ee7015SDavid Hildenbrand 628c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 629dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 6306ac1b45fSRichard Henderson return ret; 6316ac1b45fSRichard Henderson } 6326ac1b45fSRichard Henderson 633ed0bceceSAurelien Jarno /* round to integer 32-bit */ 634dce0a58fSDavid Hildenbrand uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m34) 635ed0bceceSAurelien Jarno { 636dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 637ed0bceceSAurelien Jarno float32 ret = float32_round_to_int(f2, &env->fpu_status); 638c0ee7015SDavid Hildenbrand 639c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 640dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 641ed0bceceSAurelien Jarno return ret; 642ed0bceceSAurelien Jarno } 643ed0bceceSAurelien Jarno 644ed0bceceSAurelien Jarno /* round to integer 64-bit */ 645dce0a58fSDavid Hildenbrand uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m34) 646ed0bceceSAurelien Jarno { 647dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 648ed0bceceSAurelien Jarno float64 ret = float64_round_to_int(f2, &env->fpu_status); 649c0ee7015SDavid Hildenbrand 650c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 651dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 652ed0bceceSAurelien Jarno return ret; 653ed0bceceSAurelien Jarno } 654ed0bceceSAurelien Jarno 655ed0bceceSAurelien Jarno /* round to integer 128-bit */ 656dce0a58fSDavid Hildenbrand uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, 657dce0a58fSDavid Hildenbrand uint32_t m34) 658ed0bceceSAurelien Jarno { 659dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 660ed0bceceSAurelien Jarno float128 ret = float128_round_to_int(make_float128(ah, al), 661ed0bceceSAurelien Jarno &env->fpu_status); 662cf97f9ffSDavid Hildenbrand 663c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 664dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 665ed0bceceSAurelien Jarno return RET128(ret); 666ed0bceceSAurelien Jarno } 667ed0bceceSAurelien Jarno 6689c8be598SAurelien Jarno /* 32-bit FP compare and signal */ 6699c8be598SAurelien Jarno uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 6709c8be598SAurelien Jarno { 6719c8be598SAurelien Jarno int cmp = float32_compare(f1, f2, &env->fpu_status); 672cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 6739c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6749c8be598SAurelien Jarno } 6759c8be598SAurelien Jarno 6769c8be598SAurelien Jarno /* 64-bit FP compare and signal */ 6779c8be598SAurelien Jarno uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 6789c8be598SAurelien Jarno { 6799c8be598SAurelien Jarno int cmp = float64_compare(f1, f2, &env->fpu_status); 680cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 6819c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6829c8be598SAurelien Jarno } 6839c8be598SAurelien Jarno 6849c8be598SAurelien Jarno /* 128-bit FP compare and signal */ 6859c8be598SAurelien Jarno uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 6869c8be598SAurelien Jarno uint64_t bh, uint64_t bl) 6879c8be598SAurelien Jarno { 6889c8be598SAurelien Jarno int cmp = float128_compare(make_float128(ah, al), 6899c8be598SAurelien Jarno make_float128(bh, bl), 6909c8be598SAurelien Jarno &env->fpu_status); 691cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 6929c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6939c8be598SAurelien Jarno } 6949c8be598SAurelien Jarno 695722bfec3SRichard Henderson /* 32-bit FP multiply and add */ 696722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, 697722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 698e72ca652SBlue Swirl { 699722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status); 700cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 701722bfec3SRichard Henderson return ret; 702722bfec3SRichard Henderson } 703e72ca652SBlue Swirl 704722bfec3SRichard Henderson /* 64-bit FP multiply and add */ 705722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1, 706722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 707722bfec3SRichard Henderson { 708722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status); 709cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 710722bfec3SRichard Henderson return ret; 711722bfec3SRichard Henderson } 712722bfec3SRichard Henderson 713722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */ 714722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1, 715722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 716722bfec3SRichard Henderson { 717722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c, 718e72ca652SBlue Swirl &env->fpu_status); 719cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 720722bfec3SRichard Henderson return ret; 721e72ca652SBlue Swirl } 722e72ca652SBlue Swirl 723722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */ 724722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1, 725722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 726e72ca652SBlue Swirl { 727722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c, 728e72ca652SBlue Swirl &env->fpu_status); 729cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 730722bfec3SRichard Henderson return ret; 731e72ca652SBlue Swirl } 732e72ca652SBlue Swirl 733fc7cc951SDavid Hildenbrand /* The rightmost bit has the number 11. */ 734fc7cc951SDavid Hildenbrand static inline uint16_t dcmask(int bit, bool neg) 735fc7cc951SDavid Hildenbrand { 736fc7cc951SDavid Hildenbrand return 1 << (11 - bit - neg); 737fc7cc951SDavid Hildenbrand } 738fc7cc951SDavid Hildenbrand 739fc7cc951SDavid Hildenbrand #define DEF_FLOAT_DCMASK(_TYPE) \ 740fc7cc951SDavid Hildenbrand static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1) \ 741fc7cc951SDavid Hildenbrand { \ 742fc7cc951SDavid Hildenbrand const bool neg = _TYPE##_is_neg(f1); \ 743fc7cc951SDavid Hildenbrand \ 744fc7cc951SDavid Hildenbrand /* Sorted by most common cases - only one class is possible */ \ 745fc7cc951SDavid Hildenbrand if (_TYPE##_is_normal(f1)) { \ 746fc7cc951SDavid Hildenbrand return dcmask(2, neg); \ 747fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_zero(f1)) { \ 748fc7cc951SDavid Hildenbrand return dcmask(0, neg); \ 749fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_denormal(f1)) { \ 750fc7cc951SDavid Hildenbrand return dcmask(4, neg); \ 751fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_infinity(f1)) { \ 752fc7cc951SDavid Hildenbrand return dcmask(6, neg); \ 753fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) { \ 754fc7cc951SDavid Hildenbrand return dcmask(8, neg); \ 755fc7cc951SDavid Hildenbrand } \ 756fc7cc951SDavid Hildenbrand /* signaling nan, as last remaining case */ \ 757fc7cc951SDavid Hildenbrand return dcmask(10, neg); \ 758fc7cc951SDavid Hildenbrand } 759fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float32) 760fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float64) 761fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float128) 762fc7cc951SDavid Hildenbrand 763e72ca652SBlue Swirl /* test data class 32-bit */ 764af39bc8cSAleksandar Markovic uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2) 765e72ca652SBlue Swirl { 766fc7cc951SDavid Hildenbrand return (m2 & float32_dcmask(env, f1)) != 0; 767e72ca652SBlue Swirl } 768e72ca652SBlue Swirl 769e72ca652SBlue Swirl /* test data class 64-bit */ 770af39bc8cSAleksandar Markovic uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2) 771e72ca652SBlue Swirl { 772fc7cc951SDavid Hildenbrand return (m2 & float64_dcmask(env, v1)) != 0; 773e72ca652SBlue Swirl } 774e72ca652SBlue Swirl 775e72ca652SBlue Swirl /* test data class 128-bit */ 776fc7cc951SDavid Hildenbrand uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2) 777e72ca652SBlue Swirl { 778fc7cc951SDavid Hildenbrand return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0; 779e72ca652SBlue Swirl } 780e72ca652SBlue Swirl 78116d7b2a4SRichard Henderson /* square root 32-bit */ 78216d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2) 783e72ca652SBlue Swirl { 78416d7b2a4SRichard Henderson float32 ret = float32_sqrt(f2, &env->fpu_status); 785cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 78616d7b2a4SRichard Henderson return ret; 78716d7b2a4SRichard Henderson } 78816d7b2a4SRichard Henderson 78916d7b2a4SRichard Henderson /* square root 64-bit */ 79016d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2) 79116d7b2a4SRichard Henderson { 79216d7b2a4SRichard Henderson float64 ret = float64_sqrt(f2, &env->fpu_status); 793cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 79416d7b2a4SRichard Henderson return ret; 79516d7b2a4SRichard Henderson } 79616d7b2a4SRichard Henderson 79716d7b2a4SRichard Henderson /* square root 128-bit */ 79816d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 79916d7b2a4SRichard Henderson { 80016d7b2a4SRichard Henderson float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status); 801cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 80216d7b2a4SRichard Henderson return RET128(ret); 803e72ca652SBlue Swirl } 8048379bfdbSRichard Henderson 8052aea83c6SDavid Hildenbrand static const int fpc_to_rnd[8] = { 8068379bfdbSRichard Henderson float_round_nearest_even, 8078379bfdbSRichard Henderson float_round_to_zero, 8088379bfdbSRichard Henderson float_round_up, 8092aea83c6SDavid Hildenbrand float_round_down, 8102aea83c6SDavid Hildenbrand -1, 8112aea83c6SDavid Hildenbrand -1, 8122aea83c6SDavid Hildenbrand -1, 8132aea83c6SDavid Hildenbrand float_round_to_odd, 8148379bfdbSRichard Henderson }; 8158379bfdbSRichard Henderson 816411edc22SRichard Henderson /* set fpc */ 817411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc) 818411edc22SRichard Henderson { 8192aea83c6SDavid Hildenbrand if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u || 8202aea83c6SDavid Hildenbrand (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) { 8212aea83c6SDavid Hildenbrand s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC()); 8222aea83c6SDavid Hildenbrand } 8232aea83c6SDavid Hildenbrand 8248379bfdbSRichard Henderson /* Install everything in the main FPC. */ 8258379bfdbSRichard Henderson env->fpc = fpc; 8268379bfdbSRichard Henderson 8278379bfdbSRichard Henderson /* Install the rounding mode in the shadow fpu_status. */ 8282aea83c6SDavid Hildenbrand set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status); 829411edc22SRichard Henderson } 830411edc22SRichard Henderson 831411edc22SRichard Henderson /* set fpc and signal */ 832f66a0ecfSDavid Hildenbrand void HELPER(sfas)(CPUS390XState *env, uint64_t fpc) 833411edc22SRichard Henderson { 834411edc22SRichard Henderson uint32_t signalling = env->fpc; 835411edc22SRichard Henderson uint32_t s390_exc; 836411edc22SRichard Henderson 8372aea83c6SDavid Hildenbrand if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u || 8382aea83c6SDavid Hildenbrand (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) { 8392aea83c6SDavid Hildenbrand s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC()); 8402aea83c6SDavid Hildenbrand } 8412aea83c6SDavid Hildenbrand 842f66a0ecfSDavid Hildenbrand /* 843f66a0ecfSDavid Hildenbrand * FPC is set to the FPC operand with a bitwise OR of the signalling 844f66a0ecfSDavid Hildenbrand * flags. 845f66a0ecfSDavid Hildenbrand */ 846f66a0ecfSDavid Hildenbrand env->fpc = fpc | (signalling & 0x00ff0000); 8472aea83c6SDavid Hildenbrand set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status); 848411edc22SRichard Henderson 849f66a0ecfSDavid Hildenbrand /* 850f66a0ecfSDavid Hildenbrand * If any signaling flag is enabled in the new FPC mask, a 851f66a0ecfSDavid Hildenbrand * simulated-iee-exception exception occurs. 852f66a0ecfSDavid Hildenbrand */ 853f66a0ecfSDavid Hildenbrand s390_exc = (signalling >> 16) & (fpc >> 24); 854411edc22SRichard Henderson if (s390_exc) { 8558772bbe4SDavid Hildenbrand if (s390_exc & S390_IEEE_MASK_INVALID) { 8568772bbe4SDavid Hildenbrand s390_exc = S390_IEEE_MASK_INVALID; 8578772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) { 8588772bbe4SDavid Hildenbrand s390_exc = S390_IEEE_MASK_DIVBYZERO; 8598772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) { 8608772bbe4SDavid Hildenbrand s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT); 8618772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) { 8628772bbe4SDavid Hildenbrand s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT); 8638772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_INEXACT) { 8648772bbe4SDavid Hildenbrand s390_exc = S390_IEEE_MASK_INEXACT; 8658772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_QUANTUM) { 8668772bbe4SDavid Hildenbrand s390_exc = S390_IEEE_MASK_QUANTUM; 8678772bbe4SDavid Hildenbrand } 868bbf6ea3bSDavid Hildenbrand tcg_s390_data_exception(env, s390_exc | 3, GETPC()); 869411edc22SRichard Henderson } 8708379bfdbSRichard Henderson } 871b9c737f5SDavid Hildenbrand 872b9c737f5SDavid Hildenbrand /* set bfp rounding mode */ 873b9c737f5SDavid Hildenbrand void HELPER(srnm)(CPUS390XState *env, uint64_t rnd) 874b9c737f5SDavid Hildenbrand { 875b9c737f5SDavid Hildenbrand if (rnd > 0x7 || fpc_to_rnd[rnd & 0x7] == -1) { 876b9c737f5SDavid Hildenbrand s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC()); 877b9c737f5SDavid Hildenbrand } 878b9c737f5SDavid Hildenbrand 879b9c737f5SDavid Hildenbrand env->fpc = deposit32(env->fpc, 0, 3, rnd); 880b9c737f5SDavid Hildenbrand set_float_rounding_mode(fpc_to_rnd[rnd & 0x7], &env->fpu_status); 881b9c737f5SDavid Hildenbrand } 882