xref: /qemu/target/alpha/fpu_helper.c (revision 7cef6d686309e2792186504ae17cf4f3eb57ef68)
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
9d6ea4236SChetan Pant  * version 2.1 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 
20e2e5e114SPeter Maydell #include "qemu/osdep.h"
214a58aedfSRichard Henderson #include "cpu.h"
222ef6175aSRichard Henderson #include "exec/helper-proto.h"
236b4c305cSPaolo Bonzini #include "fpu/softfloat.h"
244a58aedfSRichard Henderson 
254a58aedfSRichard Henderson #define FP_STATUS (env->fp_status)
264a58aedfSRichard Henderson 
274a58aedfSRichard Henderson 
helper_setroundmode(CPUAlphaState * env,uint32_t val)284a58aedfSRichard Henderson void helper_setroundmode(CPUAlphaState *env, uint32_t val)
294a58aedfSRichard Henderson {
304a58aedfSRichard Henderson     set_float_rounding_mode(val, &FP_STATUS);
314a58aedfSRichard Henderson }
324a58aedfSRichard Henderson 
helper_setflushzero(CPUAlphaState * env,uint32_t val)334a58aedfSRichard Henderson void helper_setflushzero(CPUAlphaState *env, uint32_t val)
344a58aedfSRichard Henderson {
354a58aedfSRichard Henderson     set_flush_to_zero(val, &FP_STATUS);
364a58aedfSRichard Henderson }
374a58aedfSRichard Henderson 
38f3d3aad4SRichard Henderson #define CONVERT_BIT(X, SRC, DST) \
39f3d3aad4SRichard Henderson     (SRC > DST ? (X) / (SRC / DST) & (DST) : ((X) & SRC) * (DST / SRC))
40f3d3aad4SRichard Henderson 
soft_to_fpcr_exc(CPUAlphaState * env)41f3d3aad4SRichard Henderson static uint32_t soft_to_fpcr_exc(CPUAlphaState *env)
424a58aedfSRichard Henderson {
43f3d3aad4SRichard Henderson     uint8_t exc = get_float_exception_flags(&FP_STATUS);
44f3d3aad4SRichard Henderson     uint32_t ret = 0;
45f3d3aad4SRichard Henderson 
46f3d3aad4SRichard Henderson     if (unlikely(exc)) {
474a58aedfSRichard Henderson         set_float_exception_flags(0, &FP_STATUS);
48f3d3aad4SRichard Henderson         ret |= CONVERT_BIT(exc, float_flag_invalid, FPCR_INV);
49f3d3aad4SRichard Henderson         ret |= CONVERT_BIT(exc, float_flag_divbyzero, FPCR_DZE);
50f3d3aad4SRichard Henderson         ret |= CONVERT_BIT(exc, float_flag_overflow, FPCR_OVF);
51f3d3aad4SRichard Henderson         ret |= CONVERT_BIT(exc, float_flag_underflow, FPCR_UNF);
52f3d3aad4SRichard Henderson         ret |= CONVERT_BIT(exc, float_flag_inexact, FPCR_INE);
534a58aedfSRichard Henderson     }
544a58aedfSRichard Henderson 
55f3d3aad4SRichard Henderson     return ret;
564a58aedfSRichard Henderson }
574a58aedfSRichard Henderson 
fp_exc_raise1(CPUAlphaState * env,uintptr_t retaddr,uint32_t exc,uint32_t regno,uint32_t hw_exc)58f3d3aad4SRichard Henderson static void fp_exc_raise1(CPUAlphaState *env, uintptr_t retaddr,
59f6b6b7b8SRichard Henderson                           uint32_t exc, uint32_t regno, uint32_t hw_exc)
604a58aedfSRichard Henderson {
61f3d3aad4SRichard Henderson     hw_exc |= CONVERT_BIT(exc, FPCR_INV, EXC_M_INV);
62f3d3aad4SRichard Henderson     hw_exc |= CONVERT_BIT(exc, FPCR_DZE, EXC_M_DZE);
63f3d3aad4SRichard Henderson     hw_exc |= CONVERT_BIT(exc, FPCR_OVF, EXC_M_FOV);
64f3d3aad4SRichard Henderson     hw_exc |= CONVERT_BIT(exc, FPCR_UNF, EXC_M_UNF);
65f3d3aad4SRichard Henderson     hw_exc |= CONVERT_BIT(exc, FPCR_INE, EXC_M_INE);
66f3d3aad4SRichard Henderson     hw_exc |= CONVERT_BIT(exc, FPCR_IOV, EXC_M_IOV);
674a58aedfSRichard Henderson 
684a58aedfSRichard Henderson     arith_excp(env, retaddr, hw_exc, 1ull << regno);
694a58aedfSRichard Henderson }
704a58aedfSRichard Henderson 
714a58aedfSRichard Henderson /* Raise exceptions for ieee fp insns without software completion.
724a58aedfSRichard Henderson    In that case there are no exceptions that don't trap; the mask
734a58aedfSRichard Henderson    doesn't apply.  */
helper_fp_exc_raise(CPUAlphaState * env,uint32_t ignore,uint32_t regno)74f3d3aad4SRichard Henderson void helper_fp_exc_raise(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
754a58aedfSRichard Henderson {
76471d4930SRichard Henderson     uint32_t exc = env->error_code;
77471d4930SRichard Henderson     if (exc) {
78471d4930SRichard Henderson         env->fpcr |= exc;
79471d4930SRichard Henderson         exc &= ~ignore;
80471d4930SRichard Henderson         if (exc) {
81f6b6b7b8SRichard Henderson             fp_exc_raise1(env, GETPC(), exc, regno, 0);
824a58aedfSRichard Henderson         }
83471d4930SRichard Henderson     }
84471d4930SRichard Henderson }
854a58aedfSRichard Henderson 
864a58aedfSRichard Henderson /* Raise exceptions for ieee fp insns with software completion.  */
helper_fp_exc_raise_s(CPUAlphaState * env,uint32_t ignore,uint32_t regno)87f3d3aad4SRichard Henderson void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
884a58aedfSRichard Henderson {
89f3d3aad4SRichard Henderson     uint32_t exc = env->error_code & ~ignore;
904a58aedfSRichard Henderson     if (exc) {
91f3d3aad4SRichard Henderson         env->fpcr |= exc;
9211bfdbdfSRichard Henderson         exc &= env->fpcr_exc_enable;
9321ba8564SRichard Henderson         /*
9421ba8564SRichard Henderson          * In system mode, the software handler gets invoked
9521ba8564SRichard Henderson          * for any non-ignored exception.
9611bfdbdfSRichard Henderson          * In user mode, the kernel's software handler only
9711bfdbdfSRichard Henderson          * delivers a signal if the exception is enabled.
9821ba8564SRichard Henderson          */
9911bfdbdfSRichard Henderson #ifdef CONFIG_USER_ONLY
10021ba8564SRichard Henderson         if (!exc) {
10121ba8564SRichard Henderson             return;
10221ba8564SRichard Henderson         }
10321ba8564SRichard Henderson #endif
104f6b6b7b8SRichard Henderson         fp_exc_raise1(env, GETPC(), exc, regno, EXC_M_SWC);
1054a58aedfSRichard Henderson     }
1064a58aedfSRichard Henderson }
1074a58aedfSRichard Henderson 
10874343409SRichard Henderson /* Input handing without software completion.  Trap for all
10974343409SRichard Henderson    non-finite numbers.  */
helper_ieee_input(CPUAlphaState * env,uint64_t val)11074343409SRichard Henderson void helper_ieee_input(CPUAlphaState *env, uint64_t val)
1114a58aedfSRichard Henderson {
1124a58aedfSRichard Henderson     uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
1134a58aedfSRichard Henderson     uint64_t frac = val & 0xfffffffffffffull;
1144a58aedfSRichard Henderson 
1154a58aedfSRichard Henderson     if (exp == 0) {
116b99e8069SRichard Henderson         /* Denormals without /S raise an exception.  */
117b99e8069SRichard Henderson         if (frac != 0) {
118b99e8069SRichard Henderson             arith_excp(env, GETPC(), EXC_M_INV, 0);
1194a58aedfSRichard Henderson         }
1204a58aedfSRichard Henderson     } else if (exp == 0x7ff) {
1214a58aedfSRichard Henderson         /* Infinity or NaN.  */
122b99e8069SRichard Henderson         env->fpcr |= FPCR_INV;
123b99e8069SRichard Henderson         arith_excp(env, GETPC(), EXC_M_INV, 0);
1244a58aedfSRichard Henderson     }
1254a58aedfSRichard Henderson }
1264a58aedfSRichard Henderson 
1274a58aedfSRichard Henderson /* Similar, but does not trap for infinities.  Used for comparisons.  */
helper_ieee_input_cmp(CPUAlphaState * env,uint64_t val)12874343409SRichard Henderson void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
1294a58aedfSRichard Henderson {
1304a58aedfSRichard Henderson     uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
1314a58aedfSRichard Henderson     uint64_t frac = val & 0xfffffffffffffull;
1324a58aedfSRichard Henderson 
1334a58aedfSRichard Henderson     if (exp == 0) {
134b99e8069SRichard Henderson         /* Denormals without /S raise an exception.  */
135b99e8069SRichard Henderson         if (frac != 0) {
136b99e8069SRichard Henderson             arith_excp(env, GETPC(), EXC_M_INV, 0);
1374a58aedfSRichard Henderson         }
1384a58aedfSRichard Henderson     } else if (exp == 0x7ff && frac) {
1394a58aedfSRichard Henderson         /* NaN.  */
140b99e8069SRichard Henderson         env->fpcr |= FPCR_INV;
1414a58aedfSRichard Henderson         arith_excp(env, GETPC(), EXC_M_INV, 0);
1424a58aedfSRichard Henderson     }
1434a58aedfSRichard Henderson }
1444a58aedfSRichard Henderson 
145b99e8069SRichard Henderson /* Input handing with software completion.  Trap for denorms, unless DNZ
146b99e8069SRichard Henderson    is set.  If we try to support DNOD (which none of the produced hardware
147b99e8069SRichard Henderson    did, AFAICS), we'll need to suppress the trap when FPCR.DNOD is set;
148b99e8069SRichard Henderson    then the code downstream of that will need to cope with denorms sans
149b99e8069SRichard Henderson    flush_input_to_zero.  Most of it should work sanely, but there's
150b99e8069SRichard Henderson    nothing to compare with.  */
helper_ieee_input_s(CPUAlphaState * env,uint64_t val)151b99e8069SRichard Henderson void helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
152b99e8069SRichard Henderson {
153b99e8069SRichard Henderson     if (unlikely(2 * val - 1 < 0x1fffffffffffffull)
154b99e8069SRichard Henderson         && !env->fp_status.flush_inputs_to_zero) {
155b99e8069SRichard Henderson         arith_excp(env, GETPC(), EXC_M_INV | EXC_M_SWC, 0);
156b99e8069SRichard Henderson     }
157b99e8069SRichard Henderson }
1584a58aedfSRichard Henderson 
1594a58aedfSRichard Henderson /* S floating (single) */
1604a58aedfSRichard Henderson 
1614a58aedfSRichard Henderson /* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg.  */
float32_to_s_int(uint32_t fi)1624a58aedfSRichard Henderson static inline uint64_t float32_to_s_int(uint32_t fi)
1634a58aedfSRichard Henderson {
1644a58aedfSRichard Henderson     uint32_t frac = fi & 0x7fffff;
1654a58aedfSRichard Henderson     uint32_t sign = fi >> 31;
1664a58aedfSRichard Henderson     uint32_t exp_msb = (fi >> 30) & 1;
1674a58aedfSRichard Henderson     uint32_t exp_low = (fi >> 23) & 0x7f;
1684a58aedfSRichard Henderson     uint32_t exp;
1694a58aedfSRichard Henderson 
1704a58aedfSRichard Henderson     exp = (exp_msb << 10) | exp_low;
1714a58aedfSRichard Henderson     if (exp_msb) {
1724a58aedfSRichard Henderson         if (exp_low == 0x7f) {
1734a58aedfSRichard Henderson             exp = 0x7ff;
1744a58aedfSRichard Henderson         }
1754a58aedfSRichard Henderson     } else {
1764a58aedfSRichard Henderson         if (exp_low != 0x00) {
1774a58aedfSRichard Henderson             exp |= 0x380;
1784a58aedfSRichard Henderson         }
1794a58aedfSRichard Henderson     }
1804a58aedfSRichard Henderson 
1814a58aedfSRichard Henderson     return (((uint64_t)sign << 63)
1824a58aedfSRichard Henderson             | ((uint64_t)exp << 52)
1834a58aedfSRichard Henderson             | ((uint64_t)frac << 29));
1844a58aedfSRichard Henderson }
1854a58aedfSRichard Henderson 
float32_to_s(float32 fa)1864a58aedfSRichard Henderson static inline uint64_t float32_to_s(float32 fa)
1874a58aedfSRichard Henderson {
1884a58aedfSRichard Henderson     CPU_FloatU a;
1894a58aedfSRichard Henderson     a.f = fa;
1904a58aedfSRichard Henderson     return float32_to_s_int(a.l);
1914a58aedfSRichard Henderson }
1924a58aedfSRichard Henderson 
s_to_float32_int(uint64_t a)1934a58aedfSRichard Henderson static inline uint32_t s_to_float32_int(uint64_t a)
1944a58aedfSRichard Henderson {
1954a58aedfSRichard Henderson     return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
1964a58aedfSRichard Henderson }
1974a58aedfSRichard Henderson 
s_to_float32(uint64_t a)1984a58aedfSRichard Henderson static inline float32 s_to_float32(uint64_t a)
1994a58aedfSRichard Henderson {
2004a58aedfSRichard Henderson     CPU_FloatU r;
2014a58aedfSRichard Henderson     r.l = s_to_float32_int(a);
2024a58aedfSRichard Henderson     return r.f;
2034a58aedfSRichard Henderson }
2044a58aedfSRichard Henderson 
helper_s_to_memory(uint64_t a)2054a58aedfSRichard Henderson uint32_t helper_s_to_memory(uint64_t a)
2064a58aedfSRichard Henderson {
2074a58aedfSRichard Henderson     return s_to_float32_int(a);
2084a58aedfSRichard Henderson }
2094a58aedfSRichard Henderson 
helper_memory_to_s(uint32_t a)2104a58aedfSRichard Henderson uint64_t helper_memory_to_s(uint32_t a)
2114a58aedfSRichard Henderson {
2124a58aedfSRichard Henderson     return float32_to_s_int(a);
2134a58aedfSRichard Henderson }
2144a58aedfSRichard Henderson 
helper_adds(CPUAlphaState * env,uint64_t a,uint64_t b)2154a58aedfSRichard Henderson uint64_t helper_adds(CPUAlphaState *env, uint64_t a, uint64_t b)
2164a58aedfSRichard Henderson {
2174a58aedfSRichard Henderson     float32 fa, fb, fr;
2184a58aedfSRichard Henderson 
2194a58aedfSRichard Henderson     fa = s_to_float32(a);
2204a58aedfSRichard Henderson     fb = s_to_float32(b);
2214a58aedfSRichard Henderson     fr = float32_add(fa, fb, &FP_STATUS);
222f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
223f3d3aad4SRichard Henderson 
2244a58aedfSRichard Henderson     return float32_to_s(fr);
2254a58aedfSRichard Henderson }
2264a58aedfSRichard Henderson 
helper_subs(CPUAlphaState * env,uint64_t a,uint64_t b)2274a58aedfSRichard Henderson uint64_t helper_subs(CPUAlphaState *env, uint64_t a, uint64_t b)
2284a58aedfSRichard Henderson {
2294a58aedfSRichard Henderson     float32 fa, fb, fr;
2304a58aedfSRichard Henderson 
2314a58aedfSRichard Henderson     fa = s_to_float32(a);
2324a58aedfSRichard Henderson     fb = s_to_float32(b);
2334a58aedfSRichard Henderson     fr = float32_sub(fa, fb, &FP_STATUS);
234f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
235f3d3aad4SRichard Henderson 
2364a58aedfSRichard Henderson     return float32_to_s(fr);
2374a58aedfSRichard Henderson }
2384a58aedfSRichard Henderson 
helper_muls(CPUAlphaState * env,uint64_t a,uint64_t b)2394a58aedfSRichard Henderson uint64_t helper_muls(CPUAlphaState *env, uint64_t a, uint64_t b)
2404a58aedfSRichard Henderson {
2414a58aedfSRichard Henderson     float32 fa, fb, fr;
2424a58aedfSRichard Henderson 
2434a58aedfSRichard Henderson     fa = s_to_float32(a);
2444a58aedfSRichard Henderson     fb = s_to_float32(b);
2454a58aedfSRichard Henderson     fr = float32_mul(fa, fb, &FP_STATUS);
246f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
247f3d3aad4SRichard Henderson 
2484a58aedfSRichard Henderson     return float32_to_s(fr);
2494a58aedfSRichard Henderson }
2504a58aedfSRichard Henderson 
helper_divs(CPUAlphaState * env,uint64_t a,uint64_t b)2514a58aedfSRichard Henderson uint64_t helper_divs(CPUAlphaState *env, uint64_t a, uint64_t b)
2524a58aedfSRichard Henderson {
2534a58aedfSRichard Henderson     float32 fa, fb, fr;
2544a58aedfSRichard Henderson 
2554a58aedfSRichard Henderson     fa = s_to_float32(a);
2564a58aedfSRichard Henderson     fb = s_to_float32(b);
2574a58aedfSRichard Henderson     fr = float32_div(fa, fb, &FP_STATUS);
258f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
259f3d3aad4SRichard Henderson 
2604a58aedfSRichard Henderson     return float32_to_s(fr);
2614a58aedfSRichard Henderson }
2624a58aedfSRichard Henderson 
helper_sqrts(CPUAlphaState * env,uint64_t a)2634a58aedfSRichard Henderson uint64_t helper_sqrts(CPUAlphaState *env, uint64_t a)
2644a58aedfSRichard Henderson {
2654a58aedfSRichard Henderson     float32 fa, fr;
2664a58aedfSRichard Henderson 
2674a58aedfSRichard Henderson     fa = s_to_float32(a);
2684a58aedfSRichard Henderson     fr = float32_sqrt(fa, &FP_STATUS);
269f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
270f3d3aad4SRichard Henderson 
2714a58aedfSRichard Henderson     return float32_to_s(fr);
2724a58aedfSRichard Henderson }
2734a58aedfSRichard Henderson 
2744a58aedfSRichard Henderson 
2754a58aedfSRichard Henderson /* T floating (double) */
t_to_float64(uint64_t a)2764a58aedfSRichard Henderson static inline float64 t_to_float64(uint64_t a)
2774a58aedfSRichard Henderson {
2784a58aedfSRichard Henderson     /* Memory format is the same as float64 */
2794a58aedfSRichard Henderson     CPU_DoubleU r;
2804a58aedfSRichard Henderson     r.ll = a;
2814a58aedfSRichard Henderson     return r.d;
2824a58aedfSRichard Henderson }
2834a58aedfSRichard Henderson 
float64_to_t(float64 fa)2844a58aedfSRichard Henderson static inline uint64_t float64_to_t(float64 fa)
2854a58aedfSRichard Henderson {
2864a58aedfSRichard Henderson     /* Memory format is the same as float64 */
2874a58aedfSRichard Henderson     CPU_DoubleU r;
2884a58aedfSRichard Henderson     r.d = fa;
2894a58aedfSRichard Henderson     return r.ll;
2904a58aedfSRichard Henderson }
2914a58aedfSRichard Henderson 
helper_addt(CPUAlphaState * env,uint64_t a,uint64_t b)2924a58aedfSRichard Henderson uint64_t helper_addt(CPUAlphaState *env, uint64_t a, uint64_t b)
2934a58aedfSRichard Henderson {
2944a58aedfSRichard Henderson     float64 fa, fb, fr;
2954a58aedfSRichard Henderson 
2964a58aedfSRichard Henderson     fa = t_to_float64(a);
2974a58aedfSRichard Henderson     fb = t_to_float64(b);
2984a58aedfSRichard Henderson     fr = float64_add(fa, fb, &FP_STATUS);
299f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
300f3d3aad4SRichard Henderson 
3014a58aedfSRichard Henderson     return float64_to_t(fr);
3024a58aedfSRichard Henderson }
3034a58aedfSRichard Henderson 
helper_subt(CPUAlphaState * env,uint64_t a,uint64_t b)3044a58aedfSRichard Henderson uint64_t helper_subt(CPUAlphaState *env, uint64_t a, uint64_t b)
3054a58aedfSRichard Henderson {
3064a58aedfSRichard Henderson     float64 fa, fb, fr;
3074a58aedfSRichard Henderson 
3084a58aedfSRichard Henderson     fa = t_to_float64(a);
3094a58aedfSRichard Henderson     fb = t_to_float64(b);
3104a58aedfSRichard Henderson     fr = float64_sub(fa, fb, &FP_STATUS);
311f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
312f3d3aad4SRichard Henderson 
3134a58aedfSRichard Henderson     return float64_to_t(fr);
3144a58aedfSRichard Henderson }
3154a58aedfSRichard Henderson 
helper_mult(CPUAlphaState * env,uint64_t a,uint64_t b)3164a58aedfSRichard Henderson uint64_t helper_mult(CPUAlphaState *env, uint64_t a, uint64_t b)
3174a58aedfSRichard Henderson {
3184a58aedfSRichard Henderson     float64 fa, fb, fr;
3194a58aedfSRichard Henderson 
3204a58aedfSRichard Henderson     fa = t_to_float64(a);
3214a58aedfSRichard Henderson     fb = t_to_float64(b);
3224a58aedfSRichard Henderson     fr = float64_mul(fa, fb, &FP_STATUS);
323f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
324f3d3aad4SRichard Henderson 
3254a58aedfSRichard Henderson     return float64_to_t(fr);
3264a58aedfSRichard Henderson }
3274a58aedfSRichard Henderson 
helper_divt(CPUAlphaState * env,uint64_t a,uint64_t b)3284a58aedfSRichard Henderson uint64_t helper_divt(CPUAlphaState *env, uint64_t a, uint64_t b)
3294a58aedfSRichard Henderson {
3304a58aedfSRichard Henderson     float64 fa, fb, fr;
3314a58aedfSRichard Henderson 
3324a58aedfSRichard Henderson     fa = t_to_float64(a);
3334a58aedfSRichard Henderson     fb = t_to_float64(b);
3344a58aedfSRichard Henderson     fr = float64_div(fa, fb, &FP_STATUS);
335f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
336f3d3aad4SRichard Henderson 
3374a58aedfSRichard Henderson     return float64_to_t(fr);
3384a58aedfSRichard Henderson }
3394a58aedfSRichard Henderson 
helper_sqrtt(CPUAlphaState * env,uint64_t a)3404a58aedfSRichard Henderson uint64_t helper_sqrtt(CPUAlphaState *env, uint64_t a)
3414a58aedfSRichard Henderson {
3424a58aedfSRichard Henderson     float64 fa, fr;
3434a58aedfSRichard Henderson 
3444a58aedfSRichard Henderson     fa = t_to_float64(a);
3454a58aedfSRichard Henderson     fr = float64_sqrt(fa, &FP_STATUS);
346f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
347f3d3aad4SRichard Henderson 
3484a58aedfSRichard Henderson     return float64_to_t(fr);
3494a58aedfSRichard Henderson }
3504a58aedfSRichard Henderson 
3514a58aedfSRichard Henderson /* Comparisons */
helper_cmptun(CPUAlphaState * env,uint64_t a,uint64_t b)3524a58aedfSRichard Henderson uint64_t helper_cmptun(CPUAlphaState *env, uint64_t a, uint64_t b)
3534a58aedfSRichard Henderson {
3544a58aedfSRichard Henderson     float64 fa, fb;
355f3d3aad4SRichard Henderson     uint64_t ret = 0;
3564a58aedfSRichard Henderson 
3574a58aedfSRichard Henderson     fa = t_to_float64(a);
3584a58aedfSRichard Henderson     fb = t_to_float64(b);
3594a58aedfSRichard Henderson 
3604a58aedfSRichard Henderson     if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
361f3d3aad4SRichard Henderson         ret = 0x4000000000000000ULL;
3624a58aedfSRichard Henderson     }
363f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
364f3d3aad4SRichard Henderson 
365f3d3aad4SRichard Henderson     return ret;
3664a58aedfSRichard Henderson }
3674a58aedfSRichard Henderson 
helper_cmpteq(CPUAlphaState * env,uint64_t a,uint64_t b)3684a58aedfSRichard Henderson uint64_t helper_cmpteq(CPUAlphaState *env, uint64_t a, uint64_t b)
3694a58aedfSRichard Henderson {
3704a58aedfSRichard Henderson     float64 fa, fb;
371f3d3aad4SRichard Henderson     uint64_t ret = 0;
3724a58aedfSRichard Henderson 
3734a58aedfSRichard Henderson     fa = t_to_float64(a);
3744a58aedfSRichard Henderson     fb = t_to_float64(b);
3754a58aedfSRichard Henderson 
3764a58aedfSRichard Henderson     if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
377f3d3aad4SRichard Henderson         ret = 0x4000000000000000ULL;
3784a58aedfSRichard Henderson     }
379f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
380f3d3aad4SRichard Henderson 
381f3d3aad4SRichard Henderson     return ret;
3824a58aedfSRichard Henderson }
3834a58aedfSRichard Henderson 
helper_cmptle(CPUAlphaState * env,uint64_t a,uint64_t b)3844a58aedfSRichard Henderson uint64_t helper_cmptle(CPUAlphaState *env, uint64_t a, uint64_t b)
3854a58aedfSRichard Henderson {
3864a58aedfSRichard Henderson     float64 fa, fb;
387f3d3aad4SRichard Henderson     uint64_t ret = 0;
3884a58aedfSRichard Henderson 
3894a58aedfSRichard Henderson     fa = t_to_float64(a);
3904a58aedfSRichard Henderson     fb = t_to_float64(b);
3914a58aedfSRichard Henderson 
3924a58aedfSRichard Henderson     if (float64_le(fa, fb, &FP_STATUS)) {
393f3d3aad4SRichard Henderson         ret = 0x4000000000000000ULL;
3944a58aedfSRichard Henderson     }
395f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
396f3d3aad4SRichard Henderson 
397f3d3aad4SRichard Henderson     return ret;
3984a58aedfSRichard Henderson }
3994a58aedfSRichard Henderson 
helper_cmptlt(CPUAlphaState * env,uint64_t a,uint64_t b)4004a58aedfSRichard Henderson uint64_t helper_cmptlt(CPUAlphaState *env, uint64_t a, uint64_t b)
4014a58aedfSRichard Henderson {
4024a58aedfSRichard Henderson     float64 fa, fb;
403f3d3aad4SRichard Henderson     uint64_t ret = 0;
4044a58aedfSRichard Henderson 
4054a58aedfSRichard Henderson     fa = t_to_float64(a);
4064a58aedfSRichard Henderson     fb = t_to_float64(b);
4074a58aedfSRichard Henderson 
4084a58aedfSRichard Henderson     if (float64_lt(fa, fb, &FP_STATUS)) {
409f3d3aad4SRichard Henderson         ret = 0x4000000000000000ULL;
4104a58aedfSRichard Henderson     }
411f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
412f3d3aad4SRichard Henderson 
413f3d3aad4SRichard Henderson     return ret;
4144a58aedfSRichard Henderson }
4154a58aedfSRichard Henderson 
4164a58aedfSRichard Henderson /* Floating point format conversion */
helper_cvtts(CPUAlphaState * env,uint64_t a)4174a58aedfSRichard Henderson uint64_t helper_cvtts(CPUAlphaState *env, uint64_t a)
4184a58aedfSRichard Henderson {
4194a58aedfSRichard Henderson     float64 fa;
4204a58aedfSRichard Henderson     float32 fr;
4214a58aedfSRichard Henderson 
4224a58aedfSRichard Henderson     fa = t_to_float64(a);
4234a58aedfSRichard Henderson     fr = float64_to_float32(fa, &FP_STATUS);
424f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
425f3d3aad4SRichard Henderson 
4264a58aedfSRichard Henderson     return float32_to_s(fr);
4274a58aedfSRichard Henderson }
4284a58aedfSRichard Henderson 
helper_cvtst(CPUAlphaState * env,uint64_t a)4294a58aedfSRichard Henderson uint64_t helper_cvtst(CPUAlphaState *env, uint64_t a)
4304a58aedfSRichard Henderson {
4314a58aedfSRichard Henderson     float32 fa;
4324a58aedfSRichard Henderson     float64 fr;
4334a58aedfSRichard Henderson 
4344a58aedfSRichard Henderson     fa = s_to_float32(a);
4354a58aedfSRichard Henderson     fr = float32_to_float64(fa, &FP_STATUS);
436f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
437f3d3aad4SRichard Henderson 
4384a58aedfSRichard Henderson     return float64_to_t(fr);
4394a58aedfSRichard Henderson }
4404a58aedfSRichard Henderson 
helper_cvtqs(CPUAlphaState * env,uint64_t a)4414a58aedfSRichard Henderson uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a)
4424a58aedfSRichard Henderson {
4434a58aedfSRichard Henderson     float32 fr = int64_to_float32(a, &FP_STATUS);
444f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
445f3d3aad4SRichard Henderson 
4464a58aedfSRichard Henderson     return float32_to_s(fr);
4474a58aedfSRichard Henderson }
4484a58aedfSRichard Henderson 
449182f42fdSPeter Maydell /* Implement float64 to uint64_t conversion without saturation -- we must
4504a58aedfSRichard Henderson    supply the truncated result.  This behaviour is used by the compiler
451c24a8a0bSRichard Henderson    to get unsigned conversion for free with the same instruction.  */
4524a58aedfSRichard Henderson 
do_cvttq(CPUAlphaState * env,uint64_t a,int roundmode)453c24a8a0bSRichard Henderson static uint64_t do_cvttq(CPUAlphaState *env, uint64_t a, int roundmode)
4544a58aedfSRichard Henderson {
455aa3bad5bSRichard Henderson     float64 fa;
456aa3bad5bSRichard Henderson     int64_t ret;
457*35487a6dSPhilippe Mathieu-Daudé     uint32_t exc = 0;
458*35487a6dSPhilippe Mathieu-Daudé     int flags;
4594a58aedfSRichard Henderson 
460aa3bad5bSRichard Henderson     fa = t_to_float64(a);
461aa3bad5bSRichard Henderson     ret = float64_to_int64_modulo(fa, roundmode, &FP_STATUS);
4624a58aedfSRichard Henderson 
463*35487a6dSPhilippe Mathieu-Daudé     flags = get_float_exception_flags(&FP_STATUS);
464*35487a6dSPhilippe Mathieu-Daudé     if (unlikely(flags)) {
465aa3bad5bSRichard Henderson         set_float_exception_flags(0, &FP_STATUS);
466aa3bad5bSRichard Henderson 
467aa3bad5bSRichard Henderson         /* We need to massage the resulting exceptions. */
468*35487a6dSPhilippe Mathieu-Daudé         if (flags & float_flag_invalid_cvti) {
469aa3bad5bSRichard Henderson             /* Overflow, either normal or infinity. */
470aa3bad5bSRichard Henderson             if (float64_is_infinity(fa)) {
4717b4dde83SRichard Henderson                 exc = FPCR_INV;
4724a58aedfSRichard Henderson             } else {
4737f2e4002SRichard Henderson                 exc = FPCR_IOV | FPCR_INE;
4744a58aedfSRichard Henderson             }
475*35487a6dSPhilippe Mathieu-Daudé         } else if (flags & float_flag_invalid) {
476aa3bad5bSRichard Henderson             exc = FPCR_INV;
477*35487a6dSPhilippe Mathieu-Daudé         } else if (flags & float_flag_inexact) {
478c24a8a0bSRichard Henderson             exc = FPCR_INE;
4794a58aedfSRichard Henderson         }
4804a58aedfSRichard Henderson     }
481f3d3aad4SRichard Henderson     env->error_code = exc;
4824a58aedfSRichard Henderson 
4834a58aedfSRichard Henderson     return ret;
4844a58aedfSRichard Henderson }
4854a58aedfSRichard Henderson 
helper_cvttq(CPUAlphaState * env,uint64_t a)4864a58aedfSRichard Henderson uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
4874a58aedfSRichard Henderson {
488c24a8a0bSRichard Henderson     return do_cvttq(env, a, FP_STATUS.float_rounding_mode);
4894a58aedfSRichard Henderson }
4904a58aedfSRichard Henderson 
helper_cvttq_c(CPUAlphaState * env,uint64_t a)4914a58aedfSRichard Henderson uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
4924a58aedfSRichard Henderson {
493c24a8a0bSRichard Henderson     return do_cvttq(env, a, float_round_to_zero);
4944a58aedfSRichard Henderson }
4954a58aedfSRichard Henderson 
helper_cvtqt(CPUAlphaState * env,uint64_t a)4964a58aedfSRichard Henderson uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a)
4974a58aedfSRichard Henderson {
4984a58aedfSRichard Henderson     float64 fr = int64_to_float64(a, &FP_STATUS);
499f3d3aad4SRichard Henderson     env->error_code = soft_to_fpcr_exc(env);
5004a58aedfSRichard Henderson     return float64_to_t(fr);
5014a58aedfSRichard Henderson }
5024a58aedfSRichard Henderson 
helper_cvtql(CPUAlphaState * env,uint64_t val)50357a808b6SRichard Henderson uint64_t helper_cvtql(CPUAlphaState *env, uint64_t val)
504e8d8fef4SRichard Henderson {
50557a808b6SRichard Henderson     uint32_t exc = 0;
506e8d8fef4SRichard Henderson     if (val != (int32_t)val) {
50757a808b6SRichard Henderson         exc = FPCR_IOV | FPCR_INE;
508e8d8fef4SRichard Henderson     }
50957a808b6SRichard Henderson     env->error_code = exc;
51057a808b6SRichard Henderson 
51157a808b6SRichard Henderson     return ((val & 0xc0000000) << 32) | ((val & 0x3fffffff) << 29);
512e8d8fef4SRichard Henderson }
513