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