1996a729fSBastian Koppelmann /* 2996a729fSBastian Koppelmann * TriCore emulation for qemu: fpu helper. 3996a729fSBastian Koppelmann * 4996a729fSBastian Koppelmann * Copyright (c) 2016 Bastian Koppelmann University of Paderborn 5996a729fSBastian Koppelmann * 6996a729fSBastian Koppelmann * This library is free software; you can redistribute it and/or 7996a729fSBastian Koppelmann * modify it under the terms of the GNU Lesser General Public 8996a729fSBastian Koppelmann * License as published by the Free Software Foundation; either 902754acdSThomas Huth * version 2.1 of the License, or (at your option) any later version. 10996a729fSBastian Koppelmann * 11996a729fSBastian Koppelmann * This library is distributed in the hope that it will be useful, 12996a729fSBastian Koppelmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 13996a729fSBastian Koppelmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14996a729fSBastian Koppelmann * Lesser General Public License for more details. 15996a729fSBastian Koppelmann * 16996a729fSBastian Koppelmann * You should have received a copy of the GNU Lesser General Public 17996a729fSBastian Koppelmann * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18996a729fSBastian Koppelmann */ 19996a729fSBastian Koppelmann 20996a729fSBastian Koppelmann #include "qemu/osdep.h" 21996a729fSBastian Koppelmann #include "cpu.h" 22996a729fSBastian Koppelmann #include "exec/helper-proto.h" 2324f91e81SAlex Bennée #include "fpu/softfloat.h" 24996a729fSBastian Koppelmann 25ddd7feadSBastian Koppelmann #define QUIET_NAN 0x7fc00000 26ddd7feadSBastian Koppelmann #define ADD_NAN 0x7fc00001 27*8317ea06SAndreas Konopik #define SQRT_NAN 0x7fc00004 28996a729fSBastian Koppelmann #define DIV_NAN 0x7fc00008 29996a729fSBastian Koppelmann #define MUL_NAN 0x7fc00002 30996a729fSBastian Koppelmann #define FPU_FS PSW_USB_C 31996a729fSBastian Koppelmann #define FPU_FI PSW_USB_V 32996a729fSBastian Koppelmann #define FPU_FV PSW_USB_SV 33996a729fSBastian Koppelmann #define FPU_FZ PSW_USB_AV 34996a729fSBastian Koppelmann #define FPU_FU PSW_USB_SAV 35996a729fSBastian Koppelmann 36*8317ea06SAndreas Konopik #define float32_sqrt_nan make_float32(SQRT_NAN) 37*8317ea06SAndreas Konopik #define float32_quiet_nan make_float32(QUIET_NAN) 38*8317ea06SAndreas Konopik 39996a729fSBastian Koppelmann /* we don't care about input_denormal */ 40996a729fSBastian Koppelmann static inline uint8_t f_get_excp_flags(CPUTriCoreState *env) 41996a729fSBastian Koppelmann { 42996a729fSBastian Koppelmann return get_float_exception_flags(&env->fp_status) 43996a729fSBastian Koppelmann & (float_flag_invalid 44996a729fSBastian Koppelmann | float_flag_overflow 45996a729fSBastian Koppelmann | float_flag_underflow 46996a729fSBastian Koppelmann | float_flag_output_denormal 47996a729fSBastian Koppelmann | float_flag_divbyzero 48996a729fSBastian Koppelmann | float_flag_inexact); 49996a729fSBastian Koppelmann } 50996a729fSBastian Koppelmann 51ddd7feadSBastian Koppelmann static inline float32 f_maddsub_nan_result(float32 arg1, float32 arg2, 52ddd7feadSBastian Koppelmann float32 arg3, float32 result, 53ddd7feadSBastian Koppelmann uint32_t muladd_negate_c) 54ddd7feadSBastian Koppelmann { 55ddd7feadSBastian Koppelmann uint32_t aSign, bSign, cSign; 56ddd7feadSBastian Koppelmann uint32_t aExp, bExp, cExp; 57ddd7feadSBastian Koppelmann 58ddd7feadSBastian Koppelmann if (float32_is_any_nan(arg1) || float32_is_any_nan(arg2) || 59ddd7feadSBastian Koppelmann float32_is_any_nan(arg3)) { 60ddd7feadSBastian Koppelmann return QUIET_NAN; 61ddd7feadSBastian Koppelmann } else if (float32_is_infinity(arg1) && float32_is_zero(arg2)) { 62ddd7feadSBastian Koppelmann return MUL_NAN; 63ddd7feadSBastian Koppelmann } else if (float32_is_zero(arg1) && float32_is_infinity(arg2)) { 64ddd7feadSBastian Koppelmann return MUL_NAN; 65ddd7feadSBastian Koppelmann } else { 66ddd7feadSBastian Koppelmann aSign = arg1 >> 31; 67ddd7feadSBastian Koppelmann bSign = arg2 >> 31; 68ddd7feadSBastian Koppelmann cSign = arg3 >> 31; 69ddd7feadSBastian Koppelmann 70ddd7feadSBastian Koppelmann aExp = (arg1 >> 23) & 0xff; 71ddd7feadSBastian Koppelmann bExp = (arg2 >> 23) & 0xff; 72ddd7feadSBastian Koppelmann cExp = (arg3 >> 23) & 0xff; 73ddd7feadSBastian Koppelmann 74ddd7feadSBastian Koppelmann if (muladd_negate_c) { 75ddd7feadSBastian Koppelmann cSign ^= 1; 76ddd7feadSBastian Koppelmann } 77ddd7feadSBastian Koppelmann if (((aExp == 0xff) || (bExp == 0xff)) && (cExp == 0xff)) { 78ddd7feadSBastian Koppelmann if (aSign ^ bSign ^ cSign) { 79ddd7feadSBastian Koppelmann return ADD_NAN; 80ddd7feadSBastian Koppelmann } 81ddd7feadSBastian Koppelmann } 82ddd7feadSBastian Koppelmann } 83ddd7feadSBastian Koppelmann 84ddd7feadSBastian Koppelmann return result; 85ddd7feadSBastian Koppelmann } 86ddd7feadSBastian Koppelmann 87baf410dcSBastian Koppelmann static void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags) 88996a729fSBastian Koppelmann { 89996a729fSBastian Koppelmann uint8_t some_excp = 0; 90996a729fSBastian Koppelmann set_float_exception_flags(0, &env->fp_status); 91996a729fSBastian Koppelmann 92996a729fSBastian Koppelmann if (flags & float_flag_invalid) { 93996a729fSBastian Koppelmann env->FPU_FI = 1 << 31; 94996a729fSBastian Koppelmann some_excp = 1; 95996a729fSBastian Koppelmann } 96996a729fSBastian Koppelmann 97996a729fSBastian Koppelmann if (flags & float_flag_overflow) { 98996a729fSBastian Koppelmann env->FPU_FV = 1 << 31; 99996a729fSBastian Koppelmann some_excp = 1; 100996a729fSBastian Koppelmann } 101996a729fSBastian Koppelmann 102996a729fSBastian Koppelmann if (flags & float_flag_underflow || flags & float_flag_output_denormal) { 103996a729fSBastian Koppelmann env->FPU_FU = 1 << 31; 104996a729fSBastian Koppelmann some_excp = 1; 105996a729fSBastian Koppelmann } 106996a729fSBastian Koppelmann 107996a729fSBastian Koppelmann if (flags & float_flag_divbyzero) { 108996a729fSBastian Koppelmann env->FPU_FZ = 1 << 31; 109996a729fSBastian Koppelmann some_excp = 1; 110996a729fSBastian Koppelmann } 111996a729fSBastian Koppelmann 112996a729fSBastian Koppelmann if (flags & float_flag_inexact || flags & float_flag_output_denormal) { 113996a729fSBastian Koppelmann env->PSW |= 1 << 26; 114996a729fSBastian Koppelmann some_excp = 1; 115996a729fSBastian Koppelmann } 116996a729fSBastian Koppelmann 117996a729fSBastian Koppelmann env->FPU_FS = some_excp; 118996a729fSBastian Koppelmann } 119baf410dcSBastian Koppelmann 120baf410dcSBastian Koppelmann #define FADD_SUB(op) \ 121baf410dcSBastian Koppelmann uint32_t helper_f##op(CPUTriCoreState *env, uint32_t r1, uint32_t r2) \ 122baf410dcSBastian Koppelmann { \ 123baf410dcSBastian Koppelmann float32 arg1 = make_float32(r1); \ 124baf410dcSBastian Koppelmann float32 arg2 = make_float32(r2); \ 125baf410dcSBastian Koppelmann uint32_t flags; \ 126baf410dcSBastian Koppelmann float32 f_result; \ 127baf410dcSBastian Koppelmann \ 128baf410dcSBastian Koppelmann f_result = float32_##op(arg2, arg1, &env->fp_status); \ 129baf410dcSBastian Koppelmann flags = f_get_excp_flags(env); \ 130baf410dcSBastian Koppelmann if (flags) { \ 131baf410dcSBastian Koppelmann /* If the output is a NaN, but the inputs aren't, \ 132baf410dcSBastian Koppelmann we return a unique value. */ \ 133baf410dcSBastian Koppelmann if ((flags & float_flag_invalid) \ 134baf410dcSBastian Koppelmann && !float32_is_any_nan(arg1) \ 135baf410dcSBastian Koppelmann && !float32_is_any_nan(arg2)) { \ 136baf410dcSBastian Koppelmann f_result = ADD_NAN; \ 137baf410dcSBastian Koppelmann } \ 138baf410dcSBastian Koppelmann f_update_psw_flags(env, flags); \ 139baf410dcSBastian Koppelmann } else { \ 140baf410dcSBastian Koppelmann env->FPU_FS = 0; \ 141baf410dcSBastian Koppelmann } \ 142baf410dcSBastian Koppelmann return (uint32_t)f_result; \ 143baf410dcSBastian Koppelmann } 144baf410dcSBastian Koppelmann FADD_SUB(add) 145baf410dcSBastian Koppelmann FADD_SUB(sub) 146daab3f7fSBastian Koppelmann 147daab3f7fSBastian Koppelmann uint32_t helper_fmul(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 148daab3f7fSBastian Koppelmann { 149daab3f7fSBastian Koppelmann uint32_t flags; 150daab3f7fSBastian Koppelmann float32 arg1 = make_float32(r1); 151daab3f7fSBastian Koppelmann float32 arg2 = make_float32(r2); 152daab3f7fSBastian Koppelmann float32 f_result; 153daab3f7fSBastian Koppelmann 154daab3f7fSBastian Koppelmann f_result = float32_mul(arg1, arg2, &env->fp_status); 155daab3f7fSBastian Koppelmann 156daab3f7fSBastian Koppelmann flags = f_get_excp_flags(env); 157daab3f7fSBastian Koppelmann if (flags) { 158daab3f7fSBastian Koppelmann /* If the output is a NaN, but the inputs aren't, 159daab3f7fSBastian Koppelmann we return a unique value. */ 160daab3f7fSBastian Koppelmann if ((flags & float_flag_invalid) 161daab3f7fSBastian Koppelmann && !float32_is_any_nan(arg1) 162daab3f7fSBastian Koppelmann && !float32_is_any_nan(arg2)) { 163daab3f7fSBastian Koppelmann f_result = MUL_NAN; 164daab3f7fSBastian Koppelmann } 165daab3f7fSBastian Koppelmann f_update_psw_flags(env, flags); 166daab3f7fSBastian Koppelmann } else { 167daab3f7fSBastian Koppelmann env->FPU_FS = 0; 168daab3f7fSBastian Koppelmann } 169daab3f7fSBastian Koppelmann return (uint32_t)f_result; 170daab3f7fSBastian Koppelmann 171daab3f7fSBastian Koppelmann } 172446ee5b2SBastian Koppelmann 173*8317ea06SAndreas Konopik /* 174*8317ea06SAndreas Konopik * Target TriCore QSEED.F significand Lookup Table 175*8317ea06SAndreas Konopik * 176*8317ea06SAndreas Konopik * The QSEED.F output significand depends on the least-significant 177*8317ea06SAndreas Konopik * exponent bit and the 6 most-significant significand bits. 178*8317ea06SAndreas Konopik * 179*8317ea06SAndreas Konopik * IEEE 754 float datatype 180*8317ea06SAndreas Konopik * partitioned into Sign (S), Exponent (E) and Significand (M): 181*8317ea06SAndreas Konopik * 182*8317ea06SAndreas Konopik * S E E E E E E E E M M M M M M ... 183*8317ea06SAndreas Konopik * | | | 184*8317ea06SAndreas Konopik * +------+------+-------+-------+ 185*8317ea06SAndreas Konopik * | | 186*8317ea06SAndreas Konopik * for lookup table 187*8317ea06SAndreas Konopik * calculating index for 188*8317ea06SAndreas Konopik * output E output M 189*8317ea06SAndreas Konopik * 190*8317ea06SAndreas Konopik * This lookup table was extracted by analyzing QSEED output 191*8317ea06SAndreas Konopik * from the real hardware 192*8317ea06SAndreas Konopik */ 193*8317ea06SAndreas Konopik static const uint8_t target_qseed_significand_table[128] = { 194*8317ea06SAndreas Konopik 253, 252, 245, 244, 239, 238, 231, 230, 225, 224, 217, 216, 195*8317ea06SAndreas Konopik 211, 210, 205, 204, 201, 200, 195, 194, 189, 188, 185, 184, 196*8317ea06SAndreas Konopik 179, 178, 175, 174, 169, 168, 165, 164, 161, 160, 157, 156, 197*8317ea06SAndreas Konopik 153, 152, 149, 148, 145, 144, 141, 140, 137, 136, 133, 132, 198*8317ea06SAndreas Konopik 131, 130, 127, 126, 123, 122, 121, 120, 117, 116, 115, 114, 199*8317ea06SAndreas Konopik 111, 110, 109, 108, 103, 102, 99, 98, 93, 92, 89, 88, 83, 200*8317ea06SAndreas Konopik 82, 79, 78, 75, 74, 71, 70, 67, 66, 63, 62, 59, 58, 55, 201*8317ea06SAndreas Konopik 54, 53, 52, 49, 48, 45, 44, 43, 42, 39, 38, 37, 36, 33, 202*8317ea06SAndreas Konopik 32, 31, 30, 27, 26, 25, 24, 23, 22, 19, 18, 17, 16, 15, 203*8317ea06SAndreas Konopik 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 204*8317ea06SAndreas Konopik }; 205*8317ea06SAndreas Konopik 206*8317ea06SAndreas Konopik uint32_t helper_qseed(CPUTriCoreState *env, uint32_t r1) 207*8317ea06SAndreas Konopik { 208*8317ea06SAndreas Konopik uint32_t arg1, S, E, M, E_minus_one, m_idx; 209*8317ea06SAndreas Konopik uint32_t new_E, new_M, new_S, result; 210*8317ea06SAndreas Konopik 211*8317ea06SAndreas Konopik arg1 = make_float32(r1); 212*8317ea06SAndreas Konopik 213*8317ea06SAndreas Konopik /* fetch IEEE-754 fields S, E and the uppermost 6-bit of M */ 214*8317ea06SAndreas Konopik S = extract32(arg1, 31, 1); 215*8317ea06SAndreas Konopik E = extract32(arg1, 23, 8); 216*8317ea06SAndreas Konopik M = extract32(arg1, 17, 6); 217*8317ea06SAndreas Konopik 218*8317ea06SAndreas Konopik if (float32_is_any_nan(arg1)) { 219*8317ea06SAndreas Konopik result = float32_quiet_nan; 220*8317ea06SAndreas Konopik } else if (float32_is_zero_or_denormal(arg1)) { 221*8317ea06SAndreas Konopik if (float32_is_neg(arg1)) { 222*8317ea06SAndreas Konopik result = float32_infinity | (1 << 31); 223*8317ea06SAndreas Konopik } else { 224*8317ea06SAndreas Konopik result = float32_infinity; 225*8317ea06SAndreas Konopik } 226*8317ea06SAndreas Konopik } else if (float32_is_neg(arg1)) { 227*8317ea06SAndreas Konopik result = float32_sqrt_nan; 228*8317ea06SAndreas Konopik } else if (float32_is_infinity(arg1)) { 229*8317ea06SAndreas Konopik result = float32_zero; 230*8317ea06SAndreas Konopik } else { 231*8317ea06SAndreas Konopik E_minus_one = E - 1; 232*8317ea06SAndreas Konopik m_idx = ((E_minus_one & 1) << 6) | M; 233*8317ea06SAndreas Konopik new_S = S; 234*8317ea06SAndreas Konopik new_E = 0xBD - E_minus_one / 2; 235*8317ea06SAndreas Konopik new_M = target_qseed_significand_table[m_idx]; 236*8317ea06SAndreas Konopik 237*8317ea06SAndreas Konopik result = 0; 238*8317ea06SAndreas Konopik result = deposit32(result, 31, 1, new_S); 239*8317ea06SAndreas Konopik result = deposit32(result, 23, 8, new_E); 240*8317ea06SAndreas Konopik result = deposit32(result, 15, 8, new_M); 241*8317ea06SAndreas Konopik } 242*8317ea06SAndreas Konopik 243*8317ea06SAndreas Konopik if (float32_is_signaling_nan(arg1, &env->fp_status) 244*8317ea06SAndreas Konopik || result == float32_sqrt_nan) { 245*8317ea06SAndreas Konopik env->FPU_FI = 1 << 31; 246*8317ea06SAndreas Konopik env->FPU_FS = 1; 247*8317ea06SAndreas Konopik } else { 248*8317ea06SAndreas Konopik env->FPU_FS = 0; 249*8317ea06SAndreas Konopik } 250*8317ea06SAndreas Konopik 251*8317ea06SAndreas Konopik return (uint32_t) result; 252*8317ea06SAndreas Konopik } 253*8317ea06SAndreas Konopik 254446ee5b2SBastian Koppelmann uint32_t helper_fdiv(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 255446ee5b2SBastian Koppelmann { 256446ee5b2SBastian Koppelmann uint32_t flags; 257446ee5b2SBastian Koppelmann float32 arg1 = make_float32(r1); 258446ee5b2SBastian Koppelmann float32 arg2 = make_float32(r2); 259446ee5b2SBastian Koppelmann float32 f_result; 260446ee5b2SBastian Koppelmann 261446ee5b2SBastian Koppelmann f_result = float32_div(arg1, arg2 , &env->fp_status); 262446ee5b2SBastian Koppelmann 263446ee5b2SBastian Koppelmann flags = f_get_excp_flags(env); 264446ee5b2SBastian Koppelmann if (flags) { 265446ee5b2SBastian Koppelmann /* If the output is a NaN, but the inputs aren't, 266446ee5b2SBastian Koppelmann we return a unique value. */ 267446ee5b2SBastian Koppelmann if ((flags & float_flag_invalid) 268446ee5b2SBastian Koppelmann && !float32_is_any_nan(arg1) 269446ee5b2SBastian Koppelmann && !float32_is_any_nan(arg2)) { 270446ee5b2SBastian Koppelmann f_result = DIV_NAN; 271446ee5b2SBastian Koppelmann } 272446ee5b2SBastian Koppelmann f_update_psw_flags(env, flags); 273446ee5b2SBastian Koppelmann } else { 274446ee5b2SBastian Koppelmann env->FPU_FS = 0; 275446ee5b2SBastian Koppelmann } 276446ee5b2SBastian Koppelmann 277446ee5b2SBastian Koppelmann return (uint32_t)f_result; 278446ee5b2SBastian Koppelmann } 279743cd09dSBastian Koppelmann 280ddd7feadSBastian Koppelmann uint32_t helper_fmadd(CPUTriCoreState *env, uint32_t r1, 281ddd7feadSBastian Koppelmann uint32_t r2, uint32_t r3) 282ddd7feadSBastian Koppelmann { 283ddd7feadSBastian Koppelmann uint32_t flags; 284ddd7feadSBastian Koppelmann float32 arg1 = make_float32(r1); 285ddd7feadSBastian Koppelmann float32 arg2 = make_float32(r2); 286ddd7feadSBastian Koppelmann float32 arg3 = make_float32(r3); 287ddd7feadSBastian Koppelmann float32 f_result; 288ddd7feadSBastian Koppelmann 289ddd7feadSBastian Koppelmann f_result = float32_muladd(arg1, arg2, arg3, 0, &env->fp_status); 290ddd7feadSBastian Koppelmann 291ddd7feadSBastian Koppelmann flags = f_get_excp_flags(env); 292ddd7feadSBastian Koppelmann if (flags) { 293ddd7feadSBastian Koppelmann if (flags & float_flag_invalid) { 294ddd7feadSBastian Koppelmann arg1 = float32_squash_input_denormal(arg1, &env->fp_status); 295ddd7feadSBastian Koppelmann arg2 = float32_squash_input_denormal(arg2, &env->fp_status); 296ddd7feadSBastian Koppelmann arg3 = float32_squash_input_denormal(arg3, &env->fp_status); 297ddd7feadSBastian Koppelmann f_result = f_maddsub_nan_result(arg1, arg2, arg3, f_result, 0); 298ddd7feadSBastian Koppelmann } 299ddd7feadSBastian Koppelmann f_update_psw_flags(env, flags); 300ddd7feadSBastian Koppelmann } else { 301ddd7feadSBastian Koppelmann env->FPU_FS = 0; 302ddd7feadSBastian Koppelmann } 303ddd7feadSBastian Koppelmann return (uint32_t)f_result; 304ddd7feadSBastian Koppelmann } 305ddd7feadSBastian Koppelmann 306ddd7feadSBastian Koppelmann uint32_t helper_fmsub(CPUTriCoreState *env, uint32_t r1, 307ddd7feadSBastian Koppelmann uint32_t r2, uint32_t r3) 308ddd7feadSBastian Koppelmann { 309ddd7feadSBastian Koppelmann uint32_t flags; 310ddd7feadSBastian Koppelmann float32 arg1 = make_float32(r1); 311ddd7feadSBastian Koppelmann float32 arg2 = make_float32(r2); 312ddd7feadSBastian Koppelmann float32 arg3 = make_float32(r3); 313ddd7feadSBastian Koppelmann float32 f_result; 314ddd7feadSBastian Koppelmann 315ddd7feadSBastian Koppelmann f_result = float32_muladd(arg1, arg2, arg3, float_muladd_negate_product, 316ddd7feadSBastian Koppelmann &env->fp_status); 317ddd7feadSBastian Koppelmann 318ddd7feadSBastian Koppelmann flags = f_get_excp_flags(env); 319ddd7feadSBastian Koppelmann if (flags) { 320ddd7feadSBastian Koppelmann if (flags & float_flag_invalid) { 321ddd7feadSBastian Koppelmann arg1 = float32_squash_input_denormal(arg1, &env->fp_status); 322ddd7feadSBastian Koppelmann arg2 = float32_squash_input_denormal(arg2, &env->fp_status); 323ddd7feadSBastian Koppelmann arg3 = float32_squash_input_denormal(arg3, &env->fp_status); 324ddd7feadSBastian Koppelmann 325ddd7feadSBastian Koppelmann f_result = f_maddsub_nan_result(arg1, arg2, arg3, f_result, 1); 326ddd7feadSBastian Koppelmann } 327ddd7feadSBastian Koppelmann f_update_psw_flags(env, flags); 328ddd7feadSBastian Koppelmann } else { 329ddd7feadSBastian Koppelmann env->FPU_FS = 0; 330ddd7feadSBastian Koppelmann } 331ddd7feadSBastian Koppelmann return (uint32_t)f_result; 332ddd7feadSBastian Koppelmann } 333ddd7feadSBastian Koppelmann 334743cd09dSBastian Koppelmann uint32_t helper_fcmp(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 335743cd09dSBastian Koppelmann { 336743cd09dSBastian Koppelmann uint32_t result, flags; 337743cd09dSBastian Koppelmann float32 arg1 = make_float32(r1); 338743cd09dSBastian Koppelmann float32 arg2 = make_float32(r2); 339743cd09dSBastian Koppelmann 340743cd09dSBastian Koppelmann set_flush_inputs_to_zero(0, &env->fp_status); 341743cd09dSBastian Koppelmann 342743cd09dSBastian Koppelmann result = 1 << (float32_compare_quiet(arg1, arg2, &env->fp_status) + 1); 343b8c54700SEmilio G. Cota result |= float32_is_denormal(arg1) << 4; 344b8c54700SEmilio G. Cota result |= float32_is_denormal(arg2) << 5; 345743cd09dSBastian Koppelmann 346743cd09dSBastian Koppelmann flags = f_get_excp_flags(env); 347743cd09dSBastian Koppelmann if (flags) { 348743cd09dSBastian Koppelmann f_update_psw_flags(env, flags); 349743cd09dSBastian Koppelmann } else { 350743cd09dSBastian Koppelmann env->FPU_FS = 0; 351743cd09dSBastian Koppelmann } 352743cd09dSBastian Koppelmann 353743cd09dSBastian Koppelmann set_flush_inputs_to_zero(1, &env->fp_status); 354743cd09dSBastian Koppelmann return result; 355743cd09dSBastian Koppelmann } 3560d4c3b80SBastian Koppelmann 3570d4c3b80SBastian Koppelmann uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg) 3580d4c3b80SBastian Koppelmann { 3590d4c3b80SBastian Koppelmann float32 f_arg = make_float32(arg); 3600d4c3b80SBastian Koppelmann int32_t result, flags; 3610d4c3b80SBastian Koppelmann 3620d4c3b80SBastian Koppelmann result = float32_to_int32(f_arg, &env->fp_status); 3630d4c3b80SBastian Koppelmann 3640d4c3b80SBastian Koppelmann flags = f_get_excp_flags(env); 3650d4c3b80SBastian Koppelmann if (flags) { 3660d4c3b80SBastian Koppelmann if (float32_is_any_nan(f_arg)) { 3670d4c3b80SBastian Koppelmann result = 0; 3680d4c3b80SBastian Koppelmann } 3690d4c3b80SBastian Koppelmann f_update_psw_flags(env, flags); 3700d4c3b80SBastian Koppelmann } else { 3710d4c3b80SBastian Koppelmann env->FPU_FS = 0; 3720d4c3b80SBastian Koppelmann } 3730d4c3b80SBastian Koppelmann return (uint32_t)result; 3740d4c3b80SBastian Koppelmann } 3750d4c3b80SBastian Koppelmann 3760d4c3b80SBastian Koppelmann uint32_t helper_itof(CPUTriCoreState *env, uint32_t arg) 3770d4c3b80SBastian Koppelmann { 3780d4c3b80SBastian Koppelmann float32 f_result; 3790d4c3b80SBastian Koppelmann uint32_t flags; 3800d4c3b80SBastian Koppelmann f_result = int32_to_float32(arg, &env->fp_status); 3810d4c3b80SBastian Koppelmann 3820d4c3b80SBastian Koppelmann flags = f_get_excp_flags(env); 3830d4c3b80SBastian Koppelmann if (flags) { 3840d4c3b80SBastian Koppelmann f_update_psw_flags(env, flags); 3850d4c3b80SBastian Koppelmann } else { 3860d4c3b80SBastian Koppelmann env->FPU_FS = 0; 3870d4c3b80SBastian Koppelmann } 3880d4c3b80SBastian Koppelmann return (uint32_t)f_result; 3890d4c3b80SBastian Koppelmann } 3908f75983dSBastian Koppelmann 3914e6fd2e3SDavid Brenken uint32_t helper_utof(CPUTriCoreState *env, uint32_t arg) 3924e6fd2e3SDavid Brenken { 3934e6fd2e3SDavid Brenken float32 f_result; 3944e6fd2e3SDavid Brenken uint32_t flags; 3954e6fd2e3SDavid Brenken 3964e6fd2e3SDavid Brenken f_result = uint32_to_float32(arg, &env->fp_status); 3974e6fd2e3SDavid Brenken 3984e6fd2e3SDavid Brenken flags = f_get_excp_flags(env); 3994e6fd2e3SDavid Brenken if (flags) { 4004e6fd2e3SDavid Brenken f_update_psw_flags(env, flags); 4014e6fd2e3SDavid Brenken } else { 4024e6fd2e3SDavid Brenken env->FPU_FS = 0; 4034e6fd2e3SDavid Brenken } 4044e6fd2e3SDavid Brenken return (uint32_t)f_result; 4054e6fd2e3SDavid Brenken } 4064e6fd2e3SDavid Brenken 4071fa79fb0SDavid Brenken uint32_t helper_ftoiz(CPUTriCoreState *env, uint32_t arg) 4081fa79fb0SDavid Brenken { 4091fa79fb0SDavid Brenken float32 f_arg = make_float32(arg); 4101fa79fb0SDavid Brenken uint32_t result; 4111fa79fb0SDavid Brenken int32_t flags; 4121fa79fb0SDavid Brenken 4131fa79fb0SDavid Brenken result = float32_to_int32_round_to_zero(f_arg, &env->fp_status); 4141fa79fb0SDavid Brenken 4151fa79fb0SDavid Brenken flags = f_get_excp_flags(env); 4161fa79fb0SDavid Brenken if (flags & float_flag_invalid) { 4171fa79fb0SDavid Brenken flags &= ~float_flag_inexact; 4181fa79fb0SDavid Brenken if (float32_is_any_nan(f_arg)) { 4191fa79fb0SDavid Brenken result = 0; 4201fa79fb0SDavid Brenken } 4211fa79fb0SDavid Brenken } 4221fa79fb0SDavid Brenken 4231fa79fb0SDavid Brenken if (flags) { 4241fa79fb0SDavid Brenken f_update_psw_flags(env, flags); 4251fa79fb0SDavid Brenken } else { 4261fa79fb0SDavid Brenken env->FPU_FS = 0; 4271fa79fb0SDavid Brenken } 4281fa79fb0SDavid Brenken 4291fa79fb0SDavid Brenken return result; 4301fa79fb0SDavid Brenken } 4311fa79fb0SDavid Brenken 4328f75983dSBastian Koppelmann uint32_t helper_ftouz(CPUTriCoreState *env, uint32_t arg) 4338f75983dSBastian Koppelmann { 4348f75983dSBastian Koppelmann float32 f_arg = make_float32(arg); 4358f75983dSBastian Koppelmann uint32_t result; 4368f75983dSBastian Koppelmann int32_t flags; 4378f75983dSBastian Koppelmann 4388f75983dSBastian Koppelmann result = float32_to_uint32_round_to_zero(f_arg, &env->fp_status); 4398f75983dSBastian Koppelmann 4408f75983dSBastian Koppelmann flags = f_get_excp_flags(env); 4418f75983dSBastian Koppelmann if (flags & float_flag_invalid) { 4428f75983dSBastian Koppelmann flags &= ~float_flag_inexact; 4438f75983dSBastian Koppelmann if (float32_is_any_nan(f_arg)) { 4448f75983dSBastian Koppelmann result = 0; 4458f75983dSBastian Koppelmann } 4468f75983dSBastian Koppelmann } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { 4478f75983dSBastian Koppelmann flags = float_flag_invalid; 4488f75983dSBastian Koppelmann result = 0; 4498f75983dSBastian Koppelmann } 4508f75983dSBastian Koppelmann 4518f75983dSBastian Koppelmann if (flags) { 4528f75983dSBastian Koppelmann f_update_psw_flags(env, flags); 4538f75983dSBastian Koppelmann } else { 4548f75983dSBastian Koppelmann env->FPU_FS = 0; 4558f75983dSBastian Koppelmann } 4568f75983dSBastian Koppelmann return result; 4578f75983dSBastian Koppelmann } 45850788a3fSBastian Koppelmann 45950788a3fSBastian Koppelmann void helper_updfl(CPUTriCoreState *env, uint32_t arg) 46050788a3fSBastian Koppelmann { 46150788a3fSBastian Koppelmann env->FPU_FS = extract32(arg, 7, 1) & extract32(arg, 15, 1); 46250788a3fSBastian Koppelmann env->FPU_FI = (extract32(arg, 6, 1) & extract32(arg, 14, 1)) << 31; 46350788a3fSBastian Koppelmann env->FPU_FV = (extract32(arg, 5, 1) & extract32(arg, 13, 1)) << 31; 46450788a3fSBastian Koppelmann env->FPU_FZ = (extract32(arg, 4, 1) & extract32(arg, 12, 1)) << 31; 46550788a3fSBastian Koppelmann env->FPU_FU = (extract32(arg, 3, 1) & extract32(arg, 11, 1)) << 31; 46650788a3fSBastian Koppelmann /* clear FX and RM */ 46750788a3fSBastian Koppelmann env->PSW &= ~(extract32(arg, 10, 1) << 26); 46850788a3fSBastian Koppelmann env->PSW |= (extract32(arg, 2, 1) & extract32(arg, 10, 1)) << 26; 46950788a3fSBastian Koppelmann 47050788a3fSBastian Koppelmann fpu_set_state(env); 47150788a3fSBastian Koppelmann } 472