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 10e72ca652SBlue Swirl * version 2 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 21e72ca652SBlue Swirl #include "cpu.h" 22e72ca652SBlue Swirl #include "helper.h" 23e72ca652SBlue Swirl 2419b0516fSBlue Swirl #if !defined(CONFIG_USER_ONLY) 25022c62cbSPaolo Bonzini #include "exec/softmmu_exec.h" 26e72ca652SBlue Swirl #endif 27e72ca652SBlue Swirl 28e72ca652SBlue Swirl /* #define DEBUG_HELPER */ 29e72ca652SBlue Swirl #ifdef DEBUG_HELPER 30e72ca652SBlue Swirl #define HELPER_LOG(x...) qemu_log(x) 31e72ca652SBlue Swirl #else 32e72ca652SBlue Swirl #define HELPER_LOG(x...) 33e72ca652SBlue Swirl #endif 34e72ca652SBlue Swirl 35587626f8SRichard Henderson #define RET128(F) (env->retxl = F.low, F.high) 36587626f8SRichard Henderson 37587626f8SRichard Henderson #define convert_bit(mask, from, to) \ 38587626f8SRichard Henderson (to < from \ 39587626f8SRichard Henderson ? (mask / (from / to)) & to \ 40587626f8SRichard Henderson : (mask & from) * (to / from)) 41587626f8SRichard Henderson 42587626f8SRichard Henderson static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr) 43587626f8SRichard Henderson { 44587626f8SRichard Henderson /* Install the DXC code. */ 45587626f8SRichard Henderson env->fpc = (env->fpc & ~0xff00) | (dxc << 8); 46587626f8SRichard Henderson /* Trap. */ 47587626f8SRichard Henderson runtime_exception(env, PGM_DATA, retaddr); 48587626f8SRichard Henderson } 49587626f8SRichard Henderson 50587626f8SRichard Henderson /* Should be called after any operation that may raise IEEE exceptions. */ 51587626f8SRichard Henderson static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr) 52587626f8SRichard Henderson { 53587626f8SRichard Henderson unsigned s390_exc, qemu_exc; 54587626f8SRichard Henderson 55587626f8SRichard Henderson /* Get the exceptions raised by the current operation. Reset the 56587626f8SRichard Henderson fpu_status contents so that the next operation has a clean slate. */ 57587626f8SRichard Henderson qemu_exc = env->fpu_status.float_exception_flags; 58587626f8SRichard Henderson if (qemu_exc == 0) { 59587626f8SRichard Henderson return; 60587626f8SRichard Henderson } 61587626f8SRichard Henderson env->fpu_status.float_exception_flags = 0; 62587626f8SRichard Henderson 63587626f8SRichard Henderson /* Convert softfloat exception bits to s390 exception bits. */ 64587626f8SRichard Henderson s390_exc = 0; 65587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80); 66587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40); 67587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20); 68587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10); 69587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08); 70587626f8SRichard Henderson 71587626f8SRichard Henderson /* Install the exceptions that we raised. */ 72587626f8SRichard Henderson env->fpc |= s390_exc << 16; 73587626f8SRichard Henderson 74587626f8SRichard Henderson /* Send signals for enabled exceptions. */ 75587626f8SRichard Henderson s390_exc &= env->fpc >> 24; 76587626f8SRichard Henderson if (s390_exc) { 77587626f8SRichard Henderson ieee_exception(env, s390_exc, retaddr); 78587626f8SRichard Henderson } 79587626f8SRichard Henderson } 80587626f8SRichard Henderson 81449c0d70SBlue Swirl static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) 82e72ca652SBlue Swirl { 83e72ca652SBlue Swirl switch (float_compare) { 84e72ca652SBlue Swirl case float_relation_equal: 85e72ca652SBlue Swirl return 0; 86e72ca652SBlue Swirl case float_relation_less: 87e72ca652SBlue Swirl return 1; 88e72ca652SBlue Swirl case float_relation_greater: 89e72ca652SBlue Swirl return 2; 90e72ca652SBlue Swirl case float_relation_unordered: 91e72ca652SBlue Swirl return 3; 92e72ca652SBlue Swirl default: 93e72ca652SBlue Swirl cpu_abort(env, "unknown return value for float compare\n"); 94e72ca652SBlue Swirl } 95e72ca652SBlue Swirl } 96e72ca652SBlue Swirl 97e72ca652SBlue Swirl /* condition codes for unary FP ops */ 98e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v) 99e72ca652SBlue Swirl { 100e72ca652SBlue Swirl if (float32_is_any_nan(v)) { 101e72ca652SBlue Swirl return 3; 102e72ca652SBlue Swirl } else if (float32_is_zero(v)) { 103e72ca652SBlue Swirl return 0; 104e72ca652SBlue Swirl } else if (float32_is_neg(v)) { 105e72ca652SBlue Swirl return 1; 106e72ca652SBlue Swirl } else { 107e72ca652SBlue Swirl return 2; 108e72ca652SBlue Swirl } 109e72ca652SBlue Swirl } 110e72ca652SBlue Swirl 111e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v) 112e72ca652SBlue Swirl { 113e72ca652SBlue Swirl if (float64_is_any_nan(v)) { 114e72ca652SBlue Swirl return 3; 115e72ca652SBlue Swirl } else if (float64_is_zero(v)) { 116e72ca652SBlue Swirl return 0; 117e72ca652SBlue Swirl } else if (float64_is_neg(v)) { 118e72ca652SBlue Swirl return 1; 119e72ca652SBlue Swirl } else { 120e72ca652SBlue Swirl return 2; 121e72ca652SBlue Swirl } 122e72ca652SBlue Swirl } 123e72ca652SBlue Swirl 124587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v) 125e72ca652SBlue Swirl { 126e72ca652SBlue Swirl if (float128_is_any_nan(v)) { 127e72ca652SBlue Swirl return 3; 128e72ca652SBlue Swirl } else if (float128_is_zero(v)) { 129e72ca652SBlue Swirl return 0; 130e72ca652SBlue Swirl } else if (float128_is_neg(v)) { 131e72ca652SBlue Swirl return 1; 132e72ca652SBlue Swirl } else { 133e72ca652SBlue Swirl return 2; 134e72ca652SBlue Swirl } 135e72ca652SBlue Swirl } 136e72ca652SBlue Swirl 137587626f8SRichard Henderson /* 32-bit FP addition */ 138587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 139e72ca652SBlue Swirl { 140587626f8SRichard Henderson float32 ret = float32_add(f1, f2, &env->fpu_status); 141587626f8SRichard Henderson handle_exceptions(env, GETPC()); 142587626f8SRichard Henderson return ret; 143e72ca652SBlue Swirl } 144e72ca652SBlue Swirl 145587626f8SRichard Henderson /* 64-bit FP addition */ 146587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 147e72ca652SBlue Swirl { 148587626f8SRichard Henderson float64 ret = float64_add(f1, f2, &env->fpu_status); 149587626f8SRichard Henderson handle_exceptions(env, GETPC()); 150587626f8SRichard Henderson return ret; 151587626f8SRichard Henderson } 152e72ca652SBlue Swirl 153587626f8SRichard Henderson /* 128-bit FP addition */ 154587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al, 155587626f8SRichard Henderson uint64_t bh, uint64_t bl) 156587626f8SRichard Henderson { 157587626f8SRichard Henderson float128 ret = float128_add(make_float128(ah, al), 158587626f8SRichard Henderson make_float128(bh, bl), 159587626f8SRichard Henderson &env->fpu_status); 160587626f8SRichard Henderson handle_exceptions(env, GETPC()); 161587626f8SRichard Henderson return RET128(ret); 162e72ca652SBlue Swirl } 163e72ca652SBlue Swirl 1641a800a2dSRichard Henderson /* 32-bit FP subtraction */ 1651a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 166e72ca652SBlue Swirl { 1671a800a2dSRichard Henderson float32 ret = float32_sub(f1, f2, &env->fpu_status); 1681a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 1691a800a2dSRichard Henderson return ret; 170e72ca652SBlue Swirl } 171e72ca652SBlue Swirl 1721a800a2dSRichard Henderson /* 64-bit FP subtraction */ 1731a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 174e72ca652SBlue Swirl { 1751a800a2dSRichard Henderson float64 ret = float64_sub(f1, f2, &env->fpu_status); 1761a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 1771a800a2dSRichard Henderson return ret; 1781a800a2dSRichard Henderson } 179e72ca652SBlue Swirl 1801a800a2dSRichard Henderson /* 128-bit FP subtraction */ 1811a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 1821a800a2dSRichard Henderson uint64_t bh, uint64_t bl) 1831a800a2dSRichard Henderson { 1841a800a2dSRichard Henderson float128 ret = float128_sub(make_float128(ah, al), 1851a800a2dSRichard Henderson make_float128(bh, bl), 1861a800a2dSRichard Henderson &env->fpu_status); 1871a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 1881a800a2dSRichard Henderson return RET128(ret); 189e72ca652SBlue Swirl } 190e72ca652SBlue Swirl 191f08a5c31SRichard Henderson /* 32-bit FP division */ 192f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 193e72ca652SBlue Swirl { 194f08a5c31SRichard Henderson float32 ret = float32_div(f1, f2, &env->fpu_status); 195f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 196f08a5c31SRichard Henderson return ret; 197e72ca652SBlue Swirl } 198e72ca652SBlue Swirl 199f08a5c31SRichard Henderson /* 64-bit FP division */ 200f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 201e72ca652SBlue Swirl { 202f08a5c31SRichard Henderson float64 ret = float64_div(f1, f2, &env->fpu_status); 203f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 204f08a5c31SRichard Henderson return ret; 205f08a5c31SRichard Henderson } 206e72ca652SBlue Swirl 207f08a5c31SRichard Henderson /* 128-bit FP division */ 208f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 209f08a5c31SRichard Henderson uint64_t bh, uint64_t bl) 210f08a5c31SRichard Henderson { 211f08a5c31SRichard Henderson float128 ret = float128_div(make_float128(ah, al), 212f08a5c31SRichard Henderson make_float128(bh, bl), 213f08a5c31SRichard Henderson &env->fpu_status); 214f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 215f08a5c31SRichard Henderson return RET128(ret); 216e72ca652SBlue Swirl } 217e72ca652SBlue Swirl 21883b00736SRichard Henderson /* 32-bit FP multiplication */ 21983b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 220e72ca652SBlue Swirl { 22183b00736SRichard Henderson float32 ret = float32_mul(f1, f2, &env->fpu_status); 22283b00736SRichard Henderson handle_exceptions(env, GETPC()); 22383b00736SRichard Henderson return ret; 224e72ca652SBlue Swirl } 225e72ca652SBlue Swirl 22683b00736SRichard Henderson /* 64-bit FP multiplication */ 22783b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 228e72ca652SBlue Swirl { 22983b00736SRichard Henderson float64 ret = float64_mul(f1, f2, &env->fpu_status); 23083b00736SRichard Henderson handle_exceptions(env, GETPC()); 23183b00736SRichard Henderson return ret; 23283b00736SRichard Henderson } 233e72ca652SBlue Swirl 23483b00736SRichard Henderson /* 64/32-bit FP multiplication */ 23583b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 23683b00736SRichard Henderson { 23783b00736SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 23883b00736SRichard Henderson ret = float64_mul(f1, ret, &env->fpu_status); 23983b00736SRichard Henderson handle_exceptions(env, GETPC()); 24083b00736SRichard Henderson return ret; 24183b00736SRichard Henderson } 24283b00736SRichard Henderson 24383b00736SRichard Henderson /* 128-bit FP multiplication */ 24483b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 24583b00736SRichard Henderson uint64_t bh, uint64_t bl) 24683b00736SRichard Henderson { 24783b00736SRichard Henderson float128 ret = float128_mul(make_float128(ah, al), 24883b00736SRichard Henderson make_float128(bh, bl), 24983b00736SRichard Henderson &env->fpu_status); 25083b00736SRichard Henderson handle_exceptions(env, GETPC()); 25183b00736SRichard Henderson return RET128(ret); 25283b00736SRichard Henderson } 25383b00736SRichard Henderson 25483b00736SRichard Henderson /* 128/64-bit FP multiplication */ 25583b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al, 25683b00736SRichard Henderson uint64_t f2) 25783b00736SRichard Henderson { 25883b00736SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 25983b00736SRichard Henderson ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status); 26083b00736SRichard Henderson handle_exceptions(env, GETPC()); 26183b00736SRichard Henderson return RET128(ret); 262e72ca652SBlue Swirl } 263e72ca652SBlue Swirl 264e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */ 265587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2) 266e72ca652SBlue Swirl { 267587626f8SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 268587626f8SRichard Henderson handle_exceptions(env, GETPC()); 269587626f8SRichard Henderson return ret; 270e72ca652SBlue Swirl } 271e72ca652SBlue Swirl 272e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */ 273587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 274e72ca652SBlue Swirl { 275587626f8SRichard Henderson float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); 276587626f8SRichard Henderson handle_exceptions(env, GETPC()); 277587626f8SRichard Henderson return ret; 278e72ca652SBlue Swirl } 279e72ca652SBlue Swirl 280e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */ 281587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) 282e72ca652SBlue Swirl { 283587626f8SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 284587626f8SRichard Henderson handle_exceptions(env, GETPC()); 285587626f8SRichard Henderson return RET128(ret); 286587626f8SRichard Henderson } 287e72ca652SBlue Swirl 288587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */ 289587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) 290587626f8SRichard Henderson { 291587626f8SRichard Henderson float128 ret = float32_to_float128(f2, &env->fpu_status); 292587626f8SRichard Henderson handle_exceptions(env, GETPC()); 293587626f8SRichard Henderson return RET128(ret); 294e72ca652SBlue Swirl } 295e72ca652SBlue Swirl 296e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */ 297587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2) 298e72ca652SBlue Swirl { 299587626f8SRichard Henderson float32 ret = float64_to_float32(f2, &env->fpu_status); 300587626f8SRichard Henderson handle_exceptions(env, GETPC()); 301587626f8SRichard Henderson return ret; 302e72ca652SBlue Swirl } 303e72ca652SBlue Swirl 304e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */ 305587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al) 306e72ca652SBlue Swirl { 307587626f8SRichard Henderson float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); 308587626f8SRichard Henderson handle_exceptions(env, GETPC()); 309587626f8SRichard Henderson return ret; 310e72ca652SBlue Swirl } 311e72ca652SBlue Swirl 312587626f8SRichard Henderson /* 32-bit FP compare */ 313587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 314e72ca652SBlue Swirl { 315587626f8SRichard Henderson int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); 316587626f8SRichard Henderson handle_exceptions(env, GETPC()); 317587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 318e72ca652SBlue Swirl } 319e72ca652SBlue Swirl 320587626f8SRichard Henderson /* 64-bit FP compare */ 321587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 322e72ca652SBlue Swirl { 323587626f8SRichard Henderson int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); 324587626f8SRichard Henderson handle_exceptions(env, GETPC()); 325587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 326e72ca652SBlue Swirl } 327e72ca652SBlue Swirl 328587626f8SRichard Henderson /* 128-bit FP compare */ 329587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 330587626f8SRichard Henderson uint64_t bh, uint64_t bl) 331e72ca652SBlue Swirl { 332587626f8SRichard Henderson int cmp = float128_compare_quiet(make_float128(ah, al), 333587626f8SRichard Henderson make_float128(bh, bl), 334587626f8SRichard Henderson &env->fpu_status); 335587626f8SRichard Henderson handle_exceptions(env, GETPC()); 336587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 337e72ca652SBlue Swirl } 338e72ca652SBlue Swirl 33968c8bd93SRichard Henderson static int swap_round_mode(CPUS390XState *env, int m3) 340e72ca652SBlue Swirl { 34168c8bd93SRichard Henderson int ret = env->fpu_status.float_rounding_mode; 342e72ca652SBlue Swirl switch (m3) { 343e72ca652SBlue Swirl case 0: 344e72ca652SBlue Swirl /* current mode */ 345e72ca652SBlue Swirl break; 346e72ca652SBlue Swirl case 1: 347e72ca652SBlue Swirl /* biased round no nearest */ 348e72ca652SBlue Swirl case 4: 349e72ca652SBlue Swirl /* round to nearest */ 350e72ca652SBlue Swirl set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); 351e72ca652SBlue Swirl break; 352e72ca652SBlue Swirl case 5: 353e72ca652SBlue Swirl /* round to zero */ 354e72ca652SBlue Swirl set_float_rounding_mode(float_round_to_zero, &env->fpu_status); 355e72ca652SBlue Swirl break; 356e72ca652SBlue Swirl case 6: 357e72ca652SBlue Swirl /* round to +inf */ 358e72ca652SBlue Swirl set_float_rounding_mode(float_round_up, &env->fpu_status); 359e72ca652SBlue Swirl break; 360e72ca652SBlue Swirl case 7: 361e72ca652SBlue Swirl /* round to -inf */ 362e72ca652SBlue Swirl set_float_rounding_mode(float_round_down, &env->fpu_status); 363e72ca652SBlue Swirl break; 364e72ca652SBlue Swirl } 36568c8bd93SRichard Henderson return ret; 366e72ca652SBlue Swirl } 367e72ca652SBlue Swirl 368683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */ 369683bb9a8SRichard Henderson uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3) 370683bb9a8SRichard Henderson { 371683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 372683bb9a8SRichard Henderson float32 ret = int64_to_float32(v2, &env->fpu_status); 373683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 374683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 375683bb9a8SRichard Henderson return ret; 376683bb9a8SRichard Henderson } 377683bb9a8SRichard Henderson 378683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */ 379683bb9a8SRichard Henderson uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3) 380683bb9a8SRichard Henderson { 381683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 382683bb9a8SRichard Henderson float64 ret = int64_to_float64(v2, &env->fpu_status); 383683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 384683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 385683bb9a8SRichard Henderson return ret; 386683bb9a8SRichard Henderson } 387683bb9a8SRichard Henderson 388683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */ 389683bb9a8SRichard Henderson uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3) 390683bb9a8SRichard Henderson { 391683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 392683bb9a8SRichard Henderson float128 ret = int64_to_float128(v2, &env->fpu_status); 393683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 394683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 395683bb9a8SRichard Henderson return RET128(ret); 396683bb9a8SRichard Henderson } 397683bb9a8SRichard Henderson 398e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */ 39968c8bd93SRichard Henderson uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 400e72ca652SBlue Swirl { 40168c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 40268c8bd93SRichard Henderson int64_t ret = float32_to_int64(v2, &env->fpu_status); 40368c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 40468c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 40568c8bd93SRichard Henderson return ret; 406e72ca652SBlue Swirl } 407e72ca652SBlue Swirl 408e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */ 40968c8bd93SRichard Henderson uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 410e72ca652SBlue Swirl { 41168c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 41268c8bd93SRichard Henderson int64_t ret = float64_to_int64(v2, &env->fpu_status); 41368c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 41468c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 41568c8bd93SRichard Henderson return ret; 416e72ca652SBlue Swirl } 417e72ca652SBlue Swirl 418e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */ 41968c8bd93SRichard Henderson uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 420e72ca652SBlue Swirl { 42168c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 42268c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 42368c8bd93SRichard Henderson int64_t ret = float128_to_int64(v2, &env->fpu_status); 42468c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 42568c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 42668c8bd93SRichard Henderson return ret; 427e72ca652SBlue Swirl } 428e72ca652SBlue Swirl 429e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */ 43068c8bd93SRichard Henderson uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 431e72ca652SBlue Swirl { 43268c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 43368c8bd93SRichard Henderson int32_t ret = float32_to_int32(v2, &env->fpu_status); 43468c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 43568c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 43668c8bd93SRichard Henderson return ret; 437e72ca652SBlue Swirl } 438e72ca652SBlue Swirl 439e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */ 44068c8bd93SRichard Henderson uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 441e72ca652SBlue Swirl { 44268c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 44368c8bd93SRichard Henderson int32_t ret = float64_to_int32(v2, &env->fpu_status); 44468c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 44568c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 44668c8bd93SRichard Henderson return ret; 447e72ca652SBlue Swirl } 448e72ca652SBlue Swirl 449e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */ 45068c8bd93SRichard Henderson uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 451e72ca652SBlue Swirl { 45268c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 45368c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 45468c8bd93SRichard Henderson int32_t ret = float128_to_int32(v2, &env->fpu_status); 45568c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 45668c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 45768c8bd93SRichard Henderson return ret; 458e72ca652SBlue Swirl } 459e72ca652SBlue Swirl 460722bfec3SRichard Henderson /* 32-bit FP multiply and add */ 461722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, 462722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 463e72ca652SBlue Swirl { 464722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status); 465722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 466722bfec3SRichard Henderson return ret; 467722bfec3SRichard Henderson } 468e72ca652SBlue Swirl 469722bfec3SRichard Henderson /* 64-bit FP multiply and add */ 470722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1, 471722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 472722bfec3SRichard Henderson { 473722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status); 474722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 475722bfec3SRichard Henderson return ret; 476722bfec3SRichard Henderson } 477722bfec3SRichard Henderson 478722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */ 479722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1, 480722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 481722bfec3SRichard Henderson { 482722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c, 483e72ca652SBlue Swirl &env->fpu_status); 484722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 485722bfec3SRichard Henderson return ret; 486e72ca652SBlue Swirl } 487e72ca652SBlue Swirl 488722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */ 489722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1, 490722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 491e72ca652SBlue Swirl { 492722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c, 493e72ca652SBlue Swirl &env->fpu_status); 494722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 495722bfec3SRichard Henderson return ret; 496e72ca652SBlue Swirl } 497e72ca652SBlue Swirl 498e72ca652SBlue Swirl /* test data class 32-bit */ 49931aa97d1SRichard Henderson uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2) 500e72ca652SBlue Swirl { 50131aa97d1SRichard Henderson float32 v1 = f1; 502e72ca652SBlue Swirl int neg = float32_is_neg(v1); 503e72ca652SBlue Swirl uint32_t cc = 0; 504e72ca652SBlue Swirl 505e72ca652SBlue Swirl if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || 506e72ca652SBlue Swirl (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 507e72ca652SBlue Swirl (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 508e72ca652SBlue Swirl (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 509e72ca652SBlue Swirl cc = 1; 510e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 511e72ca652SBlue Swirl /* assume normalized number */ 512e72ca652SBlue Swirl cc = 1; 513e72ca652SBlue Swirl } 514e72ca652SBlue Swirl /* FIXME: denormalized? */ 515e72ca652SBlue Swirl return cc; 516e72ca652SBlue Swirl } 517e72ca652SBlue Swirl 518e72ca652SBlue Swirl /* test data class 64-bit */ 51931aa97d1SRichard Henderson uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2) 520e72ca652SBlue Swirl { 521e72ca652SBlue Swirl int neg = float64_is_neg(v1); 522e72ca652SBlue Swirl uint32_t cc = 0; 523e72ca652SBlue Swirl 524e72ca652SBlue Swirl if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) || 525e72ca652SBlue Swirl (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 526e72ca652SBlue Swirl (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 527e72ca652SBlue Swirl (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 528e72ca652SBlue Swirl cc = 1; 529e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 530e72ca652SBlue Swirl /* assume normalized number */ 531e72ca652SBlue Swirl cc = 1; 532e72ca652SBlue Swirl } 533e72ca652SBlue Swirl /* FIXME: denormalized? */ 534e72ca652SBlue Swirl return cc; 535e72ca652SBlue Swirl } 536e72ca652SBlue Swirl 537e72ca652SBlue Swirl /* test data class 128-bit */ 53831aa97d1SRichard Henderson uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2) 539e72ca652SBlue Swirl { 54031aa97d1SRichard Henderson float128 v1 = make_float128(ah, al); 54131aa97d1SRichard Henderson int neg = float128_is_neg(v1); 542e72ca652SBlue Swirl uint32_t cc = 0; 543e72ca652SBlue Swirl 54431aa97d1SRichard Henderson if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) || 54531aa97d1SRichard Henderson (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 54631aa97d1SRichard Henderson (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 54731aa97d1SRichard Henderson (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 548e72ca652SBlue Swirl cc = 1; 549e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 550e72ca652SBlue Swirl /* assume normalized number */ 551e72ca652SBlue Swirl cc = 1; 552e72ca652SBlue Swirl } 553e72ca652SBlue Swirl /* FIXME: denormalized? */ 554e72ca652SBlue Swirl return cc; 555e72ca652SBlue Swirl } 556e72ca652SBlue Swirl 55716d7b2a4SRichard Henderson /* square root 32-bit */ 55816d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2) 559e72ca652SBlue Swirl { 56016d7b2a4SRichard Henderson float32 ret = float32_sqrt(f2, &env->fpu_status); 56116d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 56216d7b2a4SRichard Henderson return ret; 56316d7b2a4SRichard Henderson } 56416d7b2a4SRichard Henderson 56516d7b2a4SRichard Henderson /* square root 64-bit */ 56616d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2) 56716d7b2a4SRichard Henderson { 56816d7b2a4SRichard Henderson float64 ret = float64_sqrt(f2, &env->fpu_status); 56916d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 57016d7b2a4SRichard Henderson return ret; 57116d7b2a4SRichard Henderson } 57216d7b2a4SRichard Henderson 57316d7b2a4SRichard Henderson /* square root 128-bit */ 57416d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 57516d7b2a4SRichard Henderson { 57616d7b2a4SRichard Henderson float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status); 57716d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 57816d7b2a4SRichard Henderson return RET128(ret); 579e72ca652SBlue Swirl } 580