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 173*dce0a58fSDavid Hildenbrand static inline uint8_t round_from_m34(uint32_t m34) 174*dce0a58fSDavid Hildenbrand { 175*dce0a58fSDavid Hildenbrand return extract32(m34, 0, 4); 176*dce0a58fSDavid Hildenbrand } 177*dce0a58fSDavid Hildenbrand 178*dce0a58fSDavid Hildenbrand static inline bool xxc_from_m34(uint32_t m34) 179*dce0a58fSDavid Hildenbrand { 180*dce0a58fSDavid Hildenbrand /* XxC is bit 1 of m4 */ 181*dce0a58fSDavid Hildenbrand return extract32(m34, 4 + 3 - 1, 1); 182*dce0a58fSDavid Hildenbrand } 183*dce0a58fSDavid 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 */ 320587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 321e72ca652SBlue Swirl { 322587626f8SRichard Henderson float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); 323cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 324d0cfecb5SRichard Henderson return ret; 325e72ca652SBlue Swirl } 326e72ca652SBlue Swirl 327e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */ 328587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) 329e72ca652SBlue Swirl { 330587626f8SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 331cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 332d0cfecb5SRichard Henderson return RET128(ret); 333587626f8SRichard Henderson } 334e72ca652SBlue Swirl 335587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */ 336587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) 337587626f8SRichard Henderson { 338587626f8SRichard Henderson float128 ret = float32_to_float128(f2, &env->fpu_status); 339cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 340d0cfecb5SRichard Henderson return RET128(ret); 341e72ca652SBlue Swirl } 342e72ca652SBlue Swirl 343e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */ 344587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2) 345e72ca652SBlue Swirl { 346587626f8SRichard Henderson float32 ret = float64_to_float32(f2, &env->fpu_status); 347cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 348d0cfecb5SRichard Henderson return ret; 349e72ca652SBlue Swirl } 350e72ca652SBlue Swirl 351e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */ 352587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al) 353e72ca652SBlue Swirl { 354587626f8SRichard Henderson float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); 355cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 356d0cfecb5SRichard Henderson return ret; 357e72ca652SBlue Swirl } 358e72ca652SBlue Swirl 359587626f8SRichard Henderson /* 32-bit FP compare */ 360587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 361e72ca652SBlue Swirl { 362587626f8SRichard Henderson int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); 363cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 364587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 365e72ca652SBlue Swirl } 366e72ca652SBlue Swirl 367587626f8SRichard Henderson /* 64-bit FP compare */ 368587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 369e72ca652SBlue Swirl { 370587626f8SRichard Henderson int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); 371cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 372587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 373e72ca652SBlue Swirl } 374e72ca652SBlue Swirl 375587626f8SRichard Henderson /* 128-bit FP compare */ 376587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 377587626f8SRichard Henderson uint64_t bh, uint64_t bl) 378e72ca652SBlue Swirl { 379587626f8SRichard Henderson int cmp = float128_compare_quiet(make_float128(ah, al), 380587626f8SRichard Henderson make_float128(bh, bl), 381587626f8SRichard Henderson &env->fpu_status); 382cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 383587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 384e72ca652SBlue Swirl } 385e72ca652SBlue Swirl 386c0ee7015SDavid Hildenbrand int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3) 387e72ca652SBlue Swirl { 38868c8bd93SRichard Henderson int ret = env->fpu_status.float_rounding_mode; 389e72ca652SBlue Swirl switch (m3) { 390e72ca652SBlue Swirl case 0: 391e72ca652SBlue Swirl /* current mode */ 392e72ca652SBlue Swirl break; 393e72ca652SBlue Swirl case 1: 394e72ca652SBlue Swirl /* biased round no nearest */ 395e72ca652SBlue Swirl case 4: 396e72ca652SBlue Swirl /* round to nearest */ 397e72ca652SBlue Swirl set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); 398e72ca652SBlue Swirl break; 399e72ca652SBlue Swirl case 5: 400e72ca652SBlue Swirl /* round to zero */ 401e72ca652SBlue Swirl set_float_rounding_mode(float_round_to_zero, &env->fpu_status); 402e72ca652SBlue Swirl break; 403e72ca652SBlue Swirl case 6: 404e72ca652SBlue Swirl /* round to +inf */ 405e72ca652SBlue Swirl set_float_rounding_mode(float_round_up, &env->fpu_status); 406e72ca652SBlue Swirl break; 407e72ca652SBlue Swirl case 7: 408e72ca652SBlue Swirl /* round to -inf */ 409e72ca652SBlue Swirl set_float_rounding_mode(float_round_down, &env->fpu_status); 410e72ca652SBlue Swirl break; 411e72ca652SBlue Swirl } 41268c8bd93SRichard Henderson return ret; 413e72ca652SBlue Swirl } 414e72ca652SBlue Swirl 415c0ee7015SDavid Hildenbrand void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode) 416c0ee7015SDavid Hildenbrand { 417c0ee7015SDavid Hildenbrand set_float_rounding_mode(old_mode, &env->fpu_status); 418c0ee7015SDavid Hildenbrand } 419c0ee7015SDavid Hildenbrand 420683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */ 421*dce0a58fSDavid Hildenbrand uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m34) 422683bb9a8SRichard Henderson { 423*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 424683bb9a8SRichard Henderson float32 ret = int64_to_float32(v2, &env->fpu_status); 425c0ee7015SDavid Hildenbrand 426c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 427*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 428683bb9a8SRichard Henderson return ret; 429683bb9a8SRichard Henderson } 430683bb9a8SRichard Henderson 431683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */ 432*dce0a58fSDavid Hildenbrand uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m34) 433683bb9a8SRichard Henderson { 434*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 435683bb9a8SRichard Henderson float64 ret = int64_to_float64(v2, &env->fpu_status); 436c0ee7015SDavid Hildenbrand 437c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 438*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 439683bb9a8SRichard Henderson return ret; 440683bb9a8SRichard Henderson } 441683bb9a8SRichard Henderson 442683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */ 443*dce0a58fSDavid Hildenbrand uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m34) 444683bb9a8SRichard Henderson { 445*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 446683bb9a8SRichard Henderson float128 ret = int64_to_float128(v2, &env->fpu_status); 447c0ee7015SDavid Hildenbrand 448c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 449*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 450683bb9a8SRichard Henderson return RET128(ret); 451683bb9a8SRichard Henderson } 452683bb9a8SRichard Henderson 4532112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */ 454*dce0a58fSDavid Hildenbrand uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 4552112bf1bSRichard Henderson { 456*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 4572112bf1bSRichard Henderson float32 ret = uint64_to_float32(v2, &env->fpu_status); 458c0ee7015SDavid Hildenbrand 459c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 460*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 4612112bf1bSRichard Henderson return ret; 4622112bf1bSRichard Henderson } 4632112bf1bSRichard Henderson 4642112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */ 465*dce0a58fSDavid Hildenbrand uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 4662112bf1bSRichard Henderson { 467*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 4682112bf1bSRichard Henderson float64 ret = uint64_to_float64(v2, &env->fpu_status); 469c0ee7015SDavid Hildenbrand 470c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 471*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 4722112bf1bSRichard Henderson return ret; 4732112bf1bSRichard Henderson } 4742112bf1bSRichard Henderson 4752112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */ 476*dce0a58fSDavid Hildenbrand uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 4772112bf1bSRichard Henderson { 478*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 479d2d9feacSRichard Henderson float128 ret = uint64_to_float128(v2, &env->fpu_status); 480c0ee7015SDavid Hildenbrand 481c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 482*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 4832112bf1bSRichard Henderson return RET128(ret); 4842112bf1bSRichard Henderson } 4852112bf1bSRichard Henderson 486e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */ 487*dce0a58fSDavid Hildenbrand uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 488e72ca652SBlue Swirl { 489*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 49068c8bd93SRichard Henderson int64_t ret = float32_to_int64(v2, &env->fpu_status); 491c0ee7015SDavid Hildenbrand 492c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 493*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 49468c8bd93SRichard Henderson return ret; 495e72ca652SBlue Swirl } 496e72ca652SBlue Swirl 497e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */ 498*dce0a58fSDavid Hildenbrand uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 499e72ca652SBlue Swirl { 500*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 50168c8bd93SRichard Henderson int64_t ret = float64_to_int64(v2, &env->fpu_status); 502c0ee7015SDavid Hildenbrand 503c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 504*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 50568c8bd93SRichard Henderson return ret; 506e72ca652SBlue Swirl } 507e72ca652SBlue Swirl 508e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */ 509*dce0a58fSDavid Hildenbrand uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34) 510e72ca652SBlue Swirl { 511*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 51268c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 51368c8bd93SRichard Henderson int64_t ret = float128_to_int64(v2, &env->fpu_status); 514c0ee7015SDavid Hildenbrand 515c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 516*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 51768c8bd93SRichard Henderson return ret; 518e72ca652SBlue Swirl } 519e72ca652SBlue Swirl 520e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */ 521*dce0a58fSDavid Hildenbrand uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 522e72ca652SBlue Swirl { 523*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 52468c8bd93SRichard Henderson int32_t ret = float32_to_int32(v2, &env->fpu_status); 525c0ee7015SDavid Hildenbrand 526c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 527*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 52868c8bd93SRichard Henderson return ret; 529e72ca652SBlue Swirl } 530e72ca652SBlue Swirl 531e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */ 532*dce0a58fSDavid Hildenbrand uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 533e72ca652SBlue Swirl { 534*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 53568c8bd93SRichard Henderson int32_t ret = float64_to_int32(v2, &env->fpu_status); 536c0ee7015SDavid Hildenbrand 537c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 538*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 53968c8bd93SRichard Henderson return ret; 540e72ca652SBlue Swirl } 541e72ca652SBlue Swirl 542e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */ 543*dce0a58fSDavid Hildenbrand uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34) 544e72ca652SBlue Swirl { 545*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 54668c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 54768c8bd93SRichard Henderson int32_t ret = float128_to_int32(v2, &env->fpu_status); 548c0ee7015SDavid Hildenbrand 549c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 550*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 55168c8bd93SRichard Henderson return ret; 552e72ca652SBlue Swirl } 553e72ca652SBlue Swirl 5546ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */ 555*dce0a58fSDavid Hildenbrand uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 5566ac1b45fSRichard Henderson { 557*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 5586ac1b45fSRichard Henderson uint64_t ret; 559c0ee7015SDavid Hildenbrand 5606ac1b45fSRichard Henderson v2 = float32_to_float64(v2, &env->fpu_status); 5616ac1b45fSRichard Henderson ret = float64_to_uint64(v2, &env->fpu_status); 562c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 563*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 5646ac1b45fSRichard Henderson return ret; 5656ac1b45fSRichard Henderson } 5666ac1b45fSRichard Henderson 5676ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */ 568*dce0a58fSDavid Hildenbrand uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 5696ac1b45fSRichard Henderson { 570*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 5716ac1b45fSRichard Henderson uint64_t ret = float64_to_uint64(v2, &env->fpu_status); 572c0ee7015SDavid Hildenbrand 573c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 574*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 5756ac1b45fSRichard Henderson return ret; 5766ac1b45fSRichard Henderson } 5776ac1b45fSRichard Henderson 5786ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */ 579*dce0a58fSDavid Hildenbrand uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34) 5806ac1b45fSRichard Henderson { 581*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 5823af471f9SDavid Hildenbrand uint64_t ret = float128_to_uint64(make_float128(h, l), &env->fpu_status); 583c0ee7015SDavid Hildenbrand 584c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 585*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 5866ac1b45fSRichard Henderson return ret; 5876ac1b45fSRichard Henderson } 5886ac1b45fSRichard Henderson 5896ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */ 590*dce0a58fSDavid Hildenbrand uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 5916ac1b45fSRichard Henderson { 592*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 5936ac1b45fSRichard Henderson uint32_t ret = float32_to_uint32(v2, &env->fpu_status); 594c0ee7015SDavid Hildenbrand 595c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 596*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 5976ac1b45fSRichard Henderson return ret; 5986ac1b45fSRichard Henderson } 5996ac1b45fSRichard Henderson 6006ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */ 601*dce0a58fSDavid Hildenbrand uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m34) 6026ac1b45fSRichard Henderson { 603*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 6046ac1b45fSRichard Henderson uint32_t ret = float64_to_uint32(v2, &env->fpu_status); 605c0ee7015SDavid Hildenbrand 606c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 607*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 6086ac1b45fSRichard Henderson return ret; 6096ac1b45fSRichard Henderson } 6106ac1b45fSRichard Henderson 6116ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */ 612*dce0a58fSDavid Hildenbrand uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m34) 6136ac1b45fSRichard Henderson { 614*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 6153af471f9SDavid Hildenbrand uint32_t ret = float128_to_uint32(make_float128(h, l), &env->fpu_status); 616c0ee7015SDavid Hildenbrand 617c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 618*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 6196ac1b45fSRichard Henderson return ret; 6206ac1b45fSRichard Henderson } 6216ac1b45fSRichard Henderson 622ed0bceceSAurelien Jarno /* round to integer 32-bit */ 623*dce0a58fSDavid Hildenbrand uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m34) 624ed0bceceSAurelien Jarno { 625*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 626ed0bceceSAurelien Jarno float32 ret = float32_round_to_int(f2, &env->fpu_status); 627c0ee7015SDavid Hildenbrand 628c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 629*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 630ed0bceceSAurelien Jarno return ret; 631ed0bceceSAurelien Jarno } 632ed0bceceSAurelien Jarno 633ed0bceceSAurelien Jarno /* round to integer 64-bit */ 634*dce0a58fSDavid Hildenbrand uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m34) 635ed0bceceSAurelien Jarno { 636*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 637ed0bceceSAurelien Jarno float64 ret = float64_round_to_int(f2, &env->fpu_status); 638c0ee7015SDavid Hildenbrand 639c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 640*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 641ed0bceceSAurelien Jarno return ret; 642ed0bceceSAurelien Jarno } 643ed0bceceSAurelien Jarno 644ed0bceceSAurelien Jarno /* round to integer 128-bit */ 645*dce0a58fSDavid Hildenbrand uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, 646*dce0a58fSDavid Hildenbrand uint32_t m34) 647ed0bceceSAurelien Jarno { 648*dce0a58fSDavid Hildenbrand int old_mode = s390_swap_bfp_rounding_mode(env, round_from_m34(m34)); 649ed0bceceSAurelien Jarno float128 ret = float128_round_to_int(make_float128(ah, al), 650ed0bceceSAurelien Jarno &env->fpu_status); 651cf97f9ffSDavid Hildenbrand 652c0ee7015SDavid Hildenbrand s390_restore_bfp_rounding_mode(env, old_mode); 653*dce0a58fSDavid Hildenbrand handle_exceptions(env, xxc_from_m34(m34), GETPC()); 654ed0bceceSAurelien Jarno return RET128(ret); 655ed0bceceSAurelien Jarno } 656ed0bceceSAurelien Jarno 6579c8be598SAurelien Jarno /* 32-bit FP compare and signal */ 6589c8be598SAurelien Jarno uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 6599c8be598SAurelien Jarno { 6609c8be598SAurelien Jarno int cmp = float32_compare(f1, f2, &env->fpu_status); 661cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 6629c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6639c8be598SAurelien Jarno } 6649c8be598SAurelien Jarno 6659c8be598SAurelien Jarno /* 64-bit FP compare and signal */ 6669c8be598SAurelien Jarno uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 6679c8be598SAurelien Jarno { 6689c8be598SAurelien Jarno int cmp = float64_compare(f1, f2, &env->fpu_status); 669cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 6709c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6719c8be598SAurelien Jarno } 6729c8be598SAurelien Jarno 6739c8be598SAurelien Jarno /* 128-bit FP compare and signal */ 6749c8be598SAurelien Jarno uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 6759c8be598SAurelien Jarno uint64_t bh, uint64_t bl) 6769c8be598SAurelien Jarno { 6779c8be598SAurelien Jarno int cmp = float128_compare(make_float128(ah, al), 6789c8be598SAurelien Jarno make_float128(bh, bl), 6799c8be598SAurelien Jarno &env->fpu_status); 680cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 6819c8be598SAurelien Jarno return float_comp_to_cc(env, cmp); 6829c8be598SAurelien Jarno } 6839c8be598SAurelien Jarno 684722bfec3SRichard Henderson /* 32-bit FP multiply and add */ 685722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, 686722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 687e72ca652SBlue Swirl { 688722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status); 689cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 690722bfec3SRichard Henderson return ret; 691722bfec3SRichard Henderson } 692e72ca652SBlue Swirl 693722bfec3SRichard Henderson /* 64-bit FP multiply and add */ 694722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1, 695722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 696722bfec3SRichard Henderson { 697722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status); 698cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 699722bfec3SRichard Henderson return ret; 700722bfec3SRichard Henderson } 701722bfec3SRichard Henderson 702722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */ 703722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1, 704722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 705722bfec3SRichard Henderson { 706722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c, 707e72ca652SBlue Swirl &env->fpu_status); 708cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 709722bfec3SRichard Henderson return ret; 710e72ca652SBlue Swirl } 711e72ca652SBlue Swirl 712722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */ 713722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1, 714722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 715e72ca652SBlue Swirl { 716722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c, 717e72ca652SBlue Swirl &env->fpu_status); 718cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 719722bfec3SRichard Henderson return ret; 720e72ca652SBlue Swirl } 721e72ca652SBlue Swirl 722fc7cc951SDavid Hildenbrand /* The rightmost bit has the number 11. */ 723fc7cc951SDavid Hildenbrand static inline uint16_t dcmask(int bit, bool neg) 724fc7cc951SDavid Hildenbrand { 725fc7cc951SDavid Hildenbrand return 1 << (11 - bit - neg); 726fc7cc951SDavid Hildenbrand } 727fc7cc951SDavid Hildenbrand 728fc7cc951SDavid Hildenbrand #define DEF_FLOAT_DCMASK(_TYPE) \ 729fc7cc951SDavid Hildenbrand static uint16_t _TYPE##_dcmask(CPUS390XState *env, _TYPE f1) \ 730fc7cc951SDavid Hildenbrand { \ 731fc7cc951SDavid Hildenbrand const bool neg = _TYPE##_is_neg(f1); \ 732fc7cc951SDavid Hildenbrand \ 733fc7cc951SDavid Hildenbrand /* Sorted by most common cases - only one class is possible */ \ 734fc7cc951SDavid Hildenbrand if (_TYPE##_is_normal(f1)) { \ 735fc7cc951SDavid Hildenbrand return dcmask(2, neg); \ 736fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_zero(f1)) { \ 737fc7cc951SDavid Hildenbrand return dcmask(0, neg); \ 738fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_denormal(f1)) { \ 739fc7cc951SDavid Hildenbrand return dcmask(4, neg); \ 740fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_infinity(f1)) { \ 741fc7cc951SDavid Hildenbrand return dcmask(6, neg); \ 742fc7cc951SDavid Hildenbrand } else if (_TYPE##_is_quiet_nan(f1, &env->fpu_status)) { \ 743fc7cc951SDavid Hildenbrand return dcmask(8, neg); \ 744fc7cc951SDavid Hildenbrand } \ 745fc7cc951SDavid Hildenbrand /* signaling nan, as last remaining case */ \ 746fc7cc951SDavid Hildenbrand return dcmask(10, neg); \ 747fc7cc951SDavid Hildenbrand } 748fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float32) 749fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float64) 750fc7cc951SDavid Hildenbrand DEF_FLOAT_DCMASK(float128) 751fc7cc951SDavid Hildenbrand 752e72ca652SBlue Swirl /* test data class 32-bit */ 753af39bc8cSAleksandar Markovic uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2) 754e72ca652SBlue Swirl { 755fc7cc951SDavid Hildenbrand return (m2 & float32_dcmask(env, f1)) != 0; 756e72ca652SBlue Swirl } 757e72ca652SBlue Swirl 758e72ca652SBlue Swirl /* test data class 64-bit */ 759af39bc8cSAleksandar Markovic uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2) 760e72ca652SBlue Swirl { 761fc7cc951SDavid Hildenbrand return (m2 & float64_dcmask(env, v1)) != 0; 762e72ca652SBlue Swirl } 763e72ca652SBlue Swirl 764e72ca652SBlue Swirl /* test data class 128-bit */ 765fc7cc951SDavid Hildenbrand uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint64_t m2) 766e72ca652SBlue Swirl { 767fc7cc951SDavid Hildenbrand return (m2 & float128_dcmask(env, make_float128(ah, al))) != 0; 768e72ca652SBlue Swirl } 769e72ca652SBlue Swirl 77016d7b2a4SRichard Henderson /* square root 32-bit */ 77116d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2) 772e72ca652SBlue Swirl { 77316d7b2a4SRichard Henderson float32 ret = float32_sqrt(f2, &env->fpu_status); 774cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 77516d7b2a4SRichard Henderson return ret; 77616d7b2a4SRichard Henderson } 77716d7b2a4SRichard Henderson 77816d7b2a4SRichard Henderson /* square root 64-bit */ 77916d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2) 78016d7b2a4SRichard Henderson { 78116d7b2a4SRichard Henderson float64 ret = float64_sqrt(f2, &env->fpu_status); 782cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 78316d7b2a4SRichard Henderson return ret; 78416d7b2a4SRichard Henderson } 78516d7b2a4SRichard Henderson 78616d7b2a4SRichard Henderson /* square root 128-bit */ 78716d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 78816d7b2a4SRichard Henderson { 78916d7b2a4SRichard Henderson float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status); 790cf97f9ffSDavid Hildenbrand handle_exceptions(env, false, GETPC()); 79116d7b2a4SRichard Henderson return RET128(ret); 792e72ca652SBlue Swirl } 7938379bfdbSRichard Henderson 7942aea83c6SDavid Hildenbrand static const int fpc_to_rnd[8] = { 7958379bfdbSRichard Henderson float_round_nearest_even, 7968379bfdbSRichard Henderson float_round_to_zero, 7978379bfdbSRichard Henderson float_round_up, 7982aea83c6SDavid Hildenbrand float_round_down, 7992aea83c6SDavid Hildenbrand -1, 8002aea83c6SDavid Hildenbrand -1, 8012aea83c6SDavid Hildenbrand -1, 8022aea83c6SDavid Hildenbrand float_round_to_odd, 8038379bfdbSRichard Henderson }; 8048379bfdbSRichard Henderson 805411edc22SRichard Henderson /* set fpc */ 806411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc) 807411edc22SRichard Henderson { 8082aea83c6SDavid Hildenbrand if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u || 8092aea83c6SDavid Hildenbrand (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) { 8102aea83c6SDavid Hildenbrand s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC()); 8112aea83c6SDavid Hildenbrand } 8122aea83c6SDavid Hildenbrand 8138379bfdbSRichard Henderson /* Install everything in the main FPC. */ 8148379bfdbSRichard Henderson env->fpc = fpc; 8158379bfdbSRichard Henderson 8168379bfdbSRichard Henderson /* Install the rounding mode in the shadow fpu_status. */ 8172aea83c6SDavid Hildenbrand set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status); 818411edc22SRichard Henderson } 819411edc22SRichard Henderson 820411edc22SRichard Henderson /* set fpc and signal */ 821f66a0ecfSDavid Hildenbrand void HELPER(sfas)(CPUS390XState *env, uint64_t fpc) 822411edc22SRichard Henderson { 823411edc22SRichard Henderson uint32_t signalling = env->fpc; 824411edc22SRichard Henderson uint32_t s390_exc; 825411edc22SRichard Henderson 8262aea83c6SDavid Hildenbrand if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u || 8272aea83c6SDavid Hildenbrand (!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) { 8282aea83c6SDavid Hildenbrand s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC()); 8292aea83c6SDavid Hildenbrand } 8302aea83c6SDavid Hildenbrand 831f66a0ecfSDavid Hildenbrand /* 832f66a0ecfSDavid Hildenbrand * FPC is set to the FPC operand with a bitwise OR of the signalling 833f66a0ecfSDavid Hildenbrand * flags. 834f66a0ecfSDavid Hildenbrand */ 835f66a0ecfSDavid Hildenbrand env->fpc = fpc | (signalling & 0x00ff0000); 8362aea83c6SDavid Hildenbrand set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status); 837411edc22SRichard Henderson 838f66a0ecfSDavid Hildenbrand /* 839f66a0ecfSDavid Hildenbrand * If any signaling flag is enabled in the new FPC mask, a 840f66a0ecfSDavid Hildenbrand * simulated-iee-exception exception occurs. 841f66a0ecfSDavid Hildenbrand */ 842f66a0ecfSDavid Hildenbrand s390_exc = (signalling >> 16) & (fpc >> 24); 843411edc22SRichard Henderson if (s390_exc) { 8448772bbe4SDavid Hildenbrand if (s390_exc & S390_IEEE_MASK_INVALID) { 8458772bbe4SDavid Hildenbrand s390_exc = S390_IEEE_MASK_INVALID; 8468772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_DIVBYZERO) { 8478772bbe4SDavid Hildenbrand s390_exc = S390_IEEE_MASK_DIVBYZERO; 8488772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_OVERFLOW) { 8498772bbe4SDavid Hildenbrand s390_exc &= (S390_IEEE_MASK_OVERFLOW | S390_IEEE_MASK_INEXACT); 8508772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_UNDERFLOW) { 8518772bbe4SDavid Hildenbrand s390_exc &= (S390_IEEE_MASK_UNDERFLOW | S390_IEEE_MASK_INEXACT); 8528772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_INEXACT) { 8538772bbe4SDavid Hildenbrand s390_exc = S390_IEEE_MASK_INEXACT; 8548772bbe4SDavid Hildenbrand } else if (s390_exc & S390_IEEE_MASK_QUANTUM) { 8558772bbe4SDavid Hildenbrand s390_exc = S390_IEEE_MASK_QUANTUM; 8568772bbe4SDavid Hildenbrand } 857bbf6ea3bSDavid Hildenbrand tcg_s390_data_exception(env, s390_exc | 3, GETPC()); 858411edc22SRichard Henderson } 8598379bfdbSRichard Henderson } 860b9c737f5SDavid Hildenbrand 861b9c737f5SDavid Hildenbrand /* set bfp rounding mode */ 862b9c737f5SDavid Hildenbrand void HELPER(srnm)(CPUS390XState *env, uint64_t rnd) 863b9c737f5SDavid Hildenbrand { 864b9c737f5SDavid Hildenbrand if (rnd > 0x7 || fpc_to_rnd[rnd & 0x7] == -1) { 865b9c737f5SDavid Hildenbrand s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC()); 866b9c737f5SDavid Hildenbrand } 867b9c737f5SDavid Hildenbrand 868b9c737f5SDavid Hildenbrand env->fpc = deposit32(env->fpc, 0, 3, rnd); 869b9c737f5SDavid Hildenbrand set_float_rounding_mode(fpc_to_rnd[rnd & 0x7], &env->fpu_status); 870b9c737f5SDavid Hildenbrand } 871