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 66*fcb9e9f2SDavid Hildenbrand /* 67*fcb9e9f2SDavid Hildenbrand * FIXME: 68*fcb9e9f2SDavid Hildenbrand * 1. Right now, all inexact conditions are inidicated as 69*fcb9e9f2SDavid Hildenbrand * "truncated" (0) and never as "incremented" (1) in the DXC. 70*fcb9e9f2SDavid Hildenbrand * 2. Only traps due to invalid/divbyzero are suppressing. Other traps 71*fcb9e9f2SDavid Hildenbrand * are completing, meaning the target register has to be written! 72*fcb9e9f2SDavid Hildenbrand * This, however will mean that we have to write the register before 73*fcb9e9f2SDavid Hildenbrand * triggering the trap - impossible right now. 74*fcb9e9f2SDavid Hildenbrand */ 75587626f8SRichard Henderson 76*fcb9e9f2SDavid Hildenbrand /* 77*fcb9e9f2SDavid Hildenbrand * invalid/divbyzero cannot coexist with other conditions. 78*fcb9e9f2SDavid Hildenbrand * overflow/underflow however can coexist with inexact, we have to 79*fcb9e9f2SDavid Hildenbrand * handle it separatly. 80*fcb9e9f2SDavid Hildenbrand */ 81*fcb9e9f2SDavid Hildenbrand if (s390_exc & ~S390_IEEE_MASK_INEXACT) { 82*fcb9e9f2SDavid Hildenbrand if (s390_exc & ~S390_IEEE_MASK_INEXACT & env->fpc >> 24) { 83*fcb9e9f2SDavid Hildenbrand /* trap condition - inexact reported along */ 84bbf6ea3bSDavid Hildenbrand tcg_s390_data_exception(env, s390_exc, retaddr); 85587626f8SRichard Henderson } 86*fcb9e9f2SDavid Hildenbrand /* nontrap condition - inexact handled differently */ 87*fcb9e9f2SDavid Hildenbrand env->fpc |= (s390_exc & ~S390_IEEE_MASK_INEXACT) << 16; 88*fcb9e9f2SDavid Hildenbrand } 89*fcb9e9f2SDavid Hildenbrand 90*fcb9e9f2SDavid Hildenbrand /* inexact handling */ 91*fcb9e9f2SDavid Hildenbrand if (s390_exc & S390_IEEE_MASK_INEXACT) { 92*fcb9e9f2SDavid Hildenbrand /* trap condition - overflow/underflow _not_ reported along */ 93*fcb9e9f2SDavid Hildenbrand if (s390_exc & S390_IEEE_MASK_INEXACT & env->fpc >> 24) { 94*fcb9e9f2SDavid Hildenbrand tcg_s390_data_exception(env, s390_exc & S390_IEEE_MASK_INEXACT, 95*fcb9e9f2SDavid Hildenbrand retaddr); 96*fcb9e9f2SDavid Hildenbrand } 97*fcb9e9f2SDavid Hildenbrand /* nontrap condition */ 98*fcb9e9f2SDavid Hildenbrand env->fpc |= (s390_exc & S390_IEEE_MASK_INEXACT) << 16; 99*fcb9e9f2SDavid Hildenbrand } 100587626f8SRichard Henderson } 101587626f8SRichard Henderson 102449c0d70SBlue Swirl static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) 103e72ca652SBlue Swirl { 104a47dddd7SAndreas Färber S390CPU *cpu = s390_env_get_cpu(env); 105a47dddd7SAndreas Färber 106e72ca652SBlue Swirl switch (float_compare) { 107e72ca652SBlue Swirl case float_relation_equal: 108e72ca652SBlue Swirl return 0; 109e72ca652SBlue Swirl case float_relation_less: 110e72ca652SBlue Swirl return 1; 111e72ca652SBlue Swirl case float_relation_greater: 112e72ca652SBlue Swirl return 2; 113e72ca652SBlue Swirl case float_relation_unordered: 114e72ca652SBlue Swirl return 3; 115e72ca652SBlue Swirl default: 116a47dddd7SAndreas Färber cpu_abort(CPU(cpu), "unknown return value for float compare\n"); 117e72ca652SBlue Swirl } 118e72ca652SBlue Swirl } 119e72ca652SBlue Swirl 120e72ca652SBlue Swirl /* condition codes for unary FP ops */ 121e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v) 122e72ca652SBlue Swirl { 123e72ca652SBlue Swirl if (float32_is_any_nan(v)) { 124e72ca652SBlue Swirl return 3; 125e72ca652SBlue Swirl } else if (float32_is_zero(v)) { 126e72ca652SBlue Swirl return 0; 127e72ca652SBlue Swirl } else if (float32_is_neg(v)) { 128e72ca652SBlue Swirl return 1; 129e72ca652SBlue Swirl } else { 130e72ca652SBlue Swirl return 2; 131e72ca652SBlue Swirl } 132e72ca652SBlue Swirl } 133e72ca652SBlue Swirl 134e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v) 135e72ca652SBlue Swirl { 136e72ca652SBlue Swirl if (float64_is_any_nan(v)) { 137e72ca652SBlue Swirl return 3; 138e72ca652SBlue Swirl } else if (float64_is_zero(v)) { 139e72ca652SBlue Swirl return 0; 140e72ca652SBlue Swirl } else if (float64_is_neg(v)) { 141e72ca652SBlue Swirl return 1; 142e72ca652SBlue Swirl } else { 143e72ca652SBlue Swirl return 2; 144e72ca652SBlue Swirl } 145e72ca652SBlue Swirl } 146e72ca652SBlue Swirl 147587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v) 148e72ca652SBlue Swirl { 149e72ca652SBlue Swirl if (float128_is_any_nan(v)) { 150e72ca652SBlue Swirl return 3; 151e72ca652SBlue Swirl } else if (float128_is_zero(v)) { 152e72ca652SBlue Swirl return 0; 153e72ca652SBlue Swirl } else if (float128_is_neg(v)) { 154e72ca652SBlue Swirl return 1; 155e72ca652SBlue Swirl } else { 156e72ca652SBlue Swirl return 2; 157e72ca652SBlue Swirl } 158e72ca652SBlue Swirl } 159e72ca652SBlue Swirl 160587626f8SRichard Henderson /* 32-bit FP addition */ 161587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 162e72ca652SBlue Swirl { 163587626f8SRichard Henderson float32 ret = float32_add(f1, f2, &env->fpu_status); 164587626f8SRichard Henderson handle_exceptions(env, GETPC()); 165587626f8SRichard Henderson return ret; 166e72ca652SBlue Swirl } 167e72ca652SBlue Swirl 168587626f8SRichard Henderson /* 64-bit FP addition */ 169587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 170e72ca652SBlue Swirl { 171587626f8SRichard Henderson float64 ret = float64_add(f1, f2, &env->fpu_status); 172587626f8SRichard Henderson handle_exceptions(env, GETPC()); 173587626f8SRichard Henderson return ret; 174587626f8SRichard Henderson } 175e72ca652SBlue Swirl 176587626f8SRichard Henderson /* 128-bit FP addition */ 177587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al, 178587626f8SRichard Henderson uint64_t bh, uint64_t bl) 179587626f8SRichard Henderson { 180587626f8SRichard Henderson float128 ret = float128_add(make_float128(ah, al), 181587626f8SRichard Henderson make_float128(bh, bl), 182587626f8SRichard Henderson &env->fpu_status); 183587626f8SRichard Henderson handle_exceptions(env, GETPC()); 184587626f8SRichard Henderson return RET128(ret); 185e72ca652SBlue Swirl } 186e72ca652SBlue Swirl 1871a800a2dSRichard Henderson /* 32-bit FP subtraction */ 1881a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 189e72ca652SBlue Swirl { 1901a800a2dSRichard Henderson float32 ret = float32_sub(f1, f2, &env->fpu_status); 1911a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 1921a800a2dSRichard Henderson return ret; 193e72ca652SBlue Swirl } 194e72ca652SBlue Swirl 1951a800a2dSRichard Henderson /* 64-bit FP subtraction */ 1961a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 197e72ca652SBlue Swirl { 1981a800a2dSRichard Henderson float64 ret = float64_sub(f1, f2, &env->fpu_status); 1991a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 2001a800a2dSRichard Henderson return ret; 2011a800a2dSRichard Henderson } 202e72ca652SBlue Swirl 2031a800a2dSRichard Henderson /* 128-bit FP subtraction */ 2041a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 2051a800a2dSRichard Henderson uint64_t bh, uint64_t bl) 2061a800a2dSRichard Henderson { 2071a800a2dSRichard Henderson float128 ret = float128_sub(make_float128(ah, al), 2081a800a2dSRichard Henderson make_float128(bh, bl), 2091a800a2dSRichard Henderson &env->fpu_status); 2101a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 2111a800a2dSRichard Henderson return RET128(ret); 212e72ca652SBlue Swirl } 213e72ca652SBlue Swirl 214f08a5c31SRichard Henderson /* 32-bit FP division */ 215f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 216e72ca652SBlue Swirl { 217f08a5c31SRichard Henderson float32 ret = float32_div(f1, f2, &env->fpu_status); 218f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 219f08a5c31SRichard Henderson return ret; 220e72ca652SBlue Swirl } 221e72ca652SBlue Swirl 222f08a5c31SRichard Henderson /* 64-bit FP division */ 223f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 224e72ca652SBlue Swirl { 225f08a5c31SRichard Henderson float64 ret = float64_div(f1, f2, &env->fpu_status); 226f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 227f08a5c31SRichard Henderson return ret; 228f08a5c31SRichard Henderson } 229e72ca652SBlue Swirl 230f08a5c31SRichard Henderson /* 128-bit FP division */ 231f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 232f08a5c31SRichard Henderson uint64_t bh, uint64_t bl) 233f08a5c31SRichard Henderson { 234f08a5c31SRichard Henderson float128 ret = float128_div(make_float128(ah, al), 235f08a5c31SRichard Henderson make_float128(bh, bl), 236f08a5c31SRichard Henderson &env->fpu_status); 237f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 238f08a5c31SRichard Henderson return RET128(ret); 239e72ca652SBlue Swirl } 240e72ca652SBlue Swirl 24183b00736SRichard Henderson /* 32-bit FP multiplication */ 24283b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 243e72ca652SBlue Swirl { 24483b00736SRichard Henderson float32 ret = float32_mul(f1, f2, &env->fpu_status); 24583b00736SRichard Henderson handle_exceptions(env, GETPC()); 24683b00736SRichard Henderson return ret; 247e72ca652SBlue Swirl } 248e72ca652SBlue Swirl 24983b00736SRichard Henderson /* 64-bit FP multiplication */ 25083b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 251e72ca652SBlue Swirl { 25283b00736SRichard Henderson float64 ret = float64_mul(f1, f2, &env->fpu_status); 25383b00736SRichard Henderson handle_exceptions(env, GETPC()); 25483b00736SRichard Henderson return ret; 25583b00736SRichard Henderson } 256e72ca652SBlue Swirl 25783b00736SRichard Henderson /* 64/32-bit FP multiplication */ 25883b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 25983b00736SRichard Henderson { 26083b00736SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 26183b00736SRichard Henderson ret = float64_mul(f1, ret, &env->fpu_status); 26283b00736SRichard Henderson handle_exceptions(env, GETPC()); 26383b00736SRichard Henderson return ret; 26483b00736SRichard Henderson } 26583b00736SRichard Henderson 26683b00736SRichard Henderson /* 128-bit FP multiplication */ 26783b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 26883b00736SRichard Henderson uint64_t bh, uint64_t bl) 26983b00736SRichard Henderson { 27083b00736SRichard Henderson float128 ret = float128_mul(make_float128(ah, al), 27183b00736SRichard Henderson make_float128(bh, bl), 27283b00736SRichard Henderson &env->fpu_status); 27383b00736SRichard Henderson handle_exceptions(env, GETPC()); 27483b00736SRichard Henderson return RET128(ret); 27583b00736SRichard Henderson } 27683b00736SRichard Henderson 27783b00736SRichard Henderson /* 128/64-bit FP multiplication */ 27883b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al, 27983b00736SRichard Henderson uint64_t f2) 28083b00736SRichard Henderson { 28183b00736SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 28283b00736SRichard Henderson ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status); 28383b00736SRichard Henderson handle_exceptions(env, GETPC()); 28483b00736SRichard Henderson return RET128(ret); 285e72ca652SBlue Swirl } 286e72ca652SBlue Swirl 287e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */ 288587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2) 289e72ca652SBlue Swirl { 290587626f8SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 291587626f8SRichard Henderson handle_exceptions(env, GETPC()); 292d0cfecb5SRichard Henderson return ret; 293e72ca652SBlue Swirl } 294e72ca652SBlue Swirl 295e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */ 296587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 297e72ca652SBlue Swirl { 298587626f8SRichard Henderson float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); 299587626f8SRichard Henderson handle_exceptions(env, GETPC()); 300d0cfecb5SRichard Henderson return ret; 301e72ca652SBlue Swirl } 302e72ca652SBlue Swirl 303e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */ 304587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) 305e72ca652SBlue Swirl { 306587626f8SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 307587626f8SRichard Henderson handle_exceptions(env, GETPC()); 308d0cfecb5SRichard Henderson return RET128(ret); 309587626f8SRichard Henderson } 310e72ca652SBlue Swirl 311587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */ 312587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) 313587626f8SRichard Henderson { 314587626f8SRichard Henderson float128 ret = float32_to_float128(f2, &env->fpu_status); 315587626f8SRichard Henderson handle_exceptions(env, GETPC()); 316d0cfecb5SRichard Henderson return RET128(ret); 317e72ca652SBlue Swirl } 318e72ca652SBlue Swirl 319e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */ 320587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2) 321e72ca652SBlue Swirl { 322587626f8SRichard Henderson float32 ret = float64_to_float32(f2, &env->fpu_status); 323587626f8SRichard Henderson handle_exceptions(env, GETPC()); 324d0cfecb5SRichard Henderson return ret; 325e72ca652SBlue Swirl } 326e72ca652SBlue Swirl 327e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */ 328587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al) 329e72ca652SBlue Swirl { 330587626f8SRichard Henderson float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); 331587626f8SRichard Henderson handle_exceptions(env, GETPC()); 332d0cfecb5SRichard Henderson return ret; 333e72ca652SBlue Swirl } 334e72ca652SBlue Swirl 335587626f8SRichard Henderson /* 32-bit FP compare */ 336587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 337e72ca652SBlue Swirl { 338587626f8SRichard Henderson int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); 339587626f8SRichard Henderson handle_exceptions(env, GETPC()); 340587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 341e72ca652SBlue Swirl } 342e72ca652SBlue Swirl 343587626f8SRichard Henderson /* 64-bit FP compare */ 344587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 345e72ca652SBlue Swirl { 346587626f8SRichard Henderson int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); 347587626f8SRichard Henderson handle_exceptions(env, GETPC()); 348587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 349e72ca652SBlue Swirl } 350e72ca652SBlue Swirl 351587626f8SRichard Henderson /* 128-bit FP compare */ 352587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 353587626f8SRichard Henderson uint64_t bh, uint64_t bl) 354e72ca652SBlue Swirl { 355587626f8SRichard Henderson int cmp = float128_compare_quiet(make_float128(ah, al), 356587626f8SRichard Henderson make_float128(bh, bl), 357587626f8SRichard Henderson &env->fpu_status); 358587626f8SRichard Henderson handle_exceptions(env, GETPC()); 359587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 360e72ca652SBlue Swirl } 361e72ca652SBlue Swirl 36268c8bd93SRichard Henderson static int swap_round_mode(CPUS390XState *env, int m3) 363e72ca652SBlue Swirl { 36468c8bd93SRichard Henderson int ret = env->fpu_status.float_rounding_mode; 365e72ca652SBlue Swirl switch (m3) { 366e72ca652SBlue Swirl case 0: 367e72ca652SBlue Swirl /* current mode */ 368e72ca652SBlue Swirl break; 369e72ca652SBlue Swirl case 1: 370e72ca652SBlue Swirl /* biased round no nearest */ 371e72ca652SBlue Swirl case 4: 372e72ca652SBlue Swirl /* round to nearest */ 373e72ca652SBlue Swirl set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); 374e72ca652SBlue Swirl break; 375e72ca652SBlue Swirl case 5: 376e72ca652SBlue Swirl /* round to zero */ 377e72ca652SBlue Swirl set_float_rounding_mode(float_round_to_zero, &env->fpu_status); 378e72ca652SBlue Swirl break; 379e72ca652SBlue Swirl case 6: 380e72ca652SBlue Swirl /* round to +inf */ 381e72ca652SBlue Swirl set_float_rounding_mode(float_round_up, &env->fpu_status); 382e72ca652SBlue Swirl break; 383e72ca652SBlue Swirl case 7: 384e72ca652SBlue Swirl /* round to -inf */ 385e72ca652SBlue Swirl set_float_rounding_mode(float_round_down, &env->fpu_status); 386e72ca652SBlue Swirl break; 387e72ca652SBlue Swirl } 38868c8bd93SRichard Henderson return ret; 389e72ca652SBlue Swirl } 390e72ca652SBlue Swirl 391683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */ 392683bb9a8SRichard Henderson uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3) 393683bb9a8SRichard Henderson { 394683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 395683bb9a8SRichard Henderson float32 ret = int64_to_float32(v2, &env->fpu_status); 396683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 397683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 398683bb9a8SRichard Henderson return ret; 399683bb9a8SRichard Henderson } 400683bb9a8SRichard Henderson 401683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */ 402683bb9a8SRichard Henderson uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3) 403683bb9a8SRichard Henderson { 404683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 405683bb9a8SRichard Henderson float64 ret = int64_to_float64(v2, &env->fpu_status); 406683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 407683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 408683bb9a8SRichard Henderson return ret; 409683bb9a8SRichard Henderson } 410683bb9a8SRichard Henderson 411683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */ 412683bb9a8SRichard Henderson uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3) 413683bb9a8SRichard Henderson { 414683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 415683bb9a8SRichard Henderson float128 ret = int64_to_float128(v2, &env->fpu_status); 416683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 417683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 418683bb9a8SRichard Henderson return RET128(ret); 419683bb9a8SRichard Henderson } 420683bb9a8SRichard Henderson 4212112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */ 4222112bf1bSRichard Henderson uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 4232112bf1bSRichard Henderson { 4242112bf1bSRichard Henderson int hold = swap_round_mode(env, m3); 4252112bf1bSRichard Henderson float32 ret = uint64_to_float32(v2, &env->fpu_status); 4262112bf1bSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 4272112bf1bSRichard Henderson handle_exceptions(env, GETPC()); 4282112bf1bSRichard Henderson return ret; 4292112bf1bSRichard Henderson } 4302112bf1bSRichard Henderson 4312112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */ 4322112bf1bSRichard Henderson uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 4332112bf1bSRichard Henderson { 4342112bf1bSRichard Henderson int hold = swap_round_mode(env, m3); 4352112bf1bSRichard Henderson float64 ret = uint64_to_float64(v2, &env->fpu_status); 4362112bf1bSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 4372112bf1bSRichard Henderson handle_exceptions(env, GETPC()); 4382112bf1bSRichard Henderson return ret; 4392112bf1bSRichard Henderson } 4402112bf1bSRichard Henderson 4412112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */ 4422112bf1bSRichard Henderson uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 4432112bf1bSRichard Henderson { 4442112bf1bSRichard Henderson int hold = swap_round_mode(env, m3); 445d2d9feacSRichard Henderson float128 ret = uint64_to_float128(v2, &env->fpu_status); 4462112bf1bSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 4472112bf1bSRichard Henderson handle_exceptions(env, GETPC()); 4482112bf1bSRichard Henderson return RET128(ret); 4492112bf1bSRichard Henderson } 4502112bf1bSRichard Henderson 451e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */ 45268c8bd93SRichard Henderson uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 453e72ca652SBlue Swirl { 45468c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 45568c8bd93SRichard Henderson int64_t ret = float32_to_int64(v2, &env->fpu_status); 45668c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 45768c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 45868c8bd93SRichard Henderson return ret; 459e72ca652SBlue Swirl } 460e72ca652SBlue Swirl 461e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */ 46268c8bd93SRichard Henderson uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 463e72ca652SBlue Swirl { 46468c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 46568c8bd93SRichard Henderson int64_t ret = float64_to_int64(v2, &env->fpu_status); 46668c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 46768c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 46868c8bd93SRichard Henderson return ret; 469e72ca652SBlue Swirl } 470e72ca652SBlue Swirl 471e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */ 47268c8bd93SRichard Henderson uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 473e72ca652SBlue Swirl { 47468c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 47568c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 47668c8bd93SRichard Henderson int64_t ret = float128_to_int64(v2, &env->fpu_status); 47768c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 47868c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 47968c8bd93SRichard Henderson return ret; 480e72ca652SBlue Swirl } 481e72ca652SBlue Swirl 482e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */ 48368c8bd93SRichard Henderson uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 484e72ca652SBlue Swirl { 48568c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 48668c8bd93SRichard Henderson int32_t ret = float32_to_int32(v2, &env->fpu_status); 48768c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 48868c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 48968c8bd93SRichard Henderson return ret; 490e72ca652SBlue Swirl } 491e72ca652SBlue Swirl 492e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */ 49368c8bd93SRichard Henderson uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 494e72ca652SBlue Swirl { 49568c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 49668c8bd93SRichard Henderson int32_t ret = float64_to_int32(v2, &env->fpu_status); 49768c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 49868c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 49968c8bd93SRichard Henderson return ret; 500e72ca652SBlue Swirl } 501e72ca652SBlue Swirl 502e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */ 50368c8bd93SRichard Henderson uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 504e72ca652SBlue Swirl { 50568c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 50668c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 50768c8bd93SRichard Henderson int32_t ret = float128_to_int32(v2, &env->fpu_status); 50868c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 50968c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 51068c8bd93SRichard Henderson return ret; 511e72ca652SBlue Swirl } 512e72ca652SBlue Swirl 5136ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */ 5146ac1b45fSRichard Henderson uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 5156ac1b45fSRichard Henderson { 5166ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5176ac1b45fSRichard Henderson uint64_t ret; 5186ac1b45fSRichard Henderson v2 = float32_to_float64(v2, &env->fpu_status); 5196ac1b45fSRichard Henderson ret = float64_to_uint64(v2, &env->fpu_status); 5206ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5216ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5226ac1b45fSRichard Henderson return ret; 5236ac1b45fSRichard Henderson } 5246ac1b45fSRichard Henderson 5256ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */ 5266ac1b45fSRichard Henderson uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 5276ac1b45fSRichard Henderson { 5286ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5296ac1b45fSRichard Henderson uint64_t ret = float64_to_uint64(v2, &env->fpu_status); 5306ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5316ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5326ac1b45fSRichard Henderson return ret; 5336ac1b45fSRichard Henderson } 5346ac1b45fSRichard Henderson 5356ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */ 5366ac1b45fSRichard Henderson uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 5376ac1b45fSRichard Henderson { 5386ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5393af471f9SDavid Hildenbrand uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status); 5406ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5416ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5426ac1b45fSRichard Henderson return ret; 5436ac1b45fSRichard Henderson } 5446ac1b45fSRichard Henderson 5456ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */ 5466ac1b45fSRichard Henderson uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 5476ac1b45fSRichard Henderson { 5486ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5496ac1b45fSRichard Henderson uint32_t ret = float32_to_uint32(v2, &env->fpu_status); 5506ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5516ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5526ac1b45fSRichard Henderson return ret; 5536ac1b45fSRichard Henderson } 5546ac1b45fSRichard Henderson 5556ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */ 5566ac1b45fSRichard Henderson uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 5576ac1b45fSRichard Henderson { 5586ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5596ac1b45fSRichard Henderson uint32_t ret = float64_to_uint32(v2, &env->fpu_status); 5606ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5616ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5626ac1b45fSRichard Henderson return ret; 5636ac1b45fSRichard Henderson } 5646ac1b45fSRichard Henderson 5656ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */ 5666ac1b45fSRichard Henderson uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 5676ac1b45fSRichard Henderson { 5686ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5693af471f9SDavid Hildenbrand uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status); 5706ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5716ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5726ac1b45fSRichard Henderson return ret; 5736ac1b45fSRichard Henderson } 5746ac1b45fSRichard Henderson 575ed0bceceSAurelien Jarno /* round to integer 32-bit */ 576ed0bceceSAurelien Jarno uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3) 577ed0bceceSAurelien Jarno { 578ed0bceceSAurelien Jarno int hold = swap_round_mode(env, m3); 579ed0bceceSAurelien Jarno float32 ret = float32_round_to_int(f2, &env->fpu_status); 580ed0bceceSAurelien Jarno set_float_rounding_mode(hold, &env->fpu_status); 581ed0bceceSAurelien Jarno handle_exceptions(env, GETPC()); 582ed0bceceSAurelien Jarno return ret; 583ed0bceceSAurelien Jarno } 584ed0bceceSAurelien Jarno 585ed0bceceSAurelien Jarno /* round to integer 64-bit */ 586ed0bceceSAurelien Jarno uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3) 587ed0bceceSAurelien Jarno { 588ed0bceceSAurelien Jarno int hold = swap_round_mode(env, m3); 589ed0bceceSAurelien Jarno float64 ret = float64_round_to_int(f2, &env->fpu_status); 590ed0bceceSAurelien Jarno set_float_rounding_mode(hold, &env->fpu_status); 591ed0bceceSAurelien Jarno handle_exceptions(env, GETPC()); 592ed0bceceSAurelien Jarno return ret; 593ed0bceceSAurelien Jarno } 594ed0bceceSAurelien Jarno 595ed0bceceSAurelien Jarno /* round to integer 128-bit */ 596ed0bceceSAurelien Jarno uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3) 597ed0bceceSAurelien Jarno { 598ed0bceceSAurelien Jarno int hold = swap_round_mode(env, m3); 599ed0bceceSAurelien Jarno float128 ret = float128_round_to_int(make_float128(ah, al), 600ed0bceceSAurelien Jarno &env->fpu_status); 601ed0bceceSAurelien Jarno set_float_rounding_mode(hold, &env->fpu_status); 602ed0bceceSAurelien Jarno handle_exceptions(env, GETPC()); 603ed0bceceSAurelien Jarno return RET128(ret); 604ed0bceceSAurelien Jarno } 605ed0bceceSAurelien Jarno 6069c8be598SAurelien Jarno /* 32-bit FP compare and signal */ 6079c8be598SAurelien Jarno uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 6089c8be598SAurelien Jarno { 6099c8be598SAurelien Jarno int cmp = float32_compare(f1, f2, &env->fpu_status); 6109c8be598SAurelien Jarno handle_exceptions(env, GETPC()); 6119c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6129c8be598SAurelien Jarno } 6139c8be598SAurelien Jarno 6149c8be598SAurelien Jarno /* 64-bit FP compare and signal */ 6159c8be598SAurelien Jarno uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 6169c8be598SAurelien Jarno { 6179c8be598SAurelien Jarno int cmp = float64_compare(f1, f2, &env->fpu_status); 6189c8be598SAurelien Jarno handle_exceptions(env, GETPC()); 6199c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6209c8be598SAurelien Jarno } 6219c8be598SAurelien Jarno 6229c8be598SAurelien Jarno /* 128-bit FP compare and signal */ 6239c8be598SAurelien Jarno uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 6249c8be598SAurelien Jarno uint64_t bh, uint64_t bl) 6259c8be598SAurelien Jarno { 6269c8be598SAurelien Jarno int cmp = float128_compare(make_float128(ah, al), 6279c8be598SAurelien Jarno make_float128(bh, bl), 6289c8be598SAurelien Jarno &env->fpu_status); 6299c8be598SAurelien Jarno handle_exceptions(env, GETPC()); 6309c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6319c8be598SAurelien Jarno } 6329c8be598SAurelien Jarno 633722bfec3SRichard Henderson /* 32-bit FP multiply and add */ 634722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, 635722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 636e72ca652SBlue Swirl { 637722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status); 638722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 639722bfec3SRichard Henderson return ret; 640722bfec3SRichard Henderson } 641e72ca652SBlue Swirl 642722bfec3SRichard Henderson /* 64-bit FP multiply and add */ 643722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1, 644722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 645722bfec3SRichard Henderson { 646722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status); 647722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 648722bfec3SRichard Henderson return ret; 649722bfec3SRichard Henderson } 650722bfec3SRichard Henderson 651722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */ 652722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1, 653722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 654722bfec3SRichard Henderson { 655722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c, 656e72ca652SBlue Swirl &env->fpu_status); 657722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 658722bfec3SRichard Henderson return ret; 659e72ca652SBlue Swirl } 660e72ca652SBlue Swirl 661722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */ 662722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1, 663722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 664e72ca652SBlue Swirl { 665722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c, 666e72ca652SBlue Swirl &env->fpu_status); 667722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 668722bfec3SRichard Henderson return ret; 669e72ca652SBlue Swirl } 670e72ca652SBlue Swirl 671fc7cc951SDavid Hildenbrand /* The rightmost bit has the number 11. */ 672fc7cc951SDavid Hildenbrand static inline uint16_t dcmask(int bit, bool neg) 673fc7cc951SDavid Hildenbrand { 674fc7cc951SDavid Hildenbrand return 1 << (11 - bit - neg); 675fc7cc951SDavid Hildenbrand } 676fc7cc951SDavid Hildenbrand 677fc7cc951SDavid Hildenbrand #define DEF_FLOAT_DCMASK(_TYPE) \ 678fc7cc951SDavid Hildenbrand static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1) \ 679fc7cc951SDavid Hildenbrand { \ 680fc7cc951SDavid Hildenbrand const bool neg = _TYPE##_is_neg(f1); \ 681fc7cc951SDavid Hildenbrand \ 682fc7cc951SDavid Hildenbrand /* Sorted by most common cases - only one class is possible */ \ 683fc7cc951SDavid Hildenbrand if (_TYPE##_is_normal(f1)) { \ 684fc7cc951SDavid Hildenbrand return dcmask(2, neg); \ 685fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_zero(f1)) { \ 686fc7cc951SDavid Hildenbrand return dcmask(0, neg); \ 687fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_denormal(f1)) { \ 688fc7cc951SDavid Hildenbrand return dcmask(4, neg); \ 689fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_infinity(f1)) { \ 690fc7cc951SDavid Hildenbrand return dcmask(6, neg); \ 691fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) { \ 692fc7cc951SDavid Hildenbrand return dcmask(8, neg); \ 693fc7cc951SDavid Hildenbrand } \ 694fc7cc951SDavid Hildenbrand /* signaling nan, as last remaining case */ \ 695fc7cc951SDavid Hildenbrand return dcmask(10, neg); \ 696fc7cc951SDavid Hildenbrand } 697fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float32) 698fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float64) 699fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float128) 700fc7cc951SDavid Hildenbrand 701e72ca652SBlue Swirl /* test data class 32-bit */ 702af39bc8cSAleksandar Markovic uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2) 703e72ca652SBlue Swirl { 704fc7cc951SDavid Hildenbrand return (m2 & float32_dcmask(env, f1)) != 0; 705e72ca652SBlue Swirl } 706e72ca652SBlue Swirl 707e72ca652SBlue Swirl /* test data class 64-bit */ 708af39bc8cSAleksandar Markovic uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2) 709e72ca652SBlue Swirl { 710fc7cc951SDavid Hildenbrand return (m2 & float64_dcmask(env, v1)) != 0; 711e72ca652SBlue Swirl } 712e72ca652SBlue Swirl 713e72ca652SBlue Swirl /* test data class 128-bit */ 714fc7cc951SDavid Hildenbrand uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2) 715e72ca652SBlue Swirl { 716fc7cc951SDavid Hildenbrand return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0; 717e72ca652SBlue Swirl } 718e72ca652SBlue Swirl 71916d7b2a4SRichard Henderson /* square root 32-bit */ 72016d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2) 721e72ca652SBlue Swirl { 72216d7b2a4SRichard Henderson float32 ret = float32_sqrt(f2, &env->fpu_status); 72316d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 72416d7b2a4SRichard Henderson return ret; 72516d7b2a4SRichard Henderson } 72616d7b2a4SRichard Henderson 72716d7b2a4SRichard Henderson /* square root 64-bit */ 72816d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2) 72916d7b2a4SRichard Henderson { 73016d7b2a4SRichard Henderson float64 ret = float64_sqrt(f2, &env->fpu_status); 73116d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 73216d7b2a4SRichard Henderson return ret; 73316d7b2a4SRichard Henderson } 73416d7b2a4SRichard Henderson 73516d7b2a4SRichard Henderson /* square root 128-bit */ 73616d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 73716d7b2a4SRichard Henderson { 73816d7b2a4SRichard Henderson float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status); 73916d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 74016d7b2a4SRichard Henderson return RET128(ret); 741e72ca652SBlue Swirl } 7428379bfdbSRichard Henderson 743411edc22SRichard Henderson static const int fpc_to_rnd[4] = { 7448379bfdbSRichard Henderson float_round_nearest_even, 7458379bfdbSRichard Henderson float_round_to_zero, 7468379bfdbSRichard Henderson float_round_up, 7478379bfdbSRichard Henderson float_round_down 7488379bfdbSRichard Henderson }; 7498379bfdbSRichard Henderson 750411edc22SRichard Henderson /* set fpc */ 751411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc) 752411edc22SRichard Henderson { 7538379bfdbSRichard Henderson /* Install everything in the main FPC. */ 7548379bfdbSRichard Henderson env->fpc = fpc; 7558379bfdbSRichard Henderson 7568379bfdbSRichard Henderson /* Install the rounding mode in the shadow fpu_status. */ 757411edc22SRichard Henderson set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status); 758411edc22SRichard Henderson } 759411edc22SRichard Henderson 760411edc22SRichard Henderson /* set fpc and signal */ 761411edc22SRichard Henderson void HELPER(sfas)(CPUS390XState *env, uint64_t val) 762411edc22SRichard Henderson { 763411edc22SRichard Henderson uint32_t signalling = env->fpc; 764411edc22SRichard Henderson uint32_t source = val; 765411edc22SRichard Henderson uint32_t s390_exc; 766411edc22SRichard Henderson 767411edc22SRichard Henderson /* The contents of the source operand are placed in the FPC register; 768411edc22SRichard Henderson then the flags in the FPC register are set to the logical OR of the 769411edc22SRichard Henderson signalling flags and the source flags. */ 770411edc22SRichard Henderson env->fpc = source | (signalling & 0x00ff0000); 771411edc22SRichard Henderson set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status); 772411edc22SRichard Henderson 773411edc22SRichard Henderson /* If any signalling flag is 1 and the corresponding source mask 774411edc22SRichard Henderson is also 1, a simulated-iee-exception trap occurs. */ 775411edc22SRichard Henderson s390_exc = (signalling >> 16) & (source >> 24); 776411edc22SRichard Henderson if (s390_exc) { 777bbf6ea3bSDavid Hildenbrand tcg_s390_data_exception(env, s390_exc | 3, GETPC()); 778411edc22SRichard Henderson } 7798379bfdbSRichard Henderson } 780