14a58aedfSRichard Henderson /* 24a58aedfSRichard Henderson * Helpers for floating point instructions. 34a58aedfSRichard Henderson * 44a58aedfSRichard Henderson * Copyright (c) 2007 Jocelyn Mayer 54a58aedfSRichard Henderson * 64a58aedfSRichard Henderson * This library is free software; you can redistribute it and/or 74a58aedfSRichard Henderson * modify it under the terms of the GNU Lesser General Public 84a58aedfSRichard Henderson * License as published by the Free Software Foundation; either 94a58aedfSRichard Henderson * version 2 of the License, or (at your option) any later version. 104a58aedfSRichard Henderson * 114a58aedfSRichard Henderson * This library is distributed in the hope that it will be useful, 124a58aedfSRichard Henderson * but WITHOUT ANY WARRANTY; without even the implied warranty of 134a58aedfSRichard Henderson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 144a58aedfSRichard Henderson * Lesser General Public License for more details. 154a58aedfSRichard Henderson * 164a58aedfSRichard Henderson * You should have received a copy of the GNU Lesser General Public 174a58aedfSRichard Henderson * License along with this library; if not, see <http://www.gnu.org/licenses/>. 184a58aedfSRichard Henderson */ 194a58aedfSRichard Henderson 204a58aedfSRichard Henderson #include "cpu.h" 214a58aedfSRichard Henderson #include "helper.h" 226b4c305cSPaolo Bonzini #include "fpu/softfloat.h" 234a58aedfSRichard Henderson 244a58aedfSRichard Henderson #define FP_STATUS (env->fp_status) 254a58aedfSRichard Henderson 264a58aedfSRichard Henderson 274a58aedfSRichard Henderson void helper_setroundmode(CPUAlphaState *env, uint32_t val) 284a58aedfSRichard Henderson { 294a58aedfSRichard Henderson set_float_rounding_mode(val, &FP_STATUS); 304a58aedfSRichard Henderson } 314a58aedfSRichard Henderson 324a58aedfSRichard Henderson void helper_setflushzero(CPUAlphaState *env, uint32_t val) 334a58aedfSRichard Henderson { 344a58aedfSRichard Henderson set_flush_to_zero(val, &FP_STATUS); 354a58aedfSRichard Henderson } 364a58aedfSRichard Henderson 374a58aedfSRichard Henderson void helper_fp_exc_clear(CPUAlphaState *env) 384a58aedfSRichard Henderson { 394a58aedfSRichard Henderson set_float_exception_flags(0, &FP_STATUS); 404a58aedfSRichard Henderson } 414a58aedfSRichard Henderson 424a58aedfSRichard Henderson uint32_t helper_fp_exc_get(CPUAlphaState *env) 434a58aedfSRichard Henderson { 444a58aedfSRichard Henderson return get_float_exception_flags(&FP_STATUS); 454a58aedfSRichard Henderson } 464a58aedfSRichard Henderson 4720503968SBlue Swirl static inline void inline_fp_exc_raise(CPUAlphaState *env, uintptr_t retaddr, 484a58aedfSRichard Henderson uint32_t exc, uint32_t regno) 494a58aedfSRichard Henderson { 504a58aedfSRichard Henderson if (exc) { 514a58aedfSRichard Henderson uint32_t hw_exc = 0; 524a58aedfSRichard Henderson 534a58aedfSRichard Henderson if (exc & float_flag_invalid) { 544a58aedfSRichard Henderson hw_exc |= EXC_M_INV; 554a58aedfSRichard Henderson } 564a58aedfSRichard Henderson if (exc & float_flag_divbyzero) { 574a58aedfSRichard Henderson hw_exc |= EXC_M_DZE; 584a58aedfSRichard Henderson } 594a58aedfSRichard Henderson if (exc & float_flag_overflow) { 604a58aedfSRichard Henderson hw_exc |= EXC_M_FOV; 614a58aedfSRichard Henderson } 624a58aedfSRichard Henderson if (exc & float_flag_underflow) { 634a58aedfSRichard Henderson hw_exc |= EXC_M_UNF; 644a58aedfSRichard Henderson } 654a58aedfSRichard Henderson if (exc & float_flag_inexact) { 664a58aedfSRichard Henderson hw_exc |= EXC_M_INE; 674a58aedfSRichard Henderson } 684a58aedfSRichard Henderson 694a58aedfSRichard Henderson arith_excp(env, retaddr, hw_exc, 1ull << regno); 704a58aedfSRichard Henderson } 714a58aedfSRichard Henderson } 724a58aedfSRichard Henderson 734a58aedfSRichard Henderson /* Raise exceptions for ieee fp insns without software completion. 744a58aedfSRichard Henderson In that case there are no exceptions that don't trap; the mask 754a58aedfSRichard Henderson doesn't apply. */ 764a58aedfSRichard Henderson void helper_fp_exc_raise(CPUAlphaState *env, uint32_t exc, uint32_t regno) 774a58aedfSRichard Henderson { 784a58aedfSRichard Henderson inline_fp_exc_raise(env, GETPC(), exc, regno); 794a58aedfSRichard Henderson } 804a58aedfSRichard Henderson 814a58aedfSRichard Henderson /* Raise exceptions for ieee fp insns with software completion. */ 824a58aedfSRichard Henderson void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno) 834a58aedfSRichard Henderson { 844a58aedfSRichard Henderson if (exc) { 854a58aedfSRichard Henderson env->fpcr_exc_status |= exc; 864a58aedfSRichard Henderson exc &= ~env->fpcr_exc_mask; 874a58aedfSRichard Henderson inline_fp_exc_raise(env, GETPC(), exc, regno); 884a58aedfSRichard Henderson } 894a58aedfSRichard Henderson } 904a58aedfSRichard Henderson 9174343409SRichard Henderson /* Input handing without software completion. Trap for all 9274343409SRichard Henderson non-finite numbers. */ 9374343409SRichard Henderson void helper_ieee_input(CPUAlphaState *env, uint64_t val) 944a58aedfSRichard Henderson { 954a58aedfSRichard Henderson uint32_t exp = (uint32_t)(val >> 52) & 0x7ff; 964a58aedfSRichard Henderson uint64_t frac = val & 0xfffffffffffffull; 974a58aedfSRichard Henderson 984a58aedfSRichard Henderson if (exp == 0) { 9974343409SRichard Henderson /* Denormals without DNZ set raise an exception. */ 10074343409SRichard Henderson if (frac != 0 && !env->fp_status.flush_inputs_to_zero) { 1014a58aedfSRichard Henderson arith_excp(env, GETPC(), EXC_M_UNF, 0); 1024a58aedfSRichard Henderson } 1034a58aedfSRichard Henderson } else if (exp == 0x7ff) { 1044a58aedfSRichard Henderson /* Infinity or NaN. */ 1054a58aedfSRichard Henderson /* ??? I'm not sure these exception bit flags are correct. I do 1064a58aedfSRichard Henderson know that the Linux kernel, at least, doesn't rely on them and 1074a58aedfSRichard Henderson just emulates the insn to figure out what exception to use. */ 1084a58aedfSRichard Henderson arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0); 1094a58aedfSRichard Henderson } 1104a58aedfSRichard Henderson } 1114a58aedfSRichard Henderson 1124a58aedfSRichard Henderson /* Similar, but does not trap for infinities. Used for comparisons. */ 11374343409SRichard Henderson void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val) 1144a58aedfSRichard Henderson { 1154a58aedfSRichard Henderson uint32_t exp = (uint32_t)(val >> 52) & 0x7ff; 1164a58aedfSRichard Henderson uint64_t frac = val & 0xfffffffffffffull; 1174a58aedfSRichard Henderson 1184a58aedfSRichard Henderson if (exp == 0) { 11974343409SRichard Henderson /* Denormals without DNZ set raise an exception. */ 12074343409SRichard Henderson if (frac != 0 && !env->fp_status.flush_inputs_to_zero) { 1214a58aedfSRichard Henderson arith_excp(env, GETPC(), EXC_M_UNF, 0); 1224a58aedfSRichard Henderson } 1234a58aedfSRichard Henderson } else if (exp == 0x7ff && frac) { 1244a58aedfSRichard Henderson /* NaN. */ 1254a58aedfSRichard Henderson arith_excp(env, GETPC(), EXC_M_INV, 0); 1264a58aedfSRichard Henderson } 1274a58aedfSRichard Henderson } 1284a58aedfSRichard Henderson 1294a58aedfSRichard Henderson /* F floating (VAX) */ 1304a58aedfSRichard Henderson static uint64_t float32_to_f(float32 fa) 1314a58aedfSRichard Henderson { 1324a58aedfSRichard Henderson uint64_t r, exp, mant, sig; 1334a58aedfSRichard Henderson CPU_FloatU a; 1344a58aedfSRichard Henderson 1354a58aedfSRichard Henderson a.f = fa; 1364a58aedfSRichard Henderson sig = ((uint64_t)a.l & 0x80000000) << 32; 1374a58aedfSRichard Henderson exp = (a.l >> 23) & 0xff; 1384a58aedfSRichard Henderson mant = ((uint64_t)a.l & 0x007fffff) << 29; 1394a58aedfSRichard Henderson 1404a58aedfSRichard Henderson if (exp == 255) { 1414a58aedfSRichard Henderson /* NaN or infinity */ 1424a58aedfSRichard Henderson r = 1; /* VAX dirty zero */ 1434a58aedfSRichard Henderson } else if (exp == 0) { 1444a58aedfSRichard Henderson if (mant == 0) { 1454a58aedfSRichard Henderson /* Zero */ 1464a58aedfSRichard Henderson r = 0; 1474a58aedfSRichard Henderson } else { 1484a58aedfSRichard Henderson /* Denormalized */ 1494a58aedfSRichard Henderson r = sig | ((exp + 1) << 52) | mant; 1504a58aedfSRichard Henderson } 1514a58aedfSRichard Henderson } else { 1524a58aedfSRichard Henderson if (exp >= 253) { 1534a58aedfSRichard Henderson /* Overflow */ 1544a58aedfSRichard Henderson r = 1; /* VAX dirty zero */ 1554a58aedfSRichard Henderson } else { 1564a58aedfSRichard Henderson r = sig | ((exp + 2) << 52); 1574a58aedfSRichard Henderson } 1584a58aedfSRichard Henderson } 1594a58aedfSRichard Henderson 1604a58aedfSRichard Henderson return r; 1614a58aedfSRichard Henderson } 1624a58aedfSRichard Henderson 16320503968SBlue Swirl static float32 f_to_float32(CPUAlphaState *env, uintptr_t retaddr, uint64_t a) 1644a58aedfSRichard Henderson { 1654a58aedfSRichard Henderson uint32_t exp, mant_sig; 1664a58aedfSRichard Henderson CPU_FloatU r; 1674a58aedfSRichard Henderson 1684a58aedfSRichard Henderson exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f); 1694a58aedfSRichard Henderson mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff); 1704a58aedfSRichard Henderson 1714a58aedfSRichard Henderson if (unlikely(!exp && mant_sig)) { 1724a58aedfSRichard Henderson /* Reserved operands / Dirty zero */ 1734a58aedfSRichard Henderson dynamic_excp(env, retaddr, EXCP_OPCDEC, 0); 1744a58aedfSRichard Henderson } 1754a58aedfSRichard Henderson 1764a58aedfSRichard Henderson if (exp < 3) { 1774a58aedfSRichard Henderson /* Underflow */ 1784a58aedfSRichard Henderson r.l = 0; 1794a58aedfSRichard Henderson } else { 1804a58aedfSRichard Henderson r.l = ((exp - 2) << 23) | mant_sig; 1814a58aedfSRichard Henderson } 1824a58aedfSRichard Henderson 1834a58aedfSRichard Henderson return r.f; 1844a58aedfSRichard Henderson } 1854a58aedfSRichard Henderson 1864a58aedfSRichard Henderson uint32_t helper_f_to_memory(uint64_t a) 1874a58aedfSRichard Henderson { 1884a58aedfSRichard Henderson uint32_t r; 1894a58aedfSRichard Henderson r = (a & 0x00001fffe0000000ull) >> 13; 1904a58aedfSRichard Henderson r |= (a & 0x07ffe00000000000ull) >> 45; 1914a58aedfSRichard Henderson r |= (a & 0xc000000000000000ull) >> 48; 1924a58aedfSRichard Henderson return r; 1934a58aedfSRichard Henderson } 1944a58aedfSRichard Henderson 1954a58aedfSRichard Henderson uint64_t helper_memory_to_f(uint32_t a) 1964a58aedfSRichard Henderson { 1974a58aedfSRichard Henderson uint64_t r; 1984a58aedfSRichard Henderson r = ((uint64_t)(a & 0x0000c000)) << 48; 1994a58aedfSRichard Henderson r |= ((uint64_t)(a & 0x003fffff)) << 45; 2004a58aedfSRichard Henderson r |= ((uint64_t)(a & 0xffff0000)) << 13; 2014a58aedfSRichard Henderson if (!(a & 0x00004000)) { 2024a58aedfSRichard Henderson r |= 0x7ll << 59; 2034a58aedfSRichard Henderson } 2044a58aedfSRichard Henderson return r; 2054a58aedfSRichard Henderson } 2064a58aedfSRichard Henderson 2074a58aedfSRichard Henderson /* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should 2084a58aedfSRichard Henderson either implement VAX arithmetic properly or just signal invalid opcode. */ 2094a58aedfSRichard Henderson 2104a58aedfSRichard Henderson uint64_t helper_addf(CPUAlphaState *env, uint64_t a, uint64_t b) 2114a58aedfSRichard Henderson { 2124a58aedfSRichard Henderson float32 fa, fb, fr; 2134a58aedfSRichard Henderson 2144a58aedfSRichard Henderson fa = f_to_float32(env, GETPC(), a); 2154a58aedfSRichard Henderson fb = f_to_float32(env, GETPC(), b); 2164a58aedfSRichard Henderson fr = float32_add(fa, fb, &FP_STATUS); 2174a58aedfSRichard Henderson return float32_to_f(fr); 2184a58aedfSRichard Henderson } 2194a58aedfSRichard Henderson 2204a58aedfSRichard Henderson uint64_t helper_subf(CPUAlphaState *env, uint64_t a, uint64_t b) 2214a58aedfSRichard Henderson { 2224a58aedfSRichard Henderson float32 fa, fb, fr; 2234a58aedfSRichard Henderson 2244a58aedfSRichard Henderson fa = f_to_float32(env, GETPC(), a); 2254a58aedfSRichard Henderson fb = f_to_float32(env, GETPC(), b); 2264a58aedfSRichard Henderson fr = float32_sub(fa, fb, &FP_STATUS); 2274a58aedfSRichard Henderson return float32_to_f(fr); 2284a58aedfSRichard Henderson } 2294a58aedfSRichard Henderson 2304a58aedfSRichard Henderson uint64_t helper_mulf(CPUAlphaState *env, uint64_t a, uint64_t b) 2314a58aedfSRichard Henderson { 2324a58aedfSRichard Henderson float32 fa, fb, fr; 2334a58aedfSRichard Henderson 2344a58aedfSRichard Henderson fa = f_to_float32(env, GETPC(), a); 2354a58aedfSRichard Henderson fb = f_to_float32(env, GETPC(), b); 2364a58aedfSRichard Henderson fr = float32_mul(fa, fb, &FP_STATUS); 2374a58aedfSRichard Henderson return float32_to_f(fr); 2384a58aedfSRichard Henderson } 2394a58aedfSRichard Henderson 2404a58aedfSRichard Henderson uint64_t helper_divf(CPUAlphaState *env, uint64_t a, uint64_t b) 2414a58aedfSRichard Henderson { 2424a58aedfSRichard Henderson float32 fa, fb, fr; 2434a58aedfSRichard Henderson 2444a58aedfSRichard Henderson fa = f_to_float32(env, GETPC(), a); 2454a58aedfSRichard Henderson fb = f_to_float32(env, GETPC(), b); 2464a58aedfSRichard Henderson fr = float32_div(fa, fb, &FP_STATUS); 2474a58aedfSRichard Henderson return float32_to_f(fr); 2484a58aedfSRichard Henderson } 2494a58aedfSRichard Henderson 2504a58aedfSRichard Henderson uint64_t helper_sqrtf(CPUAlphaState *env, uint64_t t) 2514a58aedfSRichard Henderson { 2524a58aedfSRichard Henderson float32 ft, fr; 2534a58aedfSRichard Henderson 2544a58aedfSRichard Henderson ft = f_to_float32(env, GETPC(), t); 2554a58aedfSRichard Henderson fr = float32_sqrt(ft, &FP_STATUS); 2564a58aedfSRichard Henderson return float32_to_f(fr); 2574a58aedfSRichard Henderson } 2584a58aedfSRichard Henderson 2594a58aedfSRichard Henderson 2604a58aedfSRichard Henderson /* G floating (VAX) */ 2614a58aedfSRichard Henderson static uint64_t float64_to_g(float64 fa) 2624a58aedfSRichard Henderson { 2634a58aedfSRichard Henderson uint64_t r, exp, mant, sig; 2644a58aedfSRichard Henderson CPU_DoubleU a; 2654a58aedfSRichard Henderson 2664a58aedfSRichard Henderson a.d = fa; 2674a58aedfSRichard Henderson sig = a.ll & 0x8000000000000000ull; 2684a58aedfSRichard Henderson exp = (a.ll >> 52) & 0x7ff; 2694a58aedfSRichard Henderson mant = a.ll & 0x000fffffffffffffull; 2704a58aedfSRichard Henderson 2714a58aedfSRichard Henderson if (exp == 2047) { 2724a58aedfSRichard Henderson /* NaN or infinity */ 2734a58aedfSRichard Henderson r = 1; /* VAX dirty zero */ 2744a58aedfSRichard Henderson } else if (exp == 0) { 2754a58aedfSRichard Henderson if (mant == 0) { 2764a58aedfSRichard Henderson /* Zero */ 2774a58aedfSRichard Henderson r = 0; 2784a58aedfSRichard Henderson } else { 2794a58aedfSRichard Henderson /* Denormalized */ 2804a58aedfSRichard Henderson r = sig | ((exp + 1) << 52) | mant; 2814a58aedfSRichard Henderson } 2824a58aedfSRichard Henderson } else { 2834a58aedfSRichard Henderson if (exp >= 2045) { 2844a58aedfSRichard Henderson /* Overflow */ 2854a58aedfSRichard Henderson r = 1; /* VAX dirty zero */ 2864a58aedfSRichard Henderson } else { 2874a58aedfSRichard Henderson r = sig | ((exp + 2) << 52); 2884a58aedfSRichard Henderson } 2894a58aedfSRichard Henderson } 2904a58aedfSRichard Henderson 2914a58aedfSRichard Henderson return r; 2924a58aedfSRichard Henderson } 2934a58aedfSRichard Henderson 29420503968SBlue Swirl static float64 g_to_float64(CPUAlphaState *env, uintptr_t retaddr, uint64_t a) 2954a58aedfSRichard Henderson { 2964a58aedfSRichard Henderson uint64_t exp, mant_sig; 2974a58aedfSRichard Henderson CPU_DoubleU r; 2984a58aedfSRichard Henderson 2994a58aedfSRichard Henderson exp = (a >> 52) & 0x7ff; 3004a58aedfSRichard Henderson mant_sig = a & 0x800fffffffffffffull; 3014a58aedfSRichard Henderson 3024a58aedfSRichard Henderson if (!exp && mant_sig) { 3034a58aedfSRichard Henderson /* Reserved operands / Dirty zero */ 3044a58aedfSRichard Henderson dynamic_excp(env, retaddr, EXCP_OPCDEC, 0); 3054a58aedfSRichard Henderson } 3064a58aedfSRichard Henderson 3074a58aedfSRichard Henderson if (exp < 3) { 3084a58aedfSRichard Henderson /* Underflow */ 3094a58aedfSRichard Henderson r.ll = 0; 3104a58aedfSRichard Henderson } else { 3114a58aedfSRichard Henderson r.ll = ((exp - 2) << 52) | mant_sig; 3124a58aedfSRichard Henderson } 3134a58aedfSRichard Henderson 3144a58aedfSRichard Henderson return r.d; 3154a58aedfSRichard Henderson } 3164a58aedfSRichard Henderson 3174a58aedfSRichard Henderson uint64_t helper_g_to_memory(uint64_t a) 3184a58aedfSRichard Henderson { 3194a58aedfSRichard Henderson uint64_t r; 3204a58aedfSRichard Henderson r = (a & 0x000000000000ffffull) << 48; 3214a58aedfSRichard Henderson r |= (a & 0x00000000ffff0000ull) << 16; 3224a58aedfSRichard Henderson r |= (a & 0x0000ffff00000000ull) >> 16; 3234a58aedfSRichard Henderson r |= (a & 0xffff000000000000ull) >> 48; 3244a58aedfSRichard Henderson return r; 3254a58aedfSRichard Henderson } 3264a58aedfSRichard Henderson 3274a58aedfSRichard Henderson uint64_t helper_memory_to_g(uint64_t a) 3284a58aedfSRichard Henderson { 3294a58aedfSRichard Henderson uint64_t r; 3304a58aedfSRichard Henderson r = (a & 0x000000000000ffffull) << 48; 3314a58aedfSRichard Henderson r |= (a & 0x00000000ffff0000ull) << 16; 3324a58aedfSRichard Henderson r |= (a & 0x0000ffff00000000ull) >> 16; 3334a58aedfSRichard Henderson r |= (a & 0xffff000000000000ull) >> 48; 3344a58aedfSRichard Henderson return r; 3354a58aedfSRichard Henderson } 3364a58aedfSRichard Henderson 3374a58aedfSRichard Henderson uint64_t helper_addg(CPUAlphaState *env, uint64_t a, uint64_t b) 3384a58aedfSRichard Henderson { 3394a58aedfSRichard Henderson float64 fa, fb, fr; 3404a58aedfSRichard Henderson 3414a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 3424a58aedfSRichard Henderson fb = g_to_float64(env, GETPC(), b); 3434a58aedfSRichard Henderson fr = float64_add(fa, fb, &FP_STATUS); 3444a58aedfSRichard Henderson return float64_to_g(fr); 3454a58aedfSRichard Henderson } 3464a58aedfSRichard Henderson 3474a58aedfSRichard Henderson uint64_t helper_subg(CPUAlphaState *env, uint64_t a, uint64_t b) 3484a58aedfSRichard Henderson { 3494a58aedfSRichard Henderson float64 fa, fb, fr; 3504a58aedfSRichard Henderson 3514a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 3524a58aedfSRichard Henderson fb = g_to_float64(env, GETPC(), b); 3534a58aedfSRichard Henderson fr = float64_sub(fa, fb, &FP_STATUS); 3544a58aedfSRichard Henderson return float64_to_g(fr); 3554a58aedfSRichard Henderson } 3564a58aedfSRichard Henderson 3574a58aedfSRichard Henderson uint64_t helper_mulg(CPUAlphaState *env, uint64_t a, uint64_t b) 3584a58aedfSRichard Henderson { 3594a58aedfSRichard Henderson float64 fa, fb, fr; 3604a58aedfSRichard Henderson 3614a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 3624a58aedfSRichard Henderson fb = g_to_float64(env, GETPC(), b); 3634a58aedfSRichard Henderson fr = float64_mul(fa, fb, &FP_STATUS); 3644a58aedfSRichard Henderson return float64_to_g(fr); 3654a58aedfSRichard Henderson } 3664a58aedfSRichard Henderson 3674a58aedfSRichard Henderson uint64_t helper_divg(CPUAlphaState *env, uint64_t a, uint64_t b) 3684a58aedfSRichard Henderson { 3694a58aedfSRichard Henderson float64 fa, fb, fr; 3704a58aedfSRichard Henderson 3714a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 3724a58aedfSRichard Henderson fb = g_to_float64(env, GETPC(), b); 3734a58aedfSRichard Henderson fr = float64_div(fa, fb, &FP_STATUS); 3744a58aedfSRichard Henderson return float64_to_g(fr); 3754a58aedfSRichard Henderson } 3764a58aedfSRichard Henderson 3774a58aedfSRichard Henderson uint64_t helper_sqrtg(CPUAlphaState *env, uint64_t a) 3784a58aedfSRichard Henderson { 3794a58aedfSRichard Henderson float64 fa, fr; 3804a58aedfSRichard Henderson 3814a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 3824a58aedfSRichard Henderson fr = float64_sqrt(fa, &FP_STATUS); 3834a58aedfSRichard Henderson return float64_to_g(fr); 3844a58aedfSRichard Henderson } 3854a58aedfSRichard Henderson 3864a58aedfSRichard Henderson 3874a58aedfSRichard Henderson /* S floating (single) */ 3884a58aedfSRichard Henderson 3894a58aedfSRichard Henderson /* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */ 3904a58aedfSRichard Henderson static inline uint64_t float32_to_s_int(uint32_t fi) 3914a58aedfSRichard Henderson { 3924a58aedfSRichard Henderson uint32_t frac = fi & 0x7fffff; 3934a58aedfSRichard Henderson uint32_t sign = fi >> 31; 3944a58aedfSRichard Henderson uint32_t exp_msb = (fi >> 30) & 1; 3954a58aedfSRichard Henderson uint32_t exp_low = (fi >> 23) & 0x7f; 3964a58aedfSRichard Henderson uint32_t exp; 3974a58aedfSRichard Henderson 3984a58aedfSRichard Henderson exp = (exp_msb << 10) | exp_low; 3994a58aedfSRichard Henderson if (exp_msb) { 4004a58aedfSRichard Henderson if (exp_low == 0x7f) { 4014a58aedfSRichard Henderson exp = 0x7ff; 4024a58aedfSRichard Henderson } 4034a58aedfSRichard Henderson } else { 4044a58aedfSRichard Henderson if (exp_low != 0x00) { 4054a58aedfSRichard Henderson exp |= 0x380; 4064a58aedfSRichard Henderson } 4074a58aedfSRichard Henderson } 4084a58aedfSRichard Henderson 4094a58aedfSRichard Henderson return (((uint64_t)sign << 63) 4104a58aedfSRichard Henderson | ((uint64_t)exp << 52) 4114a58aedfSRichard Henderson | ((uint64_t)frac << 29)); 4124a58aedfSRichard Henderson } 4134a58aedfSRichard Henderson 4144a58aedfSRichard Henderson static inline uint64_t float32_to_s(float32 fa) 4154a58aedfSRichard Henderson { 4164a58aedfSRichard Henderson CPU_FloatU a; 4174a58aedfSRichard Henderson a.f = fa; 4184a58aedfSRichard Henderson return float32_to_s_int(a.l); 4194a58aedfSRichard Henderson } 4204a58aedfSRichard Henderson 4214a58aedfSRichard Henderson static inline uint32_t s_to_float32_int(uint64_t a) 4224a58aedfSRichard Henderson { 4234a58aedfSRichard Henderson return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff); 4244a58aedfSRichard Henderson } 4254a58aedfSRichard Henderson 4264a58aedfSRichard Henderson static inline float32 s_to_float32(uint64_t a) 4274a58aedfSRichard Henderson { 4284a58aedfSRichard Henderson CPU_FloatU r; 4294a58aedfSRichard Henderson r.l = s_to_float32_int(a); 4304a58aedfSRichard Henderson return r.f; 4314a58aedfSRichard Henderson } 4324a58aedfSRichard Henderson 4334a58aedfSRichard Henderson uint32_t helper_s_to_memory(uint64_t a) 4344a58aedfSRichard Henderson { 4354a58aedfSRichard Henderson return s_to_float32_int(a); 4364a58aedfSRichard Henderson } 4374a58aedfSRichard Henderson 4384a58aedfSRichard Henderson uint64_t helper_memory_to_s(uint32_t a) 4394a58aedfSRichard Henderson { 4404a58aedfSRichard Henderson return float32_to_s_int(a); 4414a58aedfSRichard Henderson } 4424a58aedfSRichard Henderson 4434a58aedfSRichard Henderson uint64_t helper_adds(CPUAlphaState *env, uint64_t a, uint64_t b) 4444a58aedfSRichard Henderson { 4454a58aedfSRichard Henderson float32 fa, fb, fr; 4464a58aedfSRichard Henderson 4474a58aedfSRichard Henderson fa = s_to_float32(a); 4484a58aedfSRichard Henderson fb = s_to_float32(b); 4494a58aedfSRichard Henderson fr = float32_add(fa, fb, &FP_STATUS); 4504a58aedfSRichard Henderson return float32_to_s(fr); 4514a58aedfSRichard Henderson } 4524a58aedfSRichard Henderson 4534a58aedfSRichard Henderson uint64_t helper_subs(CPUAlphaState *env, uint64_t a, uint64_t b) 4544a58aedfSRichard Henderson { 4554a58aedfSRichard Henderson float32 fa, fb, fr; 4564a58aedfSRichard Henderson 4574a58aedfSRichard Henderson fa = s_to_float32(a); 4584a58aedfSRichard Henderson fb = s_to_float32(b); 4594a58aedfSRichard Henderson fr = float32_sub(fa, fb, &FP_STATUS); 4604a58aedfSRichard Henderson return float32_to_s(fr); 4614a58aedfSRichard Henderson } 4624a58aedfSRichard Henderson 4634a58aedfSRichard Henderson uint64_t helper_muls(CPUAlphaState *env, uint64_t a, uint64_t b) 4644a58aedfSRichard Henderson { 4654a58aedfSRichard Henderson float32 fa, fb, fr; 4664a58aedfSRichard Henderson 4674a58aedfSRichard Henderson fa = s_to_float32(a); 4684a58aedfSRichard Henderson fb = s_to_float32(b); 4694a58aedfSRichard Henderson fr = float32_mul(fa, fb, &FP_STATUS); 4704a58aedfSRichard Henderson return float32_to_s(fr); 4714a58aedfSRichard Henderson } 4724a58aedfSRichard Henderson 4734a58aedfSRichard Henderson uint64_t helper_divs(CPUAlphaState *env, uint64_t a, uint64_t b) 4744a58aedfSRichard Henderson { 4754a58aedfSRichard Henderson float32 fa, fb, fr; 4764a58aedfSRichard Henderson 4774a58aedfSRichard Henderson fa = s_to_float32(a); 4784a58aedfSRichard Henderson fb = s_to_float32(b); 4794a58aedfSRichard Henderson fr = float32_div(fa, fb, &FP_STATUS); 4804a58aedfSRichard Henderson return float32_to_s(fr); 4814a58aedfSRichard Henderson } 4824a58aedfSRichard Henderson 4834a58aedfSRichard Henderson uint64_t helper_sqrts(CPUAlphaState *env, uint64_t a) 4844a58aedfSRichard Henderson { 4854a58aedfSRichard Henderson float32 fa, fr; 4864a58aedfSRichard Henderson 4874a58aedfSRichard Henderson fa = s_to_float32(a); 4884a58aedfSRichard Henderson fr = float32_sqrt(fa, &FP_STATUS); 4894a58aedfSRichard Henderson return float32_to_s(fr); 4904a58aedfSRichard Henderson } 4914a58aedfSRichard Henderson 4924a58aedfSRichard Henderson 4934a58aedfSRichard Henderson /* T floating (double) */ 4944a58aedfSRichard Henderson static inline float64 t_to_float64(uint64_t a) 4954a58aedfSRichard Henderson { 4964a58aedfSRichard Henderson /* Memory format is the same as float64 */ 4974a58aedfSRichard Henderson CPU_DoubleU r; 4984a58aedfSRichard Henderson r.ll = a; 4994a58aedfSRichard Henderson return r.d; 5004a58aedfSRichard Henderson } 5014a58aedfSRichard Henderson 5024a58aedfSRichard Henderson static inline uint64_t float64_to_t(float64 fa) 5034a58aedfSRichard Henderson { 5044a58aedfSRichard Henderson /* Memory format is the same as float64 */ 5054a58aedfSRichard Henderson CPU_DoubleU r; 5064a58aedfSRichard Henderson r.d = fa; 5074a58aedfSRichard Henderson return r.ll; 5084a58aedfSRichard Henderson } 5094a58aedfSRichard Henderson 5104a58aedfSRichard Henderson uint64_t helper_addt(CPUAlphaState *env, uint64_t a, uint64_t b) 5114a58aedfSRichard Henderson { 5124a58aedfSRichard Henderson float64 fa, fb, fr; 5134a58aedfSRichard Henderson 5144a58aedfSRichard Henderson fa = t_to_float64(a); 5154a58aedfSRichard Henderson fb = t_to_float64(b); 5164a58aedfSRichard Henderson fr = float64_add(fa, fb, &FP_STATUS); 5174a58aedfSRichard Henderson return float64_to_t(fr); 5184a58aedfSRichard Henderson } 5194a58aedfSRichard Henderson 5204a58aedfSRichard Henderson uint64_t helper_subt(CPUAlphaState *env, uint64_t a, uint64_t b) 5214a58aedfSRichard Henderson { 5224a58aedfSRichard Henderson float64 fa, fb, fr; 5234a58aedfSRichard Henderson 5244a58aedfSRichard Henderson fa = t_to_float64(a); 5254a58aedfSRichard Henderson fb = t_to_float64(b); 5264a58aedfSRichard Henderson fr = float64_sub(fa, fb, &FP_STATUS); 5274a58aedfSRichard Henderson return float64_to_t(fr); 5284a58aedfSRichard Henderson } 5294a58aedfSRichard Henderson 5304a58aedfSRichard Henderson uint64_t helper_mult(CPUAlphaState *env, uint64_t a, uint64_t b) 5314a58aedfSRichard Henderson { 5324a58aedfSRichard Henderson float64 fa, fb, fr; 5334a58aedfSRichard Henderson 5344a58aedfSRichard Henderson fa = t_to_float64(a); 5354a58aedfSRichard Henderson fb = t_to_float64(b); 5364a58aedfSRichard Henderson fr = float64_mul(fa, fb, &FP_STATUS); 5374a58aedfSRichard Henderson return float64_to_t(fr); 5384a58aedfSRichard Henderson } 5394a58aedfSRichard Henderson 5404a58aedfSRichard Henderson uint64_t helper_divt(CPUAlphaState *env, uint64_t a, uint64_t b) 5414a58aedfSRichard Henderson { 5424a58aedfSRichard Henderson float64 fa, fb, fr; 5434a58aedfSRichard Henderson 5444a58aedfSRichard Henderson fa = t_to_float64(a); 5454a58aedfSRichard Henderson fb = t_to_float64(b); 5464a58aedfSRichard Henderson fr = float64_div(fa, fb, &FP_STATUS); 5474a58aedfSRichard Henderson return float64_to_t(fr); 5484a58aedfSRichard Henderson } 5494a58aedfSRichard Henderson 5504a58aedfSRichard Henderson uint64_t helper_sqrtt(CPUAlphaState *env, uint64_t a) 5514a58aedfSRichard Henderson { 5524a58aedfSRichard Henderson float64 fa, fr; 5534a58aedfSRichard Henderson 5544a58aedfSRichard Henderson fa = t_to_float64(a); 5554a58aedfSRichard Henderson fr = float64_sqrt(fa, &FP_STATUS); 5564a58aedfSRichard Henderson return float64_to_t(fr); 5574a58aedfSRichard Henderson } 5584a58aedfSRichard Henderson 5594a58aedfSRichard Henderson /* Comparisons */ 5604a58aedfSRichard Henderson uint64_t helper_cmptun(CPUAlphaState *env, uint64_t a, uint64_t b) 5614a58aedfSRichard Henderson { 5624a58aedfSRichard Henderson float64 fa, fb; 5634a58aedfSRichard Henderson 5644a58aedfSRichard Henderson fa = t_to_float64(a); 5654a58aedfSRichard Henderson fb = t_to_float64(b); 5664a58aedfSRichard Henderson 5674a58aedfSRichard Henderson if (float64_unordered_quiet(fa, fb, &FP_STATUS)) { 5684a58aedfSRichard Henderson return 0x4000000000000000ULL; 5694a58aedfSRichard Henderson } else { 5704a58aedfSRichard Henderson return 0; 5714a58aedfSRichard Henderson } 5724a58aedfSRichard Henderson } 5734a58aedfSRichard Henderson 5744a58aedfSRichard Henderson uint64_t helper_cmpteq(CPUAlphaState *env, uint64_t a, uint64_t b) 5754a58aedfSRichard Henderson { 5764a58aedfSRichard Henderson float64 fa, fb; 5774a58aedfSRichard Henderson 5784a58aedfSRichard Henderson fa = t_to_float64(a); 5794a58aedfSRichard Henderson fb = t_to_float64(b); 5804a58aedfSRichard Henderson 5814a58aedfSRichard Henderson if (float64_eq_quiet(fa, fb, &FP_STATUS)) { 5824a58aedfSRichard Henderson return 0x4000000000000000ULL; 5834a58aedfSRichard Henderson } else { 5844a58aedfSRichard Henderson return 0; 5854a58aedfSRichard Henderson } 5864a58aedfSRichard Henderson } 5874a58aedfSRichard Henderson 5884a58aedfSRichard Henderson uint64_t helper_cmptle(CPUAlphaState *env, uint64_t a, uint64_t b) 5894a58aedfSRichard Henderson { 5904a58aedfSRichard Henderson float64 fa, fb; 5914a58aedfSRichard Henderson 5924a58aedfSRichard Henderson fa = t_to_float64(a); 5934a58aedfSRichard Henderson fb = t_to_float64(b); 5944a58aedfSRichard Henderson 5954a58aedfSRichard Henderson if (float64_le(fa, fb, &FP_STATUS)) { 5964a58aedfSRichard Henderson return 0x4000000000000000ULL; 5974a58aedfSRichard Henderson } else { 5984a58aedfSRichard Henderson return 0; 5994a58aedfSRichard Henderson } 6004a58aedfSRichard Henderson } 6014a58aedfSRichard Henderson 6024a58aedfSRichard Henderson uint64_t helper_cmptlt(CPUAlphaState *env, uint64_t a, uint64_t b) 6034a58aedfSRichard Henderson { 6044a58aedfSRichard Henderson float64 fa, fb; 6054a58aedfSRichard Henderson 6064a58aedfSRichard Henderson fa = t_to_float64(a); 6074a58aedfSRichard Henderson fb = t_to_float64(b); 6084a58aedfSRichard Henderson 6094a58aedfSRichard Henderson if (float64_lt(fa, fb, &FP_STATUS)) { 6104a58aedfSRichard Henderson return 0x4000000000000000ULL; 6114a58aedfSRichard Henderson } else { 6124a58aedfSRichard Henderson return 0; 6134a58aedfSRichard Henderson } 6144a58aedfSRichard Henderson } 6154a58aedfSRichard Henderson 6164a58aedfSRichard Henderson uint64_t helper_cmpgeq(CPUAlphaState *env, uint64_t a, uint64_t b) 6174a58aedfSRichard Henderson { 6184a58aedfSRichard Henderson float64 fa, fb; 6194a58aedfSRichard Henderson 6204a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 6214a58aedfSRichard Henderson fb = g_to_float64(env, GETPC(), b); 6224a58aedfSRichard Henderson 6234a58aedfSRichard Henderson if (float64_eq_quiet(fa, fb, &FP_STATUS)) { 6244a58aedfSRichard Henderson return 0x4000000000000000ULL; 6254a58aedfSRichard Henderson } else { 6264a58aedfSRichard Henderson return 0; 6274a58aedfSRichard Henderson } 6284a58aedfSRichard Henderson } 6294a58aedfSRichard Henderson 6304a58aedfSRichard Henderson uint64_t helper_cmpgle(CPUAlphaState *env, uint64_t a, uint64_t b) 6314a58aedfSRichard Henderson { 6324a58aedfSRichard Henderson float64 fa, fb; 6334a58aedfSRichard Henderson 6344a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 6354a58aedfSRichard Henderson fb = g_to_float64(env, GETPC(), b); 6364a58aedfSRichard Henderson 6374a58aedfSRichard Henderson if (float64_le(fa, fb, &FP_STATUS)) { 6384a58aedfSRichard Henderson return 0x4000000000000000ULL; 6394a58aedfSRichard Henderson } else { 6404a58aedfSRichard Henderson return 0; 6414a58aedfSRichard Henderson } 6424a58aedfSRichard Henderson } 6434a58aedfSRichard Henderson 6444a58aedfSRichard Henderson uint64_t helper_cmpglt(CPUAlphaState *env, uint64_t a, uint64_t b) 6454a58aedfSRichard Henderson { 6464a58aedfSRichard Henderson float64 fa, fb; 6474a58aedfSRichard Henderson 6484a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 6494a58aedfSRichard Henderson fb = g_to_float64(env, GETPC(), b); 6504a58aedfSRichard Henderson 6514a58aedfSRichard Henderson if (float64_lt(fa, fb, &FP_STATUS)) { 6524a58aedfSRichard Henderson return 0x4000000000000000ULL; 6534a58aedfSRichard Henderson } else { 6544a58aedfSRichard Henderson return 0; 6554a58aedfSRichard Henderson } 6564a58aedfSRichard Henderson } 6574a58aedfSRichard Henderson 6584a58aedfSRichard Henderson /* Floating point format conversion */ 6594a58aedfSRichard Henderson uint64_t helper_cvtts(CPUAlphaState *env, uint64_t a) 6604a58aedfSRichard Henderson { 6614a58aedfSRichard Henderson float64 fa; 6624a58aedfSRichard Henderson float32 fr; 6634a58aedfSRichard Henderson 6644a58aedfSRichard Henderson fa = t_to_float64(a); 6654a58aedfSRichard Henderson fr = float64_to_float32(fa, &FP_STATUS); 6664a58aedfSRichard Henderson return float32_to_s(fr); 6674a58aedfSRichard Henderson } 6684a58aedfSRichard Henderson 6694a58aedfSRichard Henderson uint64_t helper_cvtst(CPUAlphaState *env, uint64_t a) 6704a58aedfSRichard Henderson { 6714a58aedfSRichard Henderson float32 fa; 6724a58aedfSRichard Henderson float64 fr; 6734a58aedfSRichard Henderson 6744a58aedfSRichard Henderson fa = s_to_float32(a); 6754a58aedfSRichard Henderson fr = float32_to_float64(fa, &FP_STATUS); 6764a58aedfSRichard Henderson return float64_to_t(fr); 6774a58aedfSRichard Henderson } 6784a58aedfSRichard Henderson 6794a58aedfSRichard Henderson uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a) 6804a58aedfSRichard Henderson { 6814a58aedfSRichard Henderson float32 fr = int64_to_float32(a, &FP_STATUS); 6824a58aedfSRichard Henderson return float32_to_s(fr); 6834a58aedfSRichard Henderson } 6844a58aedfSRichard Henderson 6854a58aedfSRichard Henderson /* Implement float64 to uint64 conversion without saturation -- we must 6864a58aedfSRichard Henderson supply the truncated result. This behaviour is used by the compiler 6874a58aedfSRichard Henderson to get unsigned conversion for free with the same instruction. 6884a58aedfSRichard Henderson 6894a58aedfSRichard Henderson The VI flag is set when overflow or inexact exceptions should be raised. */ 6904a58aedfSRichard Henderson 6914a58aedfSRichard Henderson static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a, 6924a58aedfSRichard Henderson int roundmode, int VI) 6934a58aedfSRichard Henderson { 6944a58aedfSRichard Henderson uint64_t frac, ret = 0; 6954a58aedfSRichard Henderson uint32_t exp, sign, exc = 0; 6964a58aedfSRichard Henderson int shift; 6974a58aedfSRichard Henderson 6984a58aedfSRichard Henderson sign = (a >> 63); 6994a58aedfSRichard Henderson exp = (uint32_t)(a >> 52) & 0x7ff; 7004a58aedfSRichard Henderson frac = a & 0xfffffffffffffull; 7014a58aedfSRichard Henderson 7024a58aedfSRichard Henderson if (exp == 0) { 7034a58aedfSRichard Henderson if (unlikely(frac != 0)) { 7044a58aedfSRichard Henderson goto do_underflow; 7054a58aedfSRichard Henderson } 7064a58aedfSRichard Henderson } else if (exp == 0x7ff) { 7074a58aedfSRichard Henderson exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0); 7084a58aedfSRichard Henderson } else { 7094a58aedfSRichard Henderson /* Restore implicit bit. */ 7104a58aedfSRichard Henderson frac |= 0x10000000000000ull; 7114a58aedfSRichard Henderson 7124a58aedfSRichard Henderson shift = exp - 1023 - 52; 7134a58aedfSRichard Henderson if (shift >= 0) { 7144a58aedfSRichard Henderson /* In this case the number is so large that we must shift 7154a58aedfSRichard Henderson the fraction left. There is no rounding to do. */ 7164a58aedfSRichard Henderson if (shift < 63) { 7174a58aedfSRichard Henderson ret = frac << shift; 7184a58aedfSRichard Henderson if (VI && (ret >> shift) != frac) { 7194a58aedfSRichard Henderson exc = float_flag_overflow; 7204a58aedfSRichard Henderson } 7214a58aedfSRichard Henderson } 7224a58aedfSRichard Henderson } else { 7234a58aedfSRichard Henderson uint64_t round; 7244a58aedfSRichard Henderson 7254a58aedfSRichard Henderson /* In this case the number is smaller than the fraction as 7264a58aedfSRichard Henderson represented by the 52 bit number. Here we must think 7274a58aedfSRichard Henderson about rounding the result. Handle this by shifting the 7284a58aedfSRichard Henderson fractional part of the number into the high bits of ROUND. 7294a58aedfSRichard Henderson This will let us efficiently handle round-to-nearest. */ 7304a58aedfSRichard Henderson shift = -shift; 7314a58aedfSRichard Henderson if (shift < 63) { 7324a58aedfSRichard Henderson ret = frac >> shift; 7334a58aedfSRichard Henderson round = frac << (64 - shift); 7344a58aedfSRichard Henderson } else { 7354a58aedfSRichard Henderson /* The exponent is so small we shift out everything. 7364a58aedfSRichard Henderson Leave a sticky bit for proper rounding below. */ 7374a58aedfSRichard Henderson do_underflow: 7384a58aedfSRichard Henderson round = 1; 7394a58aedfSRichard Henderson } 7404a58aedfSRichard Henderson 7414a58aedfSRichard Henderson if (round) { 7424a58aedfSRichard Henderson exc = (VI ? float_flag_inexact : 0); 7434a58aedfSRichard Henderson switch (roundmode) { 7444a58aedfSRichard Henderson case float_round_nearest_even: 7454a58aedfSRichard Henderson if (round == (1ull << 63)) { 7464a58aedfSRichard Henderson /* Fraction is exactly 0.5; round to even. */ 7474a58aedfSRichard Henderson ret += (ret & 1); 7484a58aedfSRichard Henderson } else if (round > (1ull << 63)) { 7494a58aedfSRichard Henderson ret += 1; 7504a58aedfSRichard Henderson } 7514a58aedfSRichard Henderson break; 7524a58aedfSRichard Henderson case float_round_to_zero: 7534a58aedfSRichard Henderson break; 7544a58aedfSRichard Henderson case float_round_up: 7554a58aedfSRichard Henderson ret += 1 - sign; 7564a58aedfSRichard Henderson break; 7574a58aedfSRichard Henderson case float_round_down: 7584a58aedfSRichard Henderson ret += sign; 7594a58aedfSRichard Henderson break; 7604a58aedfSRichard Henderson } 7614a58aedfSRichard Henderson } 7624a58aedfSRichard Henderson } 7634a58aedfSRichard Henderson if (sign) { 7644a58aedfSRichard Henderson ret = -ret; 7654a58aedfSRichard Henderson } 7664a58aedfSRichard Henderson } 7674a58aedfSRichard Henderson if (unlikely(exc)) { 7684a58aedfSRichard Henderson float_raise(exc, &FP_STATUS); 7694a58aedfSRichard Henderson } 7704a58aedfSRichard Henderson 7714a58aedfSRichard Henderson return ret; 7724a58aedfSRichard Henderson } 7734a58aedfSRichard Henderson 7744a58aedfSRichard Henderson uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a) 7754a58aedfSRichard Henderson { 7764a58aedfSRichard Henderson return inline_cvttq(env, a, FP_STATUS.float_rounding_mode, 1); 7774a58aedfSRichard Henderson } 7784a58aedfSRichard Henderson 7794a58aedfSRichard Henderson uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a) 7804a58aedfSRichard Henderson { 7814a58aedfSRichard Henderson return inline_cvttq(env, a, float_round_to_zero, 0); 7824a58aedfSRichard Henderson } 7834a58aedfSRichard Henderson 7844a58aedfSRichard Henderson uint64_t helper_cvttq_svic(CPUAlphaState *env, uint64_t a) 7854a58aedfSRichard Henderson { 7864a58aedfSRichard Henderson return inline_cvttq(env, a, float_round_to_zero, 1); 7874a58aedfSRichard Henderson } 7884a58aedfSRichard Henderson 7894a58aedfSRichard Henderson uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a) 7904a58aedfSRichard Henderson { 7914a58aedfSRichard Henderson float64 fr = int64_to_float64(a, &FP_STATUS); 7924a58aedfSRichard Henderson return float64_to_t(fr); 7934a58aedfSRichard Henderson } 7944a58aedfSRichard Henderson 7954a58aedfSRichard Henderson uint64_t helper_cvtqf(CPUAlphaState *env, uint64_t a) 7964a58aedfSRichard Henderson { 7974a58aedfSRichard Henderson float32 fr = int64_to_float32(a, &FP_STATUS); 7984a58aedfSRichard Henderson return float32_to_f(fr); 7994a58aedfSRichard Henderson } 8004a58aedfSRichard Henderson 8014a58aedfSRichard Henderson uint64_t helper_cvtgf(CPUAlphaState *env, uint64_t a) 8024a58aedfSRichard Henderson { 8034a58aedfSRichard Henderson float64 fa; 8044a58aedfSRichard Henderson float32 fr; 8054a58aedfSRichard Henderson 8064a58aedfSRichard Henderson fa = g_to_float64(env, GETPC(), a); 8074a58aedfSRichard Henderson fr = float64_to_float32(fa, &FP_STATUS); 8084a58aedfSRichard Henderson return float32_to_f(fr); 8094a58aedfSRichard Henderson } 8104a58aedfSRichard Henderson 8114a58aedfSRichard Henderson uint64_t helper_cvtgq(CPUAlphaState *env, uint64_t a) 8124a58aedfSRichard Henderson { 8134a58aedfSRichard Henderson float64 fa = g_to_float64(env, GETPC(), a); 8144a58aedfSRichard Henderson return float64_to_int64_round_to_zero(fa, &FP_STATUS); 8154a58aedfSRichard Henderson } 8164a58aedfSRichard Henderson 8174a58aedfSRichard Henderson uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a) 8184a58aedfSRichard Henderson { 8194a58aedfSRichard Henderson float64 fr; 8204a58aedfSRichard Henderson fr = int64_to_float64(a, &FP_STATUS); 8214a58aedfSRichard Henderson return float64_to_g(fr); 8224a58aedfSRichard Henderson } 823