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 137e72ca652SBlue Swirl /* convert 32-bit int to 64-bit float */ 138449c0d70SBlue Swirl void HELPER(cdfbr)(CPUS390XState *env, uint32_t f1, int32_t v2) 139e72ca652SBlue Swirl { 140e72ca652SBlue Swirl HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1); 141e72ca652SBlue Swirl env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status); 142e72ca652SBlue Swirl } 143e72ca652SBlue Swirl 144e72ca652SBlue Swirl /* convert 32-bit int to 128-bit float */ 145449c0d70SBlue Swirl void HELPER(cxfbr)(CPUS390XState *env, uint32_t f1, int32_t v2) 146e72ca652SBlue Swirl { 147e72ca652SBlue Swirl CPU_QuadU v1; 148e72ca652SBlue Swirl 149e72ca652SBlue Swirl v1.q = int32_to_float128(v2, &env->fpu_status); 150e72ca652SBlue Swirl env->fregs[f1].ll = v1.ll.upper; 151e72ca652SBlue Swirl env->fregs[f1 + 2].ll = v1.ll.lower; 152e72ca652SBlue Swirl } 153e72ca652SBlue Swirl 154e72ca652SBlue Swirl /* convert 64-bit int to 32-bit float */ 155449c0d70SBlue Swirl void HELPER(cegbr)(CPUS390XState *env, uint32_t f1, int64_t v2) 156e72ca652SBlue Swirl { 157e72ca652SBlue Swirl HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); 158e72ca652SBlue Swirl env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status); 159e72ca652SBlue Swirl } 160e72ca652SBlue Swirl 161e72ca652SBlue Swirl /* convert 64-bit int to 64-bit float */ 162449c0d70SBlue Swirl void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2) 163e72ca652SBlue Swirl { 164e72ca652SBlue Swirl HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1); 165e72ca652SBlue Swirl env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status); 166e72ca652SBlue Swirl } 167e72ca652SBlue Swirl 168e72ca652SBlue Swirl /* convert 64-bit int to 128-bit float */ 169449c0d70SBlue Swirl void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2) 170e72ca652SBlue Swirl { 171e72ca652SBlue Swirl CPU_QuadU x1; 172e72ca652SBlue Swirl 173e72ca652SBlue Swirl x1.q = int64_to_float128(v2, &env->fpu_status); 174e72ca652SBlue Swirl HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2, 175e72ca652SBlue Swirl x1.ll.upper, x1.ll.lower); 176e72ca652SBlue Swirl env->fregs[f1].ll = x1.ll.upper; 177e72ca652SBlue Swirl env->fregs[f1 + 2].ll = x1.ll.lower; 178e72ca652SBlue Swirl } 179e72ca652SBlue Swirl 180e72ca652SBlue Swirl /* convert 32-bit int to 32-bit float */ 181449c0d70SBlue Swirl void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2) 182e72ca652SBlue Swirl { 183e72ca652SBlue Swirl env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status); 184e72ca652SBlue Swirl HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2, 185e72ca652SBlue Swirl env->fregs[f1].l.upper, f1); 186e72ca652SBlue Swirl } 187e72ca652SBlue Swirl 188587626f8SRichard Henderson /* 32-bit FP addition */ 189587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 190e72ca652SBlue Swirl { 191587626f8SRichard Henderson float32 ret = float32_add(f1, f2, &env->fpu_status); 192587626f8SRichard Henderson handle_exceptions(env, GETPC()); 193587626f8SRichard Henderson return ret; 194e72ca652SBlue Swirl } 195e72ca652SBlue Swirl 196587626f8SRichard Henderson /* 64-bit FP addition */ 197587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 198e72ca652SBlue Swirl { 199587626f8SRichard Henderson float64 ret = float64_add(f1, f2, &env->fpu_status); 200587626f8SRichard Henderson handle_exceptions(env, GETPC()); 201587626f8SRichard Henderson return ret; 202587626f8SRichard Henderson } 203e72ca652SBlue Swirl 204587626f8SRichard Henderson /* 128-bit FP addition */ 205587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al, 206587626f8SRichard Henderson uint64_t bh, uint64_t bl) 207587626f8SRichard Henderson { 208587626f8SRichard Henderson float128 ret = float128_add(make_float128(ah, al), 209587626f8SRichard Henderson make_float128(bh, bl), 210587626f8SRichard Henderson &env->fpu_status); 211587626f8SRichard Henderson handle_exceptions(env, GETPC()); 212587626f8SRichard Henderson return RET128(ret); 213e72ca652SBlue Swirl } 214e72ca652SBlue Swirl 2151a800a2dSRichard Henderson /* 32-bit FP subtraction */ 2161a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 217e72ca652SBlue Swirl { 2181a800a2dSRichard Henderson float32 ret = float32_sub(f1, f2, &env->fpu_status); 2191a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 2201a800a2dSRichard Henderson return ret; 221e72ca652SBlue Swirl } 222e72ca652SBlue Swirl 2231a800a2dSRichard Henderson /* 64-bit FP subtraction */ 2241a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 225e72ca652SBlue Swirl { 2261a800a2dSRichard Henderson float64 ret = float64_sub(f1, f2, &env->fpu_status); 2271a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 2281a800a2dSRichard Henderson return ret; 2291a800a2dSRichard Henderson } 230e72ca652SBlue Swirl 2311a800a2dSRichard Henderson /* 128-bit FP subtraction */ 2321a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 2331a800a2dSRichard Henderson uint64_t bh, uint64_t bl) 2341a800a2dSRichard Henderson { 2351a800a2dSRichard Henderson float128 ret = float128_sub(make_float128(ah, al), 2361a800a2dSRichard Henderson make_float128(bh, bl), 2371a800a2dSRichard Henderson &env->fpu_status); 2381a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 2391a800a2dSRichard Henderson return RET128(ret); 240e72ca652SBlue Swirl } 241e72ca652SBlue Swirl 242f08a5c31SRichard Henderson /* 32-bit FP division */ 243f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 244e72ca652SBlue Swirl { 245f08a5c31SRichard Henderson float32 ret = float32_div(f1, f2, &env->fpu_status); 246f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 247f08a5c31SRichard Henderson return ret; 248e72ca652SBlue Swirl } 249e72ca652SBlue Swirl 250f08a5c31SRichard Henderson /* 64-bit FP division */ 251f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 252e72ca652SBlue Swirl { 253f08a5c31SRichard Henderson float64 ret = float64_div(f1, f2, &env->fpu_status); 254f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 255f08a5c31SRichard Henderson return ret; 256f08a5c31SRichard Henderson } 257e72ca652SBlue Swirl 258f08a5c31SRichard Henderson /* 128-bit FP division */ 259f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 260f08a5c31SRichard Henderson uint64_t bh, uint64_t bl) 261f08a5c31SRichard Henderson { 262f08a5c31SRichard Henderson float128 ret = float128_div(make_float128(ah, al), 263f08a5c31SRichard Henderson make_float128(bh, bl), 264f08a5c31SRichard Henderson &env->fpu_status); 265f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 266f08a5c31SRichard Henderson return RET128(ret); 267e72ca652SBlue Swirl } 268e72ca652SBlue Swirl 26983b00736SRichard Henderson /* 32-bit FP multiplication */ 27083b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 271e72ca652SBlue Swirl { 27283b00736SRichard Henderson float32 ret = float32_mul(f1, f2, &env->fpu_status); 27383b00736SRichard Henderson handle_exceptions(env, GETPC()); 27483b00736SRichard Henderson return ret; 275e72ca652SBlue Swirl } 276e72ca652SBlue Swirl 27783b00736SRichard Henderson /* 64-bit FP multiplication */ 27883b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 279e72ca652SBlue Swirl { 28083b00736SRichard Henderson float64 ret = float64_mul(f1, f2, &env->fpu_status); 28183b00736SRichard Henderson handle_exceptions(env, GETPC()); 28283b00736SRichard Henderson return ret; 28383b00736SRichard Henderson } 284e72ca652SBlue Swirl 28583b00736SRichard Henderson /* 64/32-bit FP multiplication */ 28683b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 28783b00736SRichard Henderson { 28883b00736SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 28983b00736SRichard Henderson ret = float64_mul(f1, ret, &env->fpu_status); 29083b00736SRichard Henderson handle_exceptions(env, GETPC()); 29183b00736SRichard Henderson return ret; 29283b00736SRichard Henderson } 29383b00736SRichard Henderson 29483b00736SRichard Henderson /* 128-bit FP multiplication */ 29583b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 29683b00736SRichard Henderson uint64_t bh, uint64_t bl) 29783b00736SRichard Henderson { 29883b00736SRichard Henderson float128 ret = float128_mul(make_float128(ah, al), 29983b00736SRichard Henderson make_float128(bh, bl), 30083b00736SRichard Henderson &env->fpu_status); 30183b00736SRichard Henderson handle_exceptions(env, GETPC()); 30283b00736SRichard Henderson return RET128(ret); 30383b00736SRichard Henderson } 30483b00736SRichard Henderson 30583b00736SRichard Henderson /* 128/64-bit FP multiplication */ 30683b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al, 30783b00736SRichard Henderson uint64_t f2) 30883b00736SRichard Henderson { 30983b00736SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 31083b00736SRichard Henderson ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status); 31183b00736SRichard Henderson handle_exceptions(env, GETPC()); 31283b00736SRichard Henderson return RET128(ret); 313e72ca652SBlue Swirl } 314e72ca652SBlue Swirl 315e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */ 316587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2) 317e72ca652SBlue Swirl { 318587626f8SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 319587626f8SRichard Henderson handle_exceptions(env, GETPC()); 320587626f8SRichard Henderson return ret; 321e72ca652SBlue Swirl } 322e72ca652SBlue Swirl 323e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */ 324587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 325e72ca652SBlue Swirl { 326587626f8SRichard Henderson float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); 327587626f8SRichard Henderson handle_exceptions(env, GETPC()); 328587626f8SRichard Henderson return ret; 329e72ca652SBlue Swirl } 330e72ca652SBlue Swirl 331e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */ 332587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) 333e72ca652SBlue Swirl { 334587626f8SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 335587626f8SRichard Henderson handle_exceptions(env, GETPC()); 336587626f8SRichard Henderson return RET128(ret); 337587626f8SRichard Henderson } 338e72ca652SBlue Swirl 339587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */ 340587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) 341587626f8SRichard Henderson { 342587626f8SRichard Henderson float128 ret = float32_to_float128(f2, &env->fpu_status); 343587626f8SRichard Henderson handle_exceptions(env, GETPC()); 344587626f8SRichard Henderson return RET128(ret); 345e72ca652SBlue Swirl } 346e72ca652SBlue Swirl 347e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */ 348587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2) 349e72ca652SBlue Swirl { 350587626f8SRichard Henderson float32 ret = float64_to_float32(f2, &env->fpu_status); 351587626f8SRichard Henderson handle_exceptions(env, GETPC()); 352587626f8SRichard Henderson return ret; 353e72ca652SBlue Swirl } 354e72ca652SBlue Swirl 355e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */ 356587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al) 357e72ca652SBlue Swirl { 358587626f8SRichard Henderson float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); 359587626f8SRichard Henderson handle_exceptions(env, GETPC()); 360587626f8SRichard Henderson return ret; 361e72ca652SBlue Swirl } 362e72ca652SBlue Swirl 363587626f8SRichard Henderson /* 32-bit FP compare */ 364587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 365e72ca652SBlue Swirl { 366587626f8SRichard Henderson int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); 367587626f8SRichard Henderson handle_exceptions(env, GETPC()); 368587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 369e72ca652SBlue Swirl } 370e72ca652SBlue Swirl 371587626f8SRichard Henderson /* 64-bit FP compare */ 372587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 373e72ca652SBlue Swirl { 374587626f8SRichard Henderson int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); 375587626f8SRichard Henderson handle_exceptions(env, GETPC()); 376587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 377e72ca652SBlue Swirl } 378e72ca652SBlue Swirl 379587626f8SRichard Henderson /* 128-bit FP compare */ 380587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 381587626f8SRichard Henderson uint64_t bh, uint64_t bl) 382e72ca652SBlue Swirl { 383587626f8SRichard Henderson int cmp = float128_compare_quiet(make_float128(ah, al), 384587626f8SRichard Henderson make_float128(bh, bl), 385587626f8SRichard Henderson &env->fpu_status); 386587626f8SRichard Henderson handle_exceptions(env, GETPC()); 387587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 388e72ca652SBlue Swirl } 389e72ca652SBlue Swirl 390449c0d70SBlue Swirl static void set_round_mode(CPUS390XState *env, int m3) 391e72ca652SBlue Swirl { 392e72ca652SBlue Swirl switch (m3) { 393e72ca652SBlue Swirl case 0: 394e72ca652SBlue Swirl /* current mode */ 395e72ca652SBlue Swirl break; 396e72ca652SBlue Swirl case 1: 397e72ca652SBlue Swirl /* biased round no nearest */ 398e72ca652SBlue Swirl case 4: 399e72ca652SBlue Swirl /* round to nearest */ 400e72ca652SBlue Swirl set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); 401e72ca652SBlue Swirl break; 402e72ca652SBlue Swirl case 5: 403e72ca652SBlue Swirl /* round to zero */ 404e72ca652SBlue Swirl set_float_rounding_mode(float_round_to_zero, &env->fpu_status); 405e72ca652SBlue Swirl break; 406e72ca652SBlue Swirl case 6: 407e72ca652SBlue Swirl /* round to +inf */ 408e72ca652SBlue Swirl set_float_rounding_mode(float_round_up, &env->fpu_status); 409e72ca652SBlue Swirl break; 410e72ca652SBlue Swirl case 7: 411e72ca652SBlue Swirl /* round to -inf */ 412e72ca652SBlue Swirl set_float_rounding_mode(float_round_down, &env->fpu_status); 413e72ca652SBlue Swirl break; 414e72ca652SBlue Swirl } 415e72ca652SBlue Swirl } 416e72ca652SBlue Swirl 417e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */ 418449c0d70SBlue Swirl uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 419449c0d70SBlue Swirl uint32_t m3) 420e72ca652SBlue Swirl { 421e72ca652SBlue Swirl float32 v2 = env->fregs[f2].l.upper; 422e72ca652SBlue Swirl 423449c0d70SBlue Swirl set_round_mode(env, m3); 424e72ca652SBlue Swirl env->regs[r1] = float32_to_int64(v2, &env->fpu_status); 425e72ca652SBlue Swirl return set_cc_nz_f32(v2); 426e72ca652SBlue Swirl } 427e72ca652SBlue Swirl 428e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */ 429449c0d70SBlue Swirl uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 430449c0d70SBlue Swirl uint32_t m3) 431e72ca652SBlue Swirl { 432e72ca652SBlue Swirl float64 v2 = env->fregs[f2].d; 433e72ca652SBlue Swirl 434449c0d70SBlue Swirl set_round_mode(env, m3); 435e72ca652SBlue Swirl env->regs[r1] = float64_to_int64(v2, &env->fpu_status); 436e72ca652SBlue Swirl return set_cc_nz_f64(v2); 437e72ca652SBlue Swirl } 438e72ca652SBlue Swirl 439e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */ 440449c0d70SBlue Swirl uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 441449c0d70SBlue Swirl uint32_t m3) 442e72ca652SBlue Swirl { 443e72ca652SBlue Swirl CPU_QuadU v2; 444e72ca652SBlue Swirl 445e72ca652SBlue Swirl v2.ll.upper = env->fregs[f2].ll; 446e72ca652SBlue Swirl v2.ll.lower = env->fregs[f2 + 2].ll; 447449c0d70SBlue Swirl set_round_mode(env, m3); 448e72ca652SBlue Swirl env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status); 449e72ca652SBlue Swirl if (float128_is_any_nan(v2.q)) { 450e72ca652SBlue Swirl return 3; 451e72ca652SBlue Swirl } else if (float128_is_zero(v2.q)) { 452e72ca652SBlue Swirl return 0; 453e72ca652SBlue Swirl } else if (float128_is_neg(v2.q)) { 454e72ca652SBlue Swirl return 1; 455e72ca652SBlue Swirl } else { 456e72ca652SBlue Swirl return 2; 457e72ca652SBlue Swirl } 458e72ca652SBlue Swirl } 459e72ca652SBlue Swirl 460e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */ 461449c0d70SBlue Swirl uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 462449c0d70SBlue Swirl uint32_t m3) 463e72ca652SBlue Swirl { 464e72ca652SBlue Swirl float32 v2 = env->fregs[f2].l.upper; 465e72ca652SBlue Swirl 466449c0d70SBlue Swirl set_round_mode(env, m3); 467e72ca652SBlue Swirl env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | 468e72ca652SBlue Swirl float32_to_int32(v2, &env->fpu_status); 469e72ca652SBlue Swirl return set_cc_nz_f32(v2); 470e72ca652SBlue Swirl } 471e72ca652SBlue Swirl 472e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */ 473449c0d70SBlue Swirl uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 474449c0d70SBlue Swirl uint32_t m3) 475e72ca652SBlue Swirl { 476e72ca652SBlue Swirl float64 v2 = env->fregs[f2].d; 477e72ca652SBlue Swirl 478449c0d70SBlue Swirl set_round_mode(env, m3); 479e72ca652SBlue Swirl env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | 480e72ca652SBlue Swirl float64_to_int32(v2, &env->fpu_status); 481e72ca652SBlue Swirl return set_cc_nz_f64(v2); 482e72ca652SBlue Swirl } 483e72ca652SBlue Swirl 484e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */ 485449c0d70SBlue Swirl uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 486449c0d70SBlue Swirl uint32_t m3) 487e72ca652SBlue Swirl { 488e72ca652SBlue Swirl CPU_QuadU v2; 489e72ca652SBlue Swirl 490e72ca652SBlue Swirl v2.ll.upper = env->fregs[f2].ll; 491e72ca652SBlue Swirl v2.ll.lower = env->fregs[f2 + 2].ll; 492e72ca652SBlue Swirl env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | 493e72ca652SBlue Swirl float128_to_int32(v2.q, &env->fpu_status); 494e72ca652SBlue Swirl return set_cc_nz_f128(v2.q); 495e72ca652SBlue Swirl } 496e72ca652SBlue Swirl 497e72ca652SBlue Swirl /* load 32-bit FP zero */ 498449c0d70SBlue Swirl void HELPER(lzer)(CPUS390XState *env, uint32_t f1) 499e72ca652SBlue Swirl { 500e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_zero; 501e72ca652SBlue Swirl } 502e72ca652SBlue Swirl 503e72ca652SBlue Swirl /* load 64-bit FP zero */ 504449c0d70SBlue Swirl void HELPER(lzdr)(CPUS390XState *env, uint32_t f1) 505e72ca652SBlue Swirl { 506e72ca652SBlue Swirl env->fregs[f1].d = float64_zero; 507e72ca652SBlue Swirl } 508e72ca652SBlue Swirl 509e72ca652SBlue Swirl /* load 128-bit FP zero */ 510449c0d70SBlue Swirl void HELPER(lzxr)(CPUS390XState *env, uint32_t f1) 511e72ca652SBlue Swirl { 512e72ca652SBlue Swirl CPU_QuadU x; 513e72ca652SBlue Swirl 514e72ca652SBlue Swirl x.q = float64_to_float128(float64_zero, &env->fpu_status); 515e72ca652SBlue Swirl env->fregs[f1].ll = x.ll.upper; 516e72ca652SBlue Swirl env->fregs[f1 + 1].ll = x.ll.lower; 517e72ca652SBlue Swirl } 518e72ca652SBlue Swirl 519722bfec3SRichard Henderson /* 32-bit FP multiply and add */ 520722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, 521722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 522e72ca652SBlue Swirl { 523722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status); 524722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 525722bfec3SRichard Henderson return ret; 526722bfec3SRichard Henderson } 527e72ca652SBlue Swirl 528722bfec3SRichard Henderson /* 64-bit FP multiply and add */ 529722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1, 530722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 531722bfec3SRichard Henderson { 532722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status); 533722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 534722bfec3SRichard Henderson return ret; 535722bfec3SRichard Henderson } 536722bfec3SRichard Henderson 537722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */ 538722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1, 539722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 540722bfec3SRichard Henderson { 541722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c, 542e72ca652SBlue Swirl &env->fpu_status); 543722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 544722bfec3SRichard Henderson return ret; 545e72ca652SBlue Swirl } 546e72ca652SBlue Swirl 547722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */ 548722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1, 549722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 550e72ca652SBlue Swirl { 551722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c, 552e72ca652SBlue Swirl &env->fpu_status); 553722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 554722bfec3SRichard Henderson return ret; 555e72ca652SBlue Swirl } 556e72ca652SBlue Swirl 557e72ca652SBlue Swirl /* test data class 32-bit */ 55831aa97d1SRichard Henderson uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2) 559e72ca652SBlue Swirl { 56031aa97d1SRichard Henderson float32 v1 = f1; 561e72ca652SBlue Swirl int neg = float32_is_neg(v1); 562e72ca652SBlue Swirl uint32_t cc = 0; 563e72ca652SBlue Swirl 564e72ca652SBlue Swirl if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || 565e72ca652SBlue Swirl (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 566e72ca652SBlue Swirl (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 567e72ca652SBlue Swirl (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 568e72ca652SBlue Swirl cc = 1; 569e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 570e72ca652SBlue Swirl /* assume normalized number */ 571e72ca652SBlue Swirl cc = 1; 572e72ca652SBlue Swirl } 573e72ca652SBlue Swirl /* FIXME: denormalized? */ 574e72ca652SBlue Swirl return cc; 575e72ca652SBlue Swirl } 576e72ca652SBlue Swirl 577e72ca652SBlue Swirl /* test data class 64-bit */ 57831aa97d1SRichard Henderson uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2) 579e72ca652SBlue Swirl { 580e72ca652SBlue Swirl int neg = float64_is_neg(v1); 581e72ca652SBlue Swirl uint32_t cc = 0; 582e72ca652SBlue Swirl 583e72ca652SBlue Swirl if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) || 584e72ca652SBlue Swirl (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 585e72ca652SBlue Swirl (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 586e72ca652SBlue Swirl (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 587e72ca652SBlue Swirl cc = 1; 588e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 589e72ca652SBlue Swirl /* assume normalized number */ 590e72ca652SBlue Swirl cc = 1; 591e72ca652SBlue Swirl } 592e72ca652SBlue Swirl /* FIXME: denormalized? */ 593e72ca652SBlue Swirl return cc; 594e72ca652SBlue Swirl } 595e72ca652SBlue Swirl 596e72ca652SBlue Swirl /* test data class 128-bit */ 59731aa97d1SRichard Henderson uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2) 598e72ca652SBlue Swirl { 59931aa97d1SRichard Henderson float128 v1 = make_float128(ah, al); 60031aa97d1SRichard Henderson int neg = float128_is_neg(v1); 601e72ca652SBlue Swirl uint32_t cc = 0; 602e72ca652SBlue Swirl 60331aa97d1SRichard Henderson if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) || 60431aa97d1SRichard Henderson (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 60531aa97d1SRichard Henderson (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 60631aa97d1SRichard Henderson (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 607e72ca652SBlue Swirl cc = 1; 608e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 609e72ca652SBlue Swirl /* assume normalized number */ 610e72ca652SBlue Swirl cc = 1; 611e72ca652SBlue Swirl } 612e72ca652SBlue Swirl /* FIXME: denormalized? */ 613e72ca652SBlue Swirl return cc; 614e72ca652SBlue Swirl } 615e72ca652SBlue Swirl 61616d7b2a4SRichard Henderson /* square root 32-bit */ 61716d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2) 618e72ca652SBlue Swirl { 61916d7b2a4SRichard Henderson float32 ret = float32_sqrt(f2, &env->fpu_status); 62016d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 62116d7b2a4SRichard Henderson return ret; 62216d7b2a4SRichard Henderson } 62316d7b2a4SRichard Henderson 62416d7b2a4SRichard Henderson /* square root 64-bit */ 62516d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2) 62616d7b2a4SRichard Henderson { 62716d7b2a4SRichard Henderson float64 ret = float64_sqrt(f2, &env->fpu_status); 62816d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 62916d7b2a4SRichard Henderson return ret; 63016d7b2a4SRichard Henderson } 63116d7b2a4SRichard Henderson 63216d7b2a4SRichard Henderson /* square root 128-bit */ 63316d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 63416d7b2a4SRichard Henderson { 63516d7b2a4SRichard Henderson float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status); 63616d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 63716d7b2a4SRichard Henderson return RET128(ret); 638e72ca652SBlue Swirl } 639