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" 22f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h" 232ef6175aSRichard Henderson #include "exec/helper-proto.h" 24e72ca652SBlue Swirl 25e72ca652SBlue Swirl /* #define DEBUG_HELPER */ 26e72ca652SBlue Swirl #ifdef DEBUG_HELPER 27e72ca652SBlue Swirl #define HELPER_LOG(x...) qemu_log(x) 28e72ca652SBlue Swirl #else 29e72ca652SBlue Swirl #define HELPER_LOG(x...) 30e72ca652SBlue Swirl #endif 31e72ca652SBlue Swirl 32587626f8SRichard Henderson #define RET128(F) (env->retxl = F.low, F.high) 33587626f8SRichard Henderson 34587626f8SRichard Henderson #define convert_bit(mask, from, to) \ 35587626f8SRichard Henderson (to < from \ 36587626f8SRichard Henderson ? (mask / (from / to)) & to \ 37587626f8SRichard Henderson : (mask & from) * (to / from)) 38587626f8SRichard Henderson 39587626f8SRichard Henderson static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr) 40587626f8SRichard Henderson { 41587626f8SRichard Henderson /* Install the DXC code. */ 42587626f8SRichard Henderson env->fpc = (env->fpc & ~0xff00) | (dxc << 8); 43587626f8SRichard Henderson /* Trap. */ 44587626f8SRichard Henderson runtime_exception(env, PGM_DATA, retaddr); 45587626f8SRichard Henderson } 46587626f8SRichard Henderson 47587626f8SRichard Henderson /* Should be called after any operation that may raise IEEE exceptions. */ 48587626f8SRichard Henderson static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr) 49587626f8SRichard Henderson { 50587626f8SRichard Henderson unsigned s390_exc, qemu_exc; 51587626f8SRichard Henderson 52587626f8SRichard Henderson /* Get the exceptions raised by the current operation. Reset the 53587626f8SRichard Henderson fpu_status contents so that the next operation has a clean slate. */ 54587626f8SRichard Henderson qemu_exc = env->fpu_status.float_exception_flags; 55587626f8SRichard Henderson if (qemu_exc == 0) { 56587626f8SRichard Henderson return; 57587626f8SRichard Henderson } 58587626f8SRichard Henderson env->fpu_status.float_exception_flags = 0; 59587626f8SRichard Henderson 60587626f8SRichard Henderson /* Convert softfloat exception bits to s390 exception bits. */ 61587626f8SRichard Henderson s390_exc = 0; 62587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80); 63587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40); 64587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20); 65587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10); 66587626f8SRichard Henderson s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08); 67587626f8SRichard Henderson 68587626f8SRichard Henderson /* Install the exceptions that we raised. */ 69587626f8SRichard Henderson env->fpc |= s390_exc << 16; 70587626f8SRichard Henderson 71587626f8SRichard Henderson /* Send signals for enabled exceptions. */ 72587626f8SRichard Henderson s390_exc &= env->fpc >> 24; 73587626f8SRichard Henderson if (s390_exc) { 74587626f8SRichard Henderson ieee_exception(env, s390_exc, retaddr); 75587626f8SRichard Henderson } 76587626f8SRichard Henderson } 77587626f8SRichard Henderson 78449c0d70SBlue Swirl static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) 79e72ca652SBlue Swirl { 80a47dddd7SAndreas Färber S390CPU *cpu = s390_env_get_cpu(env); 81a47dddd7SAndreas Färber 82e72ca652SBlue Swirl switch (float_compare) { 83e72ca652SBlue Swirl case float_relation_equal: 84e72ca652SBlue Swirl return 0; 85e72ca652SBlue Swirl case float_relation_less: 86e72ca652SBlue Swirl return 1; 87e72ca652SBlue Swirl case float_relation_greater: 88e72ca652SBlue Swirl return 2; 89e72ca652SBlue Swirl case float_relation_unordered: 90e72ca652SBlue Swirl return 3; 91e72ca652SBlue Swirl default: 92a47dddd7SAndreas Färber cpu_abort(CPU(cpu), "unknown return value for float compare\n"); 93e72ca652SBlue Swirl } 94e72ca652SBlue Swirl } 95e72ca652SBlue Swirl 96e72ca652SBlue Swirl /* condition codes for unary FP ops */ 97e72ca652SBlue Swirl uint32_t set_cc_nz_f32(float32 v) 98e72ca652SBlue Swirl { 99e72ca652SBlue Swirl if (float32_is_any_nan(v)) { 100e72ca652SBlue Swirl return 3; 101e72ca652SBlue Swirl } else if (float32_is_zero(v)) { 102e72ca652SBlue Swirl return 0; 103e72ca652SBlue Swirl } else if (float32_is_neg(v)) { 104e72ca652SBlue Swirl return 1; 105e72ca652SBlue Swirl } else { 106e72ca652SBlue Swirl return 2; 107e72ca652SBlue Swirl } 108e72ca652SBlue Swirl } 109e72ca652SBlue Swirl 110e72ca652SBlue Swirl uint32_t set_cc_nz_f64(float64 v) 111e72ca652SBlue Swirl { 112e72ca652SBlue Swirl if (float64_is_any_nan(v)) { 113e72ca652SBlue Swirl return 3; 114e72ca652SBlue Swirl } else if (float64_is_zero(v)) { 115e72ca652SBlue Swirl return 0; 116e72ca652SBlue Swirl } else if (float64_is_neg(v)) { 117e72ca652SBlue Swirl return 1; 118e72ca652SBlue Swirl } else { 119e72ca652SBlue Swirl return 2; 120e72ca652SBlue Swirl } 121e72ca652SBlue Swirl } 122e72ca652SBlue Swirl 123587626f8SRichard Henderson uint32_t set_cc_nz_f128(float128 v) 124e72ca652SBlue Swirl { 125e72ca652SBlue Swirl if (float128_is_any_nan(v)) { 126e72ca652SBlue Swirl return 3; 127e72ca652SBlue Swirl } else if (float128_is_zero(v)) { 128e72ca652SBlue Swirl return 0; 129e72ca652SBlue Swirl } else if (float128_is_neg(v)) { 130e72ca652SBlue Swirl return 1; 131e72ca652SBlue Swirl } else { 132e72ca652SBlue Swirl return 2; 133e72ca652SBlue Swirl } 134e72ca652SBlue Swirl } 135e72ca652SBlue Swirl 136587626f8SRichard Henderson /* 32-bit FP addition */ 137587626f8SRichard Henderson uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 138e72ca652SBlue Swirl { 139587626f8SRichard Henderson float32 ret = float32_add(f1, f2, &env->fpu_status); 140587626f8SRichard Henderson handle_exceptions(env, GETPC()); 141587626f8SRichard Henderson return ret; 142e72ca652SBlue Swirl } 143e72ca652SBlue Swirl 144587626f8SRichard Henderson /* 64-bit FP addition */ 145587626f8SRichard Henderson uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 146e72ca652SBlue Swirl { 147587626f8SRichard Henderson float64 ret = float64_add(f1, f2, &env->fpu_status); 148587626f8SRichard Henderson handle_exceptions(env, GETPC()); 149587626f8SRichard Henderson return ret; 150587626f8SRichard Henderson } 151e72ca652SBlue Swirl 152587626f8SRichard Henderson /* 128-bit FP addition */ 153587626f8SRichard Henderson uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al, 154587626f8SRichard Henderson uint64_t bh, uint64_t bl) 155587626f8SRichard Henderson { 156587626f8SRichard Henderson float128 ret = float128_add(make_float128(ah, al), 157587626f8SRichard Henderson make_float128(bh, bl), 158587626f8SRichard Henderson &env->fpu_status); 159587626f8SRichard Henderson handle_exceptions(env, GETPC()); 160587626f8SRichard Henderson return RET128(ret); 161e72ca652SBlue Swirl } 162e72ca652SBlue Swirl 1631a800a2dSRichard Henderson /* 32-bit FP subtraction */ 1641a800a2dSRichard Henderson uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 165e72ca652SBlue Swirl { 1661a800a2dSRichard Henderson float32 ret = float32_sub(f1, f2, &env->fpu_status); 1671a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 1681a800a2dSRichard Henderson return ret; 169e72ca652SBlue Swirl } 170e72ca652SBlue Swirl 1711a800a2dSRichard Henderson /* 64-bit FP subtraction */ 1721a800a2dSRichard Henderson uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 173e72ca652SBlue Swirl { 1741a800a2dSRichard Henderson float64 ret = float64_sub(f1, f2, &env->fpu_status); 1751a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 1761a800a2dSRichard Henderson return ret; 1771a800a2dSRichard Henderson } 178e72ca652SBlue Swirl 1791a800a2dSRichard Henderson /* 128-bit FP subtraction */ 1801a800a2dSRichard Henderson uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 1811a800a2dSRichard Henderson uint64_t bh, uint64_t bl) 1821a800a2dSRichard Henderson { 1831a800a2dSRichard Henderson float128 ret = float128_sub(make_float128(ah, al), 1841a800a2dSRichard Henderson make_float128(bh, bl), 1851a800a2dSRichard Henderson &env->fpu_status); 1861a800a2dSRichard Henderson handle_exceptions(env, GETPC()); 1871a800a2dSRichard Henderson return RET128(ret); 188e72ca652SBlue Swirl } 189e72ca652SBlue Swirl 190f08a5c31SRichard Henderson /* 32-bit FP division */ 191f08a5c31SRichard Henderson uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 192e72ca652SBlue Swirl { 193f08a5c31SRichard Henderson float32 ret = float32_div(f1, f2, &env->fpu_status); 194f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 195f08a5c31SRichard Henderson return ret; 196e72ca652SBlue Swirl } 197e72ca652SBlue Swirl 198f08a5c31SRichard Henderson /* 64-bit FP division */ 199f08a5c31SRichard Henderson uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 200e72ca652SBlue Swirl { 201f08a5c31SRichard Henderson float64 ret = float64_div(f1, f2, &env->fpu_status); 202f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 203f08a5c31SRichard Henderson return ret; 204f08a5c31SRichard Henderson } 205e72ca652SBlue Swirl 206f08a5c31SRichard Henderson /* 128-bit FP division */ 207f08a5c31SRichard Henderson uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 208f08a5c31SRichard Henderson uint64_t bh, uint64_t bl) 209f08a5c31SRichard Henderson { 210f08a5c31SRichard Henderson float128 ret = float128_div(make_float128(ah, al), 211f08a5c31SRichard Henderson make_float128(bh, bl), 212f08a5c31SRichard Henderson &env->fpu_status); 213f08a5c31SRichard Henderson handle_exceptions(env, GETPC()); 214f08a5c31SRichard Henderson return RET128(ret); 215e72ca652SBlue Swirl } 216e72ca652SBlue Swirl 21783b00736SRichard Henderson /* 32-bit FP multiplication */ 21883b00736SRichard Henderson uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 219e72ca652SBlue Swirl { 22083b00736SRichard Henderson float32 ret = float32_mul(f1, f2, &env->fpu_status); 22183b00736SRichard Henderson handle_exceptions(env, GETPC()); 22283b00736SRichard Henderson return ret; 223e72ca652SBlue Swirl } 224e72ca652SBlue Swirl 22583b00736SRichard Henderson /* 64-bit FP multiplication */ 22683b00736SRichard Henderson uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 227e72ca652SBlue Swirl { 22883b00736SRichard Henderson float64 ret = float64_mul(f1, f2, &env->fpu_status); 22983b00736SRichard Henderson handle_exceptions(env, GETPC()); 23083b00736SRichard Henderson return ret; 23183b00736SRichard Henderson } 232e72ca652SBlue Swirl 23383b00736SRichard Henderson /* 64/32-bit FP multiplication */ 23483b00736SRichard Henderson uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 23583b00736SRichard Henderson { 23683b00736SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 23783b00736SRichard Henderson ret = float64_mul(f1, ret, &env->fpu_status); 23883b00736SRichard Henderson handle_exceptions(env, GETPC()); 23983b00736SRichard Henderson return ret; 24083b00736SRichard Henderson } 24183b00736SRichard Henderson 24283b00736SRichard Henderson /* 128-bit FP multiplication */ 24383b00736SRichard Henderson uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 24483b00736SRichard Henderson uint64_t bh, uint64_t bl) 24583b00736SRichard Henderson { 24683b00736SRichard Henderson float128 ret = float128_mul(make_float128(ah, al), 24783b00736SRichard Henderson make_float128(bh, bl), 24883b00736SRichard Henderson &env->fpu_status); 24983b00736SRichard Henderson handle_exceptions(env, GETPC()); 25083b00736SRichard Henderson return RET128(ret); 25183b00736SRichard Henderson } 25283b00736SRichard Henderson 25383b00736SRichard Henderson /* 128/64-bit FP multiplication */ 25483b00736SRichard Henderson uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al, 25583b00736SRichard Henderson uint64_t f2) 25683b00736SRichard Henderson { 25783b00736SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 25883b00736SRichard Henderson ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status); 25983b00736SRichard Henderson handle_exceptions(env, GETPC()); 26083b00736SRichard Henderson return RET128(ret); 261e72ca652SBlue Swirl } 262e72ca652SBlue Swirl 263e72ca652SBlue Swirl /* convert 32-bit float to 64-bit float */ 264587626f8SRichard Henderson uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2) 265e72ca652SBlue Swirl { 266587626f8SRichard Henderson float64 ret = float32_to_float64(f2, &env->fpu_status); 267587626f8SRichard Henderson handle_exceptions(env, GETPC()); 268f821135cSAurelien Jarno return float64_maybe_silence_nan(ret); 269e72ca652SBlue Swirl } 270e72ca652SBlue Swirl 271e72ca652SBlue Swirl /* convert 128-bit float to 64-bit float */ 272587626f8SRichard Henderson uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 273e72ca652SBlue Swirl { 274587626f8SRichard Henderson float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); 275587626f8SRichard Henderson handle_exceptions(env, GETPC()); 276f821135cSAurelien Jarno return float64_maybe_silence_nan(ret); 277e72ca652SBlue Swirl } 278e72ca652SBlue Swirl 279e72ca652SBlue Swirl /* convert 64-bit float to 128-bit float */ 280587626f8SRichard Henderson uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) 281e72ca652SBlue Swirl { 282587626f8SRichard Henderson float128 ret = float64_to_float128(f2, &env->fpu_status); 283587626f8SRichard Henderson handle_exceptions(env, GETPC()); 284f821135cSAurelien Jarno return RET128(float128_maybe_silence_nan(ret)); 285587626f8SRichard Henderson } 286e72ca652SBlue Swirl 287587626f8SRichard Henderson /* convert 32-bit float to 128-bit float */ 288587626f8SRichard Henderson uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) 289587626f8SRichard Henderson { 290587626f8SRichard Henderson float128 ret = float32_to_float128(f2, &env->fpu_status); 291587626f8SRichard Henderson handle_exceptions(env, GETPC()); 292f821135cSAurelien Jarno return RET128(float128_maybe_silence_nan(ret)); 293e72ca652SBlue Swirl } 294e72ca652SBlue Swirl 295e72ca652SBlue Swirl /* convert 64-bit float to 32-bit float */ 296587626f8SRichard Henderson uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2) 297e72ca652SBlue Swirl { 298587626f8SRichard Henderson float32 ret = float64_to_float32(f2, &env->fpu_status); 299587626f8SRichard Henderson handle_exceptions(env, GETPC()); 300f821135cSAurelien Jarno return float32_maybe_silence_nan(ret); 301e72ca652SBlue Swirl } 302e72ca652SBlue Swirl 303e72ca652SBlue Swirl /* convert 128-bit float to 32-bit float */ 304587626f8SRichard Henderson uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al) 305e72ca652SBlue Swirl { 306587626f8SRichard Henderson float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); 307587626f8SRichard Henderson handle_exceptions(env, GETPC()); 308f821135cSAurelien Jarno return float32_maybe_silence_nan(ret); 309e72ca652SBlue Swirl } 310e72ca652SBlue Swirl 311587626f8SRichard Henderson /* 32-bit FP compare */ 312587626f8SRichard Henderson uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 313e72ca652SBlue Swirl { 314587626f8SRichard Henderson int cmp = float32_compare_quiet(f1, f2, &env->fpu_status); 315587626f8SRichard Henderson handle_exceptions(env, GETPC()); 316587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 317e72ca652SBlue Swirl } 318e72ca652SBlue Swirl 319587626f8SRichard Henderson /* 64-bit FP compare */ 320587626f8SRichard Henderson uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) 321e72ca652SBlue Swirl { 322587626f8SRichard Henderson int cmp = float64_compare_quiet(f1, f2, &env->fpu_status); 323587626f8SRichard Henderson handle_exceptions(env, GETPC()); 324587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 325e72ca652SBlue Swirl } 326e72ca652SBlue Swirl 327587626f8SRichard Henderson /* 128-bit FP compare */ 328587626f8SRichard Henderson uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, 329587626f8SRichard Henderson uint64_t bh, uint64_t bl) 330e72ca652SBlue Swirl { 331587626f8SRichard Henderson int cmp = float128_compare_quiet(make_float128(ah, al), 332587626f8SRichard Henderson make_float128(bh, bl), 333587626f8SRichard Henderson &env->fpu_status); 334587626f8SRichard Henderson handle_exceptions(env, GETPC()); 335587626f8SRichard Henderson return float_comp_to_cc(env, cmp); 336e72ca652SBlue Swirl } 337e72ca652SBlue Swirl 33868c8bd93SRichard Henderson static int swap_round_mode(CPUS390XState *env, int m3) 339e72ca652SBlue Swirl { 34068c8bd93SRichard Henderson int ret = env->fpu_status.float_rounding_mode; 341e72ca652SBlue Swirl switch (m3) { 342e72ca652SBlue Swirl case 0: 343e72ca652SBlue Swirl /* current mode */ 344e72ca652SBlue Swirl break; 345e72ca652SBlue Swirl case 1: 346e72ca652SBlue Swirl /* biased round no nearest */ 347e72ca652SBlue Swirl case 4: 348e72ca652SBlue Swirl /* round to nearest */ 349e72ca652SBlue Swirl set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); 350e72ca652SBlue Swirl break; 351e72ca652SBlue Swirl case 5: 352e72ca652SBlue Swirl /* round to zero */ 353e72ca652SBlue Swirl set_float_rounding_mode(float_round_to_zero, &env->fpu_status); 354e72ca652SBlue Swirl break; 355e72ca652SBlue Swirl case 6: 356e72ca652SBlue Swirl /* round to +inf */ 357e72ca652SBlue Swirl set_float_rounding_mode(float_round_up, &env->fpu_status); 358e72ca652SBlue Swirl break; 359e72ca652SBlue Swirl case 7: 360e72ca652SBlue Swirl /* round to -inf */ 361e72ca652SBlue Swirl set_float_rounding_mode(float_round_down, &env->fpu_status); 362e72ca652SBlue Swirl break; 363e72ca652SBlue Swirl } 36468c8bd93SRichard Henderson return ret; 365e72ca652SBlue Swirl } 366e72ca652SBlue Swirl 367683bb9a8SRichard Henderson /* convert 64-bit int to 32-bit float */ 368683bb9a8SRichard Henderson uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3) 369683bb9a8SRichard Henderson { 370683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 371683bb9a8SRichard Henderson float32 ret = int64_to_float32(v2, &env->fpu_status); 372683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 373683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 374683bb9a8SRichard Henderson return ret; 375683bb9a8SRichard Henderson } 376683bb9a8SRichard Henderson 377683bb9a8SRichard Henderson /* convert 64-bit int to 64-bit float */ 378683bb9a8SRichard Henderson uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3) 379683bb9a8SRichard Henderson { 380683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 381683bb9a8SRichard Henderson float64 ret = int64_to_float64(v2, &env->fpu_status); 382683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 383683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 384683bb9a8SRichard Henderson return ret; 385683bb9a8SRichard Henderson } 386683bb9a8SRichard Henderson 387683bb9a8SRichard Henderson /* convert 64-bit int to 128-bit float */ 388683bb9a8SRichard Henderson uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3) 389683bb9a8SRichard Henderson { 390683bb9a8SRichard Henderson int hold = swap_round_mode(env, m3); 391683bb9a8SRichard Henderson float128 ret = int64_to_float128(v2, &env->fpu_status); 392683bb9a8SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 393683bb9a8SRichard Henderson handle_exceptions(env, GETPC()); 394683bb9a8SRichard Henderson return RET128(ret); 395683bb9a8SRichard Henderson } 396683bb9a8SRichard Henderson 3972112bf1bSRichard Henderson /* convert 64-bit uint to 32-bit float */ 3982112bf1bSRichard Henderson uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 3992112bf1bSRichard Henderson { 4002112bf1bSRichard Henderson int hold = swap_round_mode(env, m3); 4012112bf1bSRichard Henderson float32 ret = uint64_to_float32(v2, &env->fpu_status); 4022112bf1bSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 4032112bf1bSRichard Henderson handle_exceptions(env, GETPC()); 4042112bf1bSRichard Henderson return ret; 4052112bf1bSRichard Henderson } 4062112bf1bSRichard Henderson 4072112bf1bSRichard Henderson /* convert 64-bit uint to 64-bit float */ 4082112bf1bSRichard Henderson uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 4092112bf1bSRichard Henderson { 4102112bf1bSRichard Henderson int hold = swap_round_mode(env, m3); 4112112bf1bSRichard Henderson float64 ret = uint64_to_float64(v2, &env->fpu_status); 4122112bf1bSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 4132112bf1bSRichard Henderson handle_exceptions(env, GETPC()); 4142112bf1bSRichard Henderson return ret; 4152112bf1bSRichard Henderson } 4162112bf1bSRichard Henderson 4172112bf1bSRichard Henderson /* convert 64-bit uint to 128-bit float */ 4182112bf1bSRichard Henderson uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 4192112bf1bSRichard Henderson { 4202112bf1bSRichard Henderson int hold = swap_round_mode(env, m3); 421d2d9feacSRichard Henderson float128 ret = uint64_to_float128(v2, &env->fpu_status); 4222112bf1bSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 4232112bf1bSRichard Henderson handle_exceptions(env, GETPC()); 4242112bf1bSRichard Henderson return RET128(ret); 4252112bf1bSRichard Henderson } 4262112bf1bSRichard Henderson 427e72ca652SBlue Swirl /* convert 32-bit float to 64-bit int */ 42868c8bd93SRichard Henderson uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 429e72ca652SBlue Swirl { 43068c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 43168c8bd93SRichard Henderson int64_t ret = float32_to_int64(v2, &env->fpu_status); 43268c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 43368c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 43468c8bd93SRichard Henderson return ret; 435e72ca652SBlue Swirl } 436e72ca652SBlue Swirl 437e72ca652SBlue Swirl /* convert 64-bit float to 64-bit int */ 43868c8bd93SRichard Henderson uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 439e72ca652SBlue Swirl { 44068c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 44168c8bd93SRichard Henderson int64_t ret = float64_to_int64(v2, &env->fpu_status); 44268c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 44368c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 44468c8bd93SRichard Henderson return ret; 445e72ca652SBlue Swirl } 446e72ca652SBlue Swirl 447e72ca652SBlue Swirl /* convert 128-bit float to 64-bit int */ 44868c8bd93SRichard Henderson uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 449e72ca652SBlue Swirl { 45068c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 45168c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 45268c8bd93SRichard Henderson int64_t ret = float128_to_int64(v2, &env->fpu_status); 45368c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 45468c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 45568c8bd93SRichard Henderson return ret; 456e72ca652SBlue Swirl } 457e72ca652SBlue Swirl 458e72ca652SBlue Swirl /* convert 32-bit float to 32-bit int */ 45968c8bd93SRichard Henderson uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 460e72ca652SBlue Swirl { 46168c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 46268c8bd93SRichard Henderson int32_t ret = float32_to_int32(v2, &env->fpu_status); 46368c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 46468c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 46568c8bd93SRichard Henderson return ret; 466e72ca652SBlue Swirl } 467e72ca652SBlue Swirl 468e72ca652SBlue Swirl /* convert 64-bit float to 32-bit int */ 46968c8bd93SRichard Henderson uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 470e72ca652SBlue Swirl { 47168c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 47268c8bd93SRichard Henderson int32_t ret = float64_to_int32(v2, &env->fpu_status); 47368c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 47468c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 47568c8bd93SRichard Henderson return ret; 476e72ca652SBlue Swirl } 477e72ca652SBlue Swirl 478e72ca652SBlue Swirl /* convert 128-bit float to 32-bit int */ 47968c8bd93SRichard Henderson uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 480e72ca652SBlue Swirl { 48168c8bd93SRichard Henderson int hold = swap_round_mode(env, m3); 48268c8bd93SRichard Henderson float128 v2 = make_float128(h, l); 48368c8bd93SRichard Henderson int32_t ret = float128_to_int32(v2, &env->fpu_status); 48468c8bd93SRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 48568c8bd93SRichard Henderson handle_exceptions(env, GETPC()); 48668c8bd93SRichard Henderson return ret; 487e72ca652SBlue Swirl } 488e72ca652SBlue Swirl 4896ac1b45fSRichard Henderson /* convert 32-bit float to 64-bit uint */ 4906ac1b45fSRichard Henderson uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 4916ac1b45fSRichard Henderson { 4926ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 4936ac1b45fSRichard Henderson uint64_t ret; 4946ac1b45fSRichard Henderson v2 = float32_to_float64(v2, &env->fpu_status); 4956ac1b45fSRichard Henderson ret = float64_to_uint64(v2, &env->fpu_status); 4966ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 4976ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 4986ac1b45fSRichard Henderson return ret; 4996ac1b45fSRichard Henderson } 5006ac1b45fSRichard Henderson 5016ac1b45fSRichard Henderson /* convert 64-bit float to 64-bit uint */ 5026ac1b45fSRichard Henderson uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 5036ac1b45fSRichard Henderson { 5046ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5056ac1b45fSRichard Henderson uint64_t ret = float64_to_uint64(v2, &env->fpu_status); 5066ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5076ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5086ac1b45fSRichard Henderson return ret; 5096ac1b45fSRichard Henderson } 5106ac1b45fSRichard Henderson 5116ac1b45fSRichard Henderson /* convert 128-bit float to 64-bit uint */ 5126ac1b45fSRichard Henderson uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 5136ac1b45fSRichard Henderson { 5146ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5156ac1b45fSRichard Henderson float128 v2 = make_float128(h, l); 5166ac1b45fSRichard Henderson /* ??? Not 100% correct. */ 5176ac1b45fSRichard Henderson uint64_t ret = float128_to_int64(v2, &env->fpu_status); 5186ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5196ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5206ac1b45fSRichard Henderson return ret; 5216ac1b45fSRichard Henderson } 5226ac1b45fSRichard Henderson 5236ac1b45fSRichard Henderson /* convert 32-bit float to 32-bit uint */ 5246ac1b45fSRichard Henderson uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 5256ac1b45fSRichard Henderson { 5266ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5276ac1b45fSRichard Henderson uint32_t ret = float32_to_uint32(v2, &env->fpu_status); 5286ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5296ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5306ac1b45fSRichard Henderson return ret; 5316ac1b45fSRichard Henderson } 5326ac1b45fSRichard Henderson 5336ac1b45fSRichard Henderson /* convert 64-bit float to 32-bit uint */ 5346ac1b45fSRichard Henderson uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) 5356ac1b45fSRichard Henderson { 5366ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5376ac1b45fSRichard Henderson uint32_t ret = float64_to_uint32(v2, &env->fpu_status); 5386ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5396ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5406ac1b45fSRichard Henderson return ret; 5416ac1b45fSRichard Henderson } 5426ac1b45fSRichard Henderson 5436ac1b45fSRichard Henderson /* convert 128-bit float to 32-bit uint */ 5446ac1b45fSRichard Henderson uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) 5456ac1b45fSRichard Henderson { 5466ac1b45fSRichard Henderson int hold = swap_round_mode(env, m3); 5476ac1b45fSRichard Henderson float128 v2 = make_float128(h, l); 5486ac1b45fSRichard Henderson /* Not 100% correct. */ 5496ac1b45fSRichard Henderson uint32_t ret = float128_to_int64(v2, &env->fpu_status); 5506ac1b45fSRichard Henderson set_float_rounding_mode(hold, &env->fpu_status); 5516ac1b45fSRichard Henderson handle_exceptions(env, GETPC()); 5526ac1b45fSRichard Henderson return ret; 5536ac1b45fSRichard Henderson } 5546ac1b45fSRichard Henderson 555ed0bceceSAurelien Jarno /* round to integer 32-bit */ 556ed0bceceSAurelien Jarno uint64_t HELPER(fieb)(CPUS390XState *env, uint64_t f2, uint32_t m3) 557ed0bceceSAurelien Jarno { 558ed0bceceSAurelien Jarno int hold = swap_round_mode(env, m3); 559ed0bceceSAurelien Jarno float32 ret = float32_round_to_int(f2, &env->fpu_status); 560ed0bceceSAurelien Jarno set_float_rounding_mode(hold, &env->fpu_status); 561ed0bceceSAurelien Jarno handle_exceptions(env, GETPC()); 562ed0bceceSAurelien Jarno return ret; 563ed0bceceSAurelien Jarno } 564ed0bceceSAurelien Jarno 565ed0bceceSAurelien Jarno /* round to integer 64-bit */ 566ed0bceceSAurelien Jarno uint64_t HELPER(fidb)(CPUS390XState *env, uint64_t f2, uint32_t m3) 567ed0bceceSAurelien Jarno { 568ed0bceceSAurelien Jarno int hold = swap_round_mode(env, m3); 569ed0bceceSAurelien Jarno float64 ret = float64_round_to_int(f2, &env->fpu_status); 570ed0bceceSAurelien Jarno set_float_rounding_mode(hold, &env->fpu_status); 571ed0bceceSAurelien Jarno handle_exceptions(env, GETPC()); 572ed0bceceSAurelien Jarno return ret; 573ed0bceceSAurelien Jarno } 574ed0bceceSAurelien Jarno 575ed0bceceSAurelien Jarno /* round to integer 128-bit */ 576ed0bceceSAurelien Jarno uint64_t HELPER(fixb)(CPUS390XState *env, uint64_t ah, uint64_t al, uint32_t m3) 577ed0bceceSAurelien Jarno { 578ed0bceceSAurelien Jarno int hold = swap_round_mode(env, m3); 579ed0bceceSAurelien Jarno float128 ret = float128_round_to_int(make_float128(ah, al), 580ed0bceceSAurelien Jarno &env->fpu_status); 581ed0bceceSAurelien Jarno set_float_rounding_mode(hold, &env->fpu_status); 582ed0bceceSAurelien Jarno handle_exceptions(env, GETPC()); 583ed0bceceSAurelien Jarno return RET128(ret); 584ed0bceceSAurelien Jarno } 585ed0bceceSAurelien Jarno 586722bfec3SRichard Henderson /* 32-bit FP multiply and add */ 587722bfec3SRichard Henderson uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, 588722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 589e72ca652SBlue Swirl { 590722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status); 591722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 592722bfec3SRichard Henderson return ret; 593722bfec3SRichard Henderson } 594e72ca652SBlue Swirl 595722bfec3SRichard Henderson /* 64-bit FP multiply and add */ 596722bfec3SRichard Henderson uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1, 597722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 598722bfec3SRichard Henderson { 599722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status); 600722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 601722bfec3SRichard Henderson return ret; 602722bfec3SRichard Henderson } 603722bfec3SRichard Henderson 604722bfec3SRichard Henderson /* 32-bit FP multiply and subtract */ 605722bfec3SRichard Henderson uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1, 606722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 607722bfec3SRichard Henderson { 608722bfec3SRichard Henderson float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c, 609e72ca652SBlue Swirl &env->fpu_status); 610722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 611722bfec3SRichard Henderson return ret; 612e72ca652SBlue Swirl } 613e72ca652SBlue Swirl 614722bfec3SRichard Henderson /* 64-bit FP multiply and subtract */ 615722bfec3SRichard Henderson uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1, 616722bfec3SRichard Henderson uint64_t f2, uint64_t f3) 617e72ca652SBlue Swirl { 618722bfec3SRichard Henderson float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c, 619e72ca652SBlue Swirl &env->fpu_status); 620722bfec3SRichard Henderson handle_exceptions(env, GETPC()); 621722bfec3SRichard Henderson return ret; 622e72ca652SBlue Swirl } 623e72ca652SBlue Swirl 624e72ca652SBlue Swirl /* test data class 32-bit */ 62531aa97d1SRichard Henderson uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2) 626e72ca652SBlue Swirl { 62731aa97d1SRichard Henderson float32 v1 = f1; 628e72ca652SBlue Swirl int neg = float32_is_neg(v1); 629e72ca652SBlue Swirl uint32_t cc = 0; 630e72ca652SBlue Swirl 631e72ca652SBlue Swirl if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || 632e72ca652SBlue Swirl (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 633e72ca652SBlue Swirl (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 634e72ca652SBlue Swirl (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 635e72ca652SBlue Swirl cc = 1; 636e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 637e72ca652SBlue Swirl /* assume normalized number */ 638e72ca652SBlue Swirl cc = 1; 639e72ca652SBlue Swirl } 640e72ca652SBlue Swirl /* FIXME: denormalized? */ 641e72ca652SBlue Swirl return cc; 642e72ca652SBlue Swirl } 643e72ca652SBlue Swirl 644e72ca652SBlue Swirl /* test data class 64-bit */ 64531aa97d1SRichard Henderson uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2) 646e72ca652SBlue Swirl { 647e72ca652SBlue Swirl int neg = float64_is_neg(v1); 648e72ca652SBlue Swirl uint32_t cc = 0; 649e72ca652SBlue Swirl 650e72ca652SBlue Swirl if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) || 651e72ca652SBlue Swirl (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 652e72ca652SBlue Swirl (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 653e72ca652SBlue Swirl (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 654e72ca652SBlue Swirl cc = 1; 655e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 656e72ca652SBlue Swirl /* assume normalized number */ 657e72ca652SBlue Swirl cc = 1; 658e72ca652SBlue Swirl } 659e72ca652SBlue Swirl /* FIXME: denormalized? */ 660e72ca652SBlue Swirl return cc; 661e72ca652SBlue Swirl } 662e72ca652SBlue Swirl 663e72ca652SBlue Swirl /* test data class 128-bit */ 66431aa97d1SRichard Henderson uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2) 665e72ca652SBlue Swirl { 66631aa97d1SRichard Henderson float128 v1 = make_float128(ah, al); 66731aa97d1SRichard Henderson int neg = float128_is_neg(v1); 668e72ca652SBlue Swirl uint32_t cc = 0; 669e72ca652SBlue Swirl 67031aa97d1SRichard Henderson if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) || 67131aa97d1SRichard Henderson (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) || 67231aa97d1SRichard Henderson (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || 67331aa97d1SRichard Henderson (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { 674e72ca652SBlue Swirl cc = 1; 675e72ca652SBlue Swirl } else if (m2 & (1 << (9-neg))) { 676e72ca652SBlue Swirl /* assume normalized number */ 677e72ca652SBlue Swirl cc = 1; 678e72ca652SBlue Swirl } 679e72ca652SBlue Swirl /* FIXME: denormalized? */ 680e72ca652SBlue Swirl return cc; 681e72ca652SBlue Swirl } 682e72ca652SBlue Swirl 68316d7b2a4SRichard Henderson /* square root 32-bit */ 68416d7b2a4SRichard Henderson uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2) 685e72ca652SBlue Swirl { 68616d7b2a4SRichard Henderson float32 ret = float32_sqrt(f2, &env->fpu_status); 68716d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 68816d7b2a4SRichard Henderson return ret; 68916d7b2a4SRichard Henderson } 69016d7b2a4SRichard Henderson 69116d7b2a4SRichard Henderson /* square root 64-bit */ 69216d7b2a4SRichard Henderson uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2) 69316d7b2a4SRichard Henderson { 69416d7b2a4SRichard Henderson float64 ret = float64_sqrt(f2, &env->fpu_status); 69516d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 69616d7b2a4SRichard Henderson return ret; 69716d7b2a4SRichard Henderson } 69816d7b2a4SRichard Henderson 69916d7b2a4SRichard Henderson /* square root 128-bit */ 70016d7b2a4SRichard Henderson uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al) 70116d7b2a4SRichard Henderson { 70216d7b2a4SRichard Henderson float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status); 70316d7b2a4SRichard Henderson handle_exceptions(env, GETPC()); 70416d7b2a4SRichard Henderson return RET128(ret); 705e72ca652SBlue Swirl } 7068379bfdbSRichard Henderson 707411edc22SRichard Henderson static const int fpc_to_rnd[4] = { 7088379bfdbSRichard Henderson float_round_nearest_even, 7098379bfdbSRichard Henderson float_round_to_zero, 7108379bfdbSRichard Henderson float_round_up, 7118379bfdbSRichard Henderson float_round_down 7128379bfdbSRichard Henderson }; 7138379bfdbSRichard Henderson 714411edc22SRichard Henderson /* set fpc */ 715411edc22SRichard Henderson void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc) 716411edc22SRichard Henderson { 7178379bfdbSRichard Henderson /* Install everything in the main FPC. */ 7188379bfdbSRichard Henderson env->fpc = fpc; 7198379bfdbSRichard Henderson 7208379bfdbSRichard Henderson /* Install the rounding mode in the shadow fpu_status. */ 721411edc22SRichard Henderson set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status); 722411edc22SRichard Henderson } 723411edc22SRichard Henderson 724411edc22SRichard Henderson /* set fpc and signal */ 725411edc22SRichard Henderson void HELPER(sfas)(CPUS390XState *env, uint64_t val) 726411edc22SRichard Henderson { 727411edc22SRichard Henderson uint32_t signalling = env->fpc; 728411edc22SRichard Henderson uint32_t source = val; 729411edc22SRichard Henderson uint32_t s390_exc; 730411edc22SRichard Henderson 731411edc22SRichard Henderson /* The contents of the source operand are placed in the FPC register; 732411edc22SRichard Henderson then the flags in the FPC register are set to the logical OR of the 733411edc22SRichard Henderson signalling flags and the source flags. */ 734411edc22SRichard Henderson env->fpc = source | (signalling & 0x00ff0000); 735411edc22SRichard Henderson set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status); 736411edc22SRichard Henderson 737411edc22SRichard Henderson /* If any signalling flag is 1 and the corresponding source mask 738411edc22SRichard Henderson is also 1, a simulated-iee-exception trap occurs. */ 739411edc22SRichard Henderson s390_exc = (signalling >> 16) & (source >> 24); 740411edc22SRichard Henderson if (s390_exc) { 741411edc22SRichard Henderson ieee_exception(env, s390_exc | 3, GETPC()); 742411edc22SRichard Henderson } 7438379bfdbSRichard Henderson } 744