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 215e72ca652SBlue Swirl /* 32-bit FP subtraction RR */ 216449c0d70SBlue Swirl uint32_t HELPER(sebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 217e72ca652SBlue Swirl { 218e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper, 219e72ca652SBlue Swirl env->fregs[f2].l.upper, 220e72ca652SBlue Swirl &env->fpu_status); 221e72ca652SBlue Swirl HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__, 222e72ca652SBlue Swirl env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1); 223e72ca652SBlue Swirl 224e72ca652SBlue Swirl return set_cc_nz_f32(env->fregs[f1].l.upper); 225e72ca652SBlue Swirl } 226e72ca652SBlue Swirl 227e72ca652SBlue Swirl /* 64-bit FP subtraction RR */ 228449c0d70SBlue Swirl uint32_t HELPER(sdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 229e72ca652SBlue Swirl { 230e72ca652SBlue Swirl env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d, 231e72ca652SBlue Swirl &env->fpu_status); 232e72ca652SBlue Swirl HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n", 233e72ca652SBlue Swirl __func__, env->fregs[f2].d, env->fregs[f1].d, f1); 234e72ca652SBlue Swirl 235e72ca652SBlue Swirl return set_cc_nz_f64(env->fregs[f1].d); 236e72ca652SBlue Swirl } 237e72ca652SBlue Swirl 238e72ca652SBlue Swirl /* 32-bit FP division RR */ 239449c0d70SBlue Swirl void HELPER(debr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 240e72ca652SBlue Swirl { 241e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper, 242e72ca652SBlue Swirl env->fregs[f2].l.upper, 243e72ca652SBlue Swirl &env->fpu_status); 244e72ca652SBlue Swirl } 245e72ca652SBlue Swirl 246e72ca652SBlue Swirl /* 128-bit FP division RR */ 247449c0d70SBlue Swirl void HELPER(dxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 248e72ca652SBlue Swirl { 249e72ca652SBlue Swirl CPU_QuadU v1; 250e72ca652SBlue Swirl CPU_QuadU v2; 251e72ca652SBlue Swirl CPU_QuadU res; 252e72ca652SBlue Swirl 253e72ca652SBlue Swirl v1.ll.upper = env->fregs[f1].ll; 254e72ca652SBlue Swirl v1.ll.lower = env->fregs[f1 + 2].ll; 255e72ca652SBlue Swirl v2.ll.upper = env->fregs[f2].ll; 256e72ca652SBlue Swirl v2.ll.lower = env->fregs[f2 + 2].ll; 257e72ca652SBlue Swirl res.q = float128_div(v1.q, v2.q, &env->fpu_status); 258e72ca652SBlue Swirl env->fregs[f1].ll = res.ll.upper; 259e72ca652SBlue Swirl env->fregs[f1 + 2].ll = res.ll.lower; 260e72ca652SBlue Swirl } 261e72ca652SBlue Swirl 262e72ca652SBlue Swirl /* 64-bit FP multiplication RR */ 263449c0d70SBlue Swirl void HELPER(mdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 264e72ca652SBlue Swirl { 265e72ca652SBlue Swirl env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d, 266e72ca652SBlue Swirl &env->fpu_status); 267e72ca652SBlue Swirl } 268e72ca652SBlue Swirl 269e72ca652SBlue Swirl /* 128-bit FP multiplication RR */ 270449c0d70SBlue Swirl void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 271e72ca652SBlue Swirl { 272e72ca652SBlue Swirl CPU_QuadU v1; 273e72ca652SBlue Swirl CPU_QuadU v2; 274e72ca652SBlue Swirl CPU_QuadU res; 275e72ca652SBlue Swirl 276e72ca652SBlue Swirl v1.ll.upper = env->fregs[f1].ll; 277e72ca652SBlue Swirl v1.ll.lower = env->fregs[f1 + 2].ll; 278e72ca652SBlue Swirl v2.ll.upper = env->fregs[f2].ll; 279e72ca652SBlue Swirl v2.ll.lower = env->fregs[f2 + 2].ll; 280e72ca652SBlue Swirl res.q = float128_mul(v1.q, v2.q, &env->fpu_status); 281e72ca652SBlue Swirl env->fregs[f1].ll = res.ll.upper; 282e72ca652SBlue Swirl env->fregs[f1 + 2].ll = res.ll.lower; 283e72ca652SBlue Swirl } 284e72ca652SBlue Swirl 285e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */ 286587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2) 287e72ca652SBlue Swirl { 288587626f8SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 289587626f8SRichard Henderson handle_exceptions(env, GETPC()); 290587626f8SRichard Henderson return ret; 291e72ca652SBlue Swirl } 292e72ca652SBlue Swirl 293e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */ 294587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 295e72ca652SBlue Swirl { 296587626f8SRichard Henderson float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); 297587626f8SRichard Henderson handle_exceptions(env, GETPC()); 298587626f8SRichard Henderson return ret; 299e72ca652SBlue Swirl } 300e72ca652SBlue Swirl 301e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */ 302587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) 303e72ca652SBlue Swirl { 304587626f8SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 305587626f8SRichard Henderson handle_exceptions(env, GETPC()); 306587626f8SRichard Henderson return RET128(ret); 307587626f8SRichard Henderson } 308e72ca652SBlue Swirl 309587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */ 310587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) 311587626f8SRichard Henderson { 312587626f8SRichard Henderson float128 ret = float32_to_float128(f2, &env->fpu_status); 313587626f8SRichard Henderson handle_exceptions(env, GETPC()); 314587626f8SRichard Henderson return RET128(ret); 315e72ca652SBlue Swirl } 316e72ca652SBlue Swirl 317e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */ 318587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2) 319e72ca652SBlue Swirl { 320587626f8SRichard Henderson float32 ret = float64_to_float32(f2, &env->fpu_status); 321587626f8SRichard Henderson handle_exceptions(env, GETPC()); 322587626f8SRichard Henderson return ret; 323e72ca652SBlue Swirl } 324e72ca652SBlue Swirl 325e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */ 326587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al) 327e72ca652SBlue Swirl { 328587626f8SRichard Henderson float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); 329587626f8SRichard Henderson handle_exceptions(env, GETPC()); 330587626f8SRichard Henderson return ret; 331e72ca652SBlue Swirl } 332e72ca652SBlue Swirl 333e72ca652SBlue Swirl /* absolute value of 32-bit float */ 334449c0d70SBlue Swirl uint32_t HELPER(lpebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 335e72ca652SBlue Swirl { 336e72ca652SBlue Swirl float32 v1; 337e72ca652SBlue Swirl float32 v2 = env->fregs[f2].d; 338e72ca652SBlue Swirl 339e72ca652SBlue Swirl v1 = float32_abs(v2); 340e72ca652SBlue Swirl env->fregs[f1].d = v1; 341e72ca652SBlue Swirl return set_cc_nz_f32(v1); 342e72ca652SBlue Swirl } 343e72ca652SBlue Swirl 344e72ca652SBlue Swirl /* absolute value of 64-bit float */ 345449c0d70SBlue Swirl uint32_t HELPER(lpdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 346e72ca652SBlue Swirl { 347e72ca652SBlue Swirl float64 v1; 348e72ca652SBlue Swirl float64 v2 = env->fregs[f2].d; 349e72ca652SBlue Swirl 350e72ca652SBlue Swirl v1 = float64_abs(v2); 351e72ca652SBlue Swirl env->fregs[f1].d = v1; 352e72ca652SBlue Swirl return set_cc_nz_f64(v1); 353e72ca652SBlue Swirl } 354e72ca652SBlue Swirl 355e72ca652SBlue Swirl /* absolute value of 128-bit float */ 356449c0d70SBlue Swirl uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 357e72ca652SBlue Swirl { 358e72ca652SBlue Swirl CPU_QuadU v1; 359e72ca652SBlue Swirl CPU_QuadU v2; 360e72ca652SBlue Swirl 361e72ca652SBlue Swirl v2.ll.upper = env->fregs[f2].ll; 362e72ca652SBlue Swirl v2.ll.lower = env->fregs[f2 + 2].ll; 363e72ca652SBlue Swirl v1.q = float128_abs(v2.q); 364e72ca652SBlue Swirl env->fregs[f1].ll = v1.ll.upper; 365e72ca652SBlue Swirl env->fregs[f1 + 2].ll = v1.ll.lower; 366e72ca652SBlue Swirl return set_cc_nz_f128(v1.q); 367e72ca652SBlue Swirl } 368e72ca652SBlue Swirl 369e72ca652SBlue Swirl /* load complement of 32-bit float */ 370449c0d70SBlue Swirl uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 371e72ca652SBlue Swirl { 372e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper); 373e72ca652SBlue Swirl 374e72ca652SBlue Swirl return set_cc_nz_f32(env->fregs[f1].l.upper); 375e72ca652SBlue Swirl } 376e72ca652SBlue Swirl 377e72ca652SBlue Swirl /* load complement of 64-bit float */ 378449c0d70SBlue Swirl uint32_t HELPER(lcdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 379e72ca652SBlue Swirl { 380e72ca652SBlue Swirl env->fregs[f1].d = float64_chs(env->fregs[f2].d); 381e72ca652SBlue Swirl 382e72ca652SBlue Swirl return set_cc_nz_f64(env->fregs[f1].d); 383e72ca652SBlue Swirl } 384e72ca652SBlue Swirl 385e72ca652SBlue Swirl /* load complement of 128-bit float */ 386449c0d70SBlue Swirl uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 387e72ca652SBlue Swirl { 388e72ca652SBlue Swirl CPU_QuadU x1, x2; 389e72ca652SBlue Swirl 390e72ca652SBlue Swirl x2.ll.upper = env->fregs[f2].ll; 391e72ca652SBlue Swirl x2.ll.lower = env->fregs[f2 + 2].ll; 392e72ca652SBlue Swirl x1.q = float128_chs(x2.q); 393e72ca652SBlue Swirl env->fregs[f1].ll = x1.ll.upper; 394e72ca652SBlue Swirl env->fregs[f1 + 2].ll = x1.ll.lower; 395e72ca652SBlue Swirl return set_cc_nz_f128(x1.q); 396e72ca652SBlue Swirl } 397e72ca652SBlue Swirl 398e72ca652SBlue Swirl /* 32-bit FP division RM */ 399449c0d70SBlue Swirl void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val) 400e72ca652SBlue Swirl { 401e72ca652SBlue Swirl float32 v1 = env->fregs[f1].l.upper; 402e72ca652SBlue Swirl CPU_FloatU v2; 403e72ca652SBlue Swirl 404e72ca652SBlue Swirl v2.l = val; 405e72ca652SBlue Swirl HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__, 406e72ca652SBlue Swirl v1, f1, v2.f); 407e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status); 408e72ca652SBlue Swirl } 409e72ca652SBlue Swirl 410e72ca652SBlue Swirl /* 32-bit FP multiplication RM */ 411449c0d70SBlue Swirl void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val) 412e72ca652SBlue Swirl { 413e72ca652SBlue Swirl float32 v1 = env->fregs[f1].l.upper; 414e72ca652SBlue Swirl CPU_FloatU v2; 415e72ca652SBlue Swirl 416e72ca652SBlue Swirl v2.l = val; 417e72ca652SBlue Swirl HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__, 418e72ca652SBlue Swirl v1, f1, v2.f); 419e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status); 420e72ca652SBlue Swirl } 421e72ca652SBlue Swirl 422587626f8SRichard Henderson /* 32-bit FP compare */ 423587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 424e72ca652SBlue Swirl { 425587626f8SRichard Henderson int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); 426587626f8SRichard Henderson handle_exceptions(env, GETPC()); 427587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 428e72ca652SBlue Swirl } 429e72ca652SBlue Swirl 430587626f8SRichard Henderson /* 64-bit FP compare */ 431587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 432e72ca652SBlue Swirl { 433587626f8SRichard Henderson int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); 434587626f8SRichard Henderson handle_exceptions(env, GETPC()); 435587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 436e72ca652SBlue Swirl } 437e72ca652SBlue Swirl 438587626f8SRichard Henderson /* 128-bit FP compare */ 439587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 440587626f8SRichard Henderson uint64_t bh, uint64_t bl) 441e72ca652SBlue Swirl { 442587626f8SRichard Henderson int cmp = float128_compare_quiet(make_float128(ah, al), 443587626f8SRichard Henderson make_float128(bh, bl), 444587626f8SRichard Henderson &env->fpu_status); 445587626f8SRichard Henderson handle_exceptions(env, GETPC()); 446587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 447e72ca652SBlue Swirl } 448e72ca652SBlue Swirl 449e72ca652SBlue Swirl /* 32-bit FP subtraction RM */ 450449c0d70SBlue Swirl void HELPER(seb)(CPUS390XState *env, uint32_t f1, uint32_t val) 451e72ca652SBlue Swirl { 452e72ca652SBlue Swirl float32 v1 = env->fregs[f1].l.upper; 453e72ca652SBlue Swirl CPU_FloatU v2; 454e72ca652SBlue Swirl 455e72ca652SBlue Swirl v2.l = val; 456e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status); 457e72ca652SBlue Swirl } 458e72ca652SBlue Swirl 459e72ca652SBlue Swirl /* 64-bit FP subtraction RM */ 460449c0d70SBlue Swirl uint32_t HELPER(sdb)(CPUS390XState *env, uint32_t f1, uint64_t a2) 461e72ca652SBlue Swirl { 462e72ca652SBlue Swirl float64 v1 = env->fregs[f1].d; 463e72ca652SBlue Swirl CPU_DoubleU v2; 464e72ca652SBlue Swirl 465449c0d70SBlue Swirl v2.ll = cpu_ldq_data(env, a2); 466e72ca652SBlue Swirl env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status); 467e72ca652SBlue Swirl return set_cc_nz_f64(v1); 468e72ca652SBlue Swirl } 469e72ca652SBlue Swirl 470e72ca652SBlue Swirl /* 64-bit FP multiplication RM */ 471449c0d70SBlue Swirl void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2) 472e72ca652SBlue Swirl { 473e72ca652SBlue Swirl float64 v1 = env->fregs[f1].d; 474e72ca652SBlue Swirl CPU_DoubleU v2; 475e72ca652SBlue Swirl 476449c0d70SBlue Swirl v2.ll = cpu_ldq_data(env, a2); 477e72ca652SBlue Swirl HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__, 478e72ca652SBlue Swirl v1, f1, v2.d); 479e72ca652SBlue Swirl env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status); 480e72ca652SBlue Swirl } 481e72ca652SBlue Swirl 482e72ca652SBlue Swirl /* 64-bit FP division RM */ 483449c0d70SBlue Swirl void HELPER(ddb)(CPUS390XState *env, uint32_t f1, uint64_t a2) 484e72ca652SBlue Swirl { 485e72ca652SBlue Swirl float64 v1 = env->fregs[f1].d; 486e72ca652SBlue Swirl CPU_DoubleU v2; 487e72ca652SBlue Swirl 488449c0d70SBlue Swirl v2.ll = cpu_ldq_data(env, a2); 489e72ca652SBlue Swirl HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__, 490e72ca652SBlue Swirl v1, f1, v2.d); 491e72ca652SBlue Swirl env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status); 492e72ca652SBlue Swirl } 493e72ca652SBlue Swirl 494449c0d70SBlue Swirl static void set_round_mode(CPUS390XState *env, int m3) 495e72ca652SBlue Swirl { 496e72ca652SBlue Swirl switch (m3) { 497e72ca652SBlue Swirl case 0: 498e72ca652SBlue Swirl /* current mode */ 499e72ca652SBlue Swirl break; 500e72ca652SBlue Swirl case 1: 501e72ca652SBlue Swirl /* biased round no nearest */ 502e72ca652SBlue Swirl case 4: 503e72ca652SBlue Swirl /* round to nearest */ 504e72ca652SBlue Swirl set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); 505e72ca652SBlue Swirl break; 506e72ca652SBlue Swirl case 5: 507e72ca652SBlue Swirl /* round to zero */ 508e72ca652SBlue Swirl set_float_rounding_mode(float_round_to_zero, &env->fpu_status); 509e72ca652SBlue Swirl break; 510e72ca652SBlue Swirl case 6: 511e72ca652SBlue Swirl /* round to +inf */ 512e72ca652SBlue Swirl set_float_rounding_mode(float_round_up, &env->fpu_status); 513e72ca652SBlue Swirl break; 514e72ca652SBlue Swirl case 7: 515e72ca652SBlue Swirl /* round to -inf */ 516e72ca652SBlue Swirl set_float_rounding_mode(float_round_down, &env->fpu_status); 517e72ca652SBlue Swirl break; 518e72ca652SBlue Swirl } 519e72ca652SBlue Swirl } 520e72ca652SBlue Swirl 521e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */ 522449c0d70SBlue Swirl uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 523449c0d70SBlue Swirl uint32_t m3) 524e72ca652SBlue Swirl { 525e72ca652SBlue Swirl float32 v2 = env->fregs[f2].l.upper; 526e72ca652SBlue Swirl 527449c0d70SBlue Swirl set_round_mode(env, m3); 528e72ca652SBlue Swirl env->regs[r1] = float32_to_int64(v2, &env->fpu_status); 529e72ca652SBlue Swirl return set_cc_nz_f32(v2); 530e72ca652SBlue Swirl } 531e72ca652SBlue Swirl 532e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */ 533449c0d70SBlue Swirl uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 534449c0d70SBlue Swirl uint32_t m3) 535e72ca652SBlue Swirl { 536e72ca652SBlue Swirl float64 v2 = env->fregs[f2].d; 537e72ca652SBlue Swirl 538449c0d70SBlue Swirl set_round_mode(env, m3); 539e72ca652SBlue Swirl env->regs[r1] = float64_to_int64(v2, &env->fpu_status); 540e72ca652SBlue Swirl return set_cc_nz_f64(v2); 541e72ca652SBlue Swirl } 542e72ca652SBlue Swirl 543e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */ 544449c0d70SBlue Swirl uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 545449c0d70SBlue Swirl uint32_t m3) 546e72ca652SBlue Swirl { 547e72ca652SBlue Swirl CPU_QuadU v2; 548e72ca652SBlue Swirl 549e72ca652SBlue Swirl v2.ll.upper = env->fregs[f2].ll; 550e72ca652SBlue Swirl v2.ll.lower = env->fregs[f2 + 2].ll; 551449c0d70SBlue Swirl set_round_mode(env, m3); 552e72ca652SBlue Swirl env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status); 553e72ca652SBlue Swirl if (float128_is_any_nan(v2.q)) { 554e72ca652SBlue Swirl return 3; 555e72ca652SBlue Swirl } else if (float128_is_zero(v2.q)) { 556e72ca652SBlue Swirl return 0; 557e72ca652SBlue Swirl } else if (float128_is_neg(v2.q)) { 558e72ca652SBlue Swirl return 1; 559e72ca652SBlue Swirl } else { 560e72ca652SBlue Swirl return 2; 561e72ca652SBlue Swirl } 562e72ca652SBlue Swirl } 563e72ca652SBlue Swirl 564e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */ 565449c0d70SBlue Swirl uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 566449c0d70SBlue Swirl uint32_t m3) 567e72ca652SBlue Swirl { 568e72ca652SBlue Swirl float32 v2 = env->fregs[f2].l.upper; 569e72ca652SBlue Swirl 570449c0d70SBlue Swirl set_round_mode(env, m3); 571e72ca652SBlue Swirl env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | 572e72ca652SBlue Swirl float32_to_int32(v2, &env->fpu_status); 573e72ca652SBlue Swirl return set_cc_nz_f32(v2); 574e72ca652SBlue Swirl } 575e72ca652SBlue Swirl 576e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */ 577449c0d70SBlue Swirl uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 578449c0d70SBlue Swirl uint32_t m3) 579e72ca652SBlue Swirl { 580e72ca652SBlue Swirl float64 v2 = env->fregs[f2].d; 581e72ca652SBlue Swirl 582449c0d70SBlue Swirl set_round_mode(env, m3); 583e72ca652SBlue Swirl env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | 584e72ca652SBlue Swirl float64_to_int32(v2, &env->fpu_status); 585e72ca652SBlue Swirl return set_cc_nz_f64(v2); 586e72ca652SBlue Swirl } 587e72ca652SBlue Swirl 588e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */ 589449c0d70SBlue Swirl uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2, 590449c0d70SBlue Swirl uint32_t m3) 591e72ca652SBlue Swirl { 592e72ca652SBlue Swirl CPU_QuadU v2; 593e72ca652SBlue Swirl 594e72ca652SBlue Swirl v2.ll.upper = env->fregs[f2].ll; 595e72ca652SBlue Swirl v2.ll.lower = env->fregs[f2 + 2].ll; 596e72ca652SBlue Swirl env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | 597e72ca652SBlue Swirl float128_to_int32(v2.q, &env->fpu_status); 598e72ca652SBlue Swirl return set_cc_nz_f128(v2.q); 599e72ca652SBlue Swirl } 600e72ca652SBlue Swirl 601e72ca652SBlue Swirl /* load 32-bit FP zero */ 602449c0d70SBlue Swirl void HELPER(lzer)(CPUS390XState *env, uint32_t f1) 603e72ca652SBlue Swirl { 604e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_zero; 605e72ca652SBlue Swirl } 606e72ca652SBlue Swirl 607e72ca652SBlue Swirl /* load 64-bit FP zero */ 608449c0d70SBlue Swirl void HELPER(lzdr)(CPUS390XState *env, uint32_t f1) 609e72ca652SBlue Swirl { 610e72ca652SBlue Swirl env->fregs[f1].d = float64_zero; 611e72ca652SBlue Swirl } 612e72ca652SBlue Swirl 613e72ca652SBlue Swirl /* load 128-bit FP zero */ 614449c0d70SBlue Swirl void HELPER(lzxr)(CPUS390XState *env, uint32_t f1) 615e72ca652SBlue Swirl { 616e72ca652SBlue Swirl CPU_QuadU x; 617e72ca652SBlue Swirl 618e72ca652SBlue Swirl x.q = float64_to_float128(float64_zero, &env->fpu_status); 619e72ca652SBlue Swirl env->fregs[f1].ll = x.ll.upper; 620e72ca652SBlue Swirl env->fregs[f1 + 1].ll = x.ll.lower; 621e72ca652SBlue Swirl } 622e72ca652SBlue Swirl 623e72ca652SBlue Swirl /* 128-bit FP subtraction RR */ 624449c0d70SBlue Swirl uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 625e72ca652SBlue Swirl { 626e72ca652SBlue Swirl CPU_QuadU v1; 627e72ca652SBlue Swirl CPU_QuadU v2; 628e72ca652SBlue Swirl CPU_QuadU res; 629e72ca652SBlue Swirl 630e72ca652SBlue Swirl v1.ll.upper = env->fregs[f1].ll; 631e72ca652SBlue Swirl v1.ll.lower = env->fregs[f1 + 2].ll; 632e72ca652SBlue Swirl v2.ll.upper = env->fregs[f2].ll; 633e72ca652SBlue Swirl v2.ll.lower = env->fregs[f2 + 2].ll; 634e72ca652SBlue Swirl res.q = float128_sub(v1.q, v2.q, &env->fpu_status); 635e72ca652SBlue Swirl env->fregs[f1].ll = res.ll.upper; 636e72ca652SBlue Swirl env->fregs[f1 + 2].ll = res.ll.lower; 637e72ca652SBlue Swirl return set_cc_nz_f128(res.q); 638e72ca652SBlue Swirl } 639e72ca652SBlue Swirl 640e72ca652SBlue Swirl /* 32-bit FP multiplication RR */ 641449c0d70SBlue Swirl void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 642e72ca652SBlue Swirl { 643e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper, 644e72ca652SBlue Swirl env->fregs[f2].l.upper, 645e72ca652SBlue Swirl &env->fpu_status); 646e72ca652SBlue Swirl } 647e72ca652SBlue Swirl 648e72ca652SBlue Swirl /* 64-bit FP division RR */ 649449c0d70SBlue Swirl void HELPER(ddbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 650e72ca652SBlue Swirl { 651e72ca652SBlue Swirl env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d, 652e72ca652SBlue Swirl &env->fpu_status); 653e72ca652SBlue Swirl } 654e72ca652SBlue Swirl 655e72ca652SBlue Swirl /* 64-bit FP multiply and add RM */ 656449c0d70SBlue Swirl void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3) 657e72ca652SBlue Swirl { 658e72ca652SBlue Swirl CPU_DoubleU v2; 659e72ca652SBlue Swirl 660e72ca652SBlue Swirl HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3); 661449c0d70SBlue Swirl v2.ll = cpu_ldq_data(env, a2); 662e72ca652SBlue Swirl env->fregs[f1].d = float64_add(env->fregs[f1].d, 663e72ca652SBlue Swirl float64_mul(v2.d, env->fregs[f3].d, 664e72ca652SBlue Swirl &env->fpu_status), 665e72ca652SBlue Swirl &env->fpu_status); 666e72ca652SBlue Swirl } 667e72ca652SBlue Swirl 668e72ca652SBlue Swirl /* 64-bit FP multiply and add RR */ 669449c0d70SBlue Swirl void HELPER(madbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2) 670e72ca652SBlue Swirl { 671e72ca652SBlue Swirl HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); 672e72ca652SBlue Swirl env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d, 673e72ca652SBlue Swirl env->fregs[f3].d, 674e72ca652SBlue Swirl &env->fpu_status), 675e72ca652SBlue Swirl env->fregs[f1].d, &env->fpu_status); 676e72ca652SBlue Swirl } 677e72ca652SBlue Swirl 678e72ca652SBlue Swirl /* 64-bit FP multiply and subtract RR */ 679449c0d70SBlue Swirl void HELPER(msdbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2) 680e72ca652SBlue Swirl { 681e72ca652SBlue Swirl HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3); 682e72ca652SBlue Swirl env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d, 683e72ca652SBlue Swirl env->fregs[f3].d, 684e72ca652SBlue Swirl &env->fpu_status), 685e72ca652SBlue Swirl env->fregs[f1].d, &env->fpu_status); 686e72ca652SBlue Swirl } 687e72ca652SBlue Swirl 688e72ca652SBlue Swirl /* 32-bit FP multiply and add RR */ 689449c0d70SBlue Swirl void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2) 690e72ca652SBlue Swirl { 691e72ca652SBlue Swirl env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper, 692e72ca652SBlue Swirl float32_mul(env->fregs[f2].l.upper, 693e72ca652SBlue Swirl env->fregs[f3].l.upper, 694e72ca652SBlue Swirl &env->fpu_status), 695e72ca652SBlue Swirl &env->fpu_status); 696e72ca652SBlue Swirl } 697e72ca652SBlue Swirl 698e72ca652SBlue Swirl /* test data class 32-bit */ 699449c0d70SBlue Swirl uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2) 700e72ca652SBlue Swirl { 701e72ca652SBlue Swirl float32 v1 = env->fregs[f1].l.upper; 702e72ca652SBlue Swirl int neg = float32_is_neg(v1); 703e72ca652SBlue Swirl uint32_t cc = 0; 704e72ca652SBlue Swirl 705e72ca652SBlue Swirl HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg); 706e72ca652SBlue Swirl if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || 707e72ca652SBlue Swirl (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 708e72ca652SBlue Swirl (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 709e72ca652SBlue Swirl (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 710e72ca652SBlue Swirl cc = 1; 711e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 712e72ca652SBlue Swirl /* assume normalized number */ 713e72ca652SBlue Swirl cc = 1; 714e72ca652SBlue Swirl } 715e72ca652SBlue Swirl 716e72ca652SBlue Swirl /* FIXME: denormalized? */ 717e72ca652SBlue Swirl return cc; 718e72ca652SBlue Swirl } 719e72ca652SBlue Swirl 720e72ca652SBlue Swirl /* test data class 64-bit */ 721449c0d70SBlue Swirl uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2) 722e72ca652SBlue Swirl { 723e72ca652SBlue Swirl float64 v1 = env->fregs[f1].d; 724e72ca652SBlue Swirl int neg = float64_is_neg(v1); 725e72ca652SBlue Swirl uint32_t cc = 0; 726e72ca652SBlue Swirl 727e72ca652SBlue Swirl HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg); 728e72ca652SBlue Swirl if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) || 729e72ca652SBlue Swirl (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 730e72ca652SBlue Swirl (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 731e72ca652SBlue Swirl (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 732e72ca652SBlue Swirl cc = 1; 733e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 734e72ca652SBlue Swirl /* assume normalized number */ 735e72ca652SBlue Swirl cc = 1; 736e72ca652SBlue Swirl } 737e72ca652SBlue Swirl /* FIXME: denormalized? */ 738e72ca652SBlue Swirl return cc; 739e72ca652SBlue Swirl } 740e72ca652SBlue Swirl 741e72ca652SBlue Swirl /* test data class 128-bit */ 742449c0d70SBlue Swirl uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2) 743e72ca652SBlue Swirl { 744e72ca652SBlue Swirl CPU_QuadU v1; 745e72ca652SBlue Swirl uint32_t cc = 0; 746e72ca652SBlue Swirl int neg; 747e72ca652SBlue Swirl 748e72ca652SBlue Swirl v1.ll.upper = env->fregs[f1].ll; 749e72ca652SBlue Swirl v1.ll.lower = env->fregs[f1 + 2].ll; 750e72ca652SBlue Swirl 751e72ca652SBlue Swirl neg = float128_is_neg(v1.q); 752e72ca652SBlue Swirl if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) || 753e72ca652SBlue Swirl (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) || 754e72ca652SBlue Swirl (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) || 755e72ca652SBlue Swirl (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) { 756e72ca652SBlue Swirl cc = 1; 757e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 758e72ca652SBlue Swirl /* assume normalized number */ 759e72ca652SBlue Swirl cc = 1; 760e72ca652SBlue Swirl } 761e72ca652SBlue Swirl /* FIXME: denormalized? */ 762e72ca652SBlue Swirl return cc; 763e72ca652SBlue Swirl } 764e72ca652SBlue Swirl 765e72ca652SBlue Swirl /* square root 64-bit RR */ 766449c0d70SBlue Swirl void HELPER(sqdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2) 767e72ca652SBlue Swirl { 768e72ca652SBlue Swirl env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status); 769e72ca652SBlue Swirl } 770