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 27996a729fSBastian Koppelmann #define DIV_NAN 0x7fc00008 28996a729fSBastian Koppelmann #define MUL_NAN 0x7fc00002 29996a729fSBastian Koppelmann #define FPU_FS PSW_USB_C 30996a729fSBastian Koppelmann #define FPU_FI PSW_USB_V 31996a729fSBastian Koppelmann #define FPU_FV PSW_USB_SV 32996a729fSBastian Koppelmann #define FPU_FZ PSW_USB_AV 33996a729fSBastian Koppelmann #define FPU_FU PSW_USB_SAV 34996a729fSBastian Koppelmann 35996a729fSBastian Koppelmann /* we don't care about input_denormal */ 36996a729fSBastian Koppelmann static inline uint8_t f_get_excp_flags(CPUTriCoreState *env) 37996a729fSBastian Koppelmann { 38996a729fSBastian Koppelmann return get_float_exception_flags(&env->fp_status) 39996a729fSBastian Koppelmann & (float_flag_invalid 40996a729fSBastian Koppelmann | float_flag_overflow 41996a729fSBastian Koppelmann | float_flag_underflow 42996a729fSBastian Koppelmann | float_flag_output_denormal 43996a729fSBastian Koppelmann | float_flag_divbyzero 44996a729fSBastian Koppelmann | float_flag_inexact); 45996a729fSBastian Koppelmann } 46996a729fSBastian Koppelmann 47ddd7feadSBastian Koppelmann static inline float32 f_maddsub_nan_result(float32 arg1, float32 arg2, 48ddd7feadSBastian Koppelmann float32 arg3, float32 result, 49ddd7feadSBastian Koppelmann uint32_t muladd_negate_c) 50ddd7feadSBastian Koppelmann { 51ddd7feadSBastian Koppelmann uint32_t aSign, bSign, cSign; 52ddd7feadSBastian Koppelmann uint32_t aExp, bExp, cExp; 53ddd7feadSBastian Koppelmann 54ddd7feadSBastian Koppelmann if (float32_is_any_nan(arg1) || float32_is_any_nan(arg2) || 55ddd7feadSBastian Koppelmann float32_is_any_nan(arg3)) { 56ddd7feadSBastian Koppelmann return QUIET_NAN; 57ddd7feadSBastian Koppelmann } else if (float32_is_infinity(arg1) && float32_is_zero(arg2)) { 58ddd7feadSBastian Koppelmann return MUL_NAN; 59ddd7feadSBastian Koppelmann } else if (float32_is_zero(arg1) && float32_is_infinity(arg2)) { 60ddd7feadSBastian Koppelmann return MUL_NAN; 61ddd7feadSBastian Koppelmann } else { 62ddd7feadSBastian Koppelmann aSign = arg1 >> 31; 63ddd7feadSBastian Koppelmann bSign = arg2 >> 31; 64ddd7feadSBastian Koppelmann cSign = arg3 >> 31; 65ddd7feadSBastian Koppelmann 66ddd7feadSBastian Koppelmann aExp = (arg1 >> 23) & 0xff; 67ddd7feadSBastian Koppelmann bExp = (arg2 >> 23) & 0xff; 68ddd7feadSBastian Koppelmann cExp = (arg3 >> 23) & 0xff; 69ddd7feadSBastian Koppelmann 70ddd7feadSBastian Koppelmann if (muladd_negate_c) { 71ddd7feadSBastian Koppelmann cSign ^= 1; 72ddd7feadSBastian Koppelmann } 73ddd7feadSBastian Koppelmann if (((aExp == 0xff) || (bExp == 0xff)) && (cExp == 0xff)) { 74ddd7feadSBastian Koppelmann if (aSign ^ bSign ^ cSign) { 75ddd7feadSBastian Koppelmann return ADD_NAN; 76ddd7feadSBastian Koppelmann } 77ddd7feadSBastian Koppelmann } 78ddd7feadSBastian Koppelmann } 79ddd7feadSBastian Koppelmann 80ddd7feadSBastian Koppelmann return result; 81ddd7feadSBastian Koppelmann } 82ddd7feadSBastian Koppelmann 83baf410dcSBastian Koppelmann static void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags) 84996a729fSBastian Koppelmann { 85996a729fSBastian Koppelmann uint8_t some_excp = 0; 86996a729fSBastian Koppelmann set_float_exception_flags(0, &env->fp_status); 87996a729fSBastian Koppelmann 88996a729fSBastian Koppelmann if (flags & float_flag_invalid) { 89996a729fSBastian Koppelmann env->FPU_FI = 1 << 31; 90996a729fSBastian Koppelmann some_excp = 1; 91996a729fSBastian Koppelmann } 92996a729fSBastian Koppelmann 93996a729fSBastian Koppelmann if (flags & float_flag_overflow) { 94996a729fSBastian Koppelmann env->FPU_FV = 1 << 31; 95996a729fSBastian Koppelmann some_excp = 1; 96996a729fSBastian Koppelmann } 97996a729fSBastian Koppelmann 98996a729fSBastian Koppelmann if (flags & float_flag_underflow || flags & float_flag_output_denormal) { 99996a729fSBastian Koppelmann env->FPU_FU = 1 << 31; 100996a729fSBastian Koppelmann some_excp = 1; 101996a729fSBastian Koppelmann } 102996a729fSBastian Koppelmann 103996a729fSBastian Koppelmann if (flags & float_flag_divbyzero) { 104996a729fSBastian Koppelmann env->FPU_FZ = 1 << 31; 105996a729fSBastian Koppelmann some_excp = 1; 106996a729fSBastian Koppelmann } 107996a729fSBastian Koppelmann 108996a729fSBastian Koppelmann if (flags & float_flag_inexact || flags & float_flag_output_denormal) { 109996a729fSBastian Koppelmann env->PSW |= 1 << 26; 110996a729fSBastian Koppelmann some_excp = 1; 111996a729fSBastian Koppelmann } 112996a729fSBastian Koppelmann 113996a729fSBastian Koppelmann env->FPU_FS = some_excp; 114996a729fSBastian Koppelmann } 115baf410dcSBastian Koppelmann 116baf410dcSBastian Koppelmann #define FADD_SUB(op) \ 117baf410dcSBastian Koppelmann uint32_t helper_f##op(CPUTriCoreState *env, uint32_t r1, uint32_t r2) \ 118baf410dcSBastian Koppelmann { \ 119baf410dcSBastian Koppelmann float32 arg1 = make_float32(r1); \ 120baf410dcSBastian Koppelmann float32 arg2 = make_float32(r2); \ 121baf410dcSBastian Koppelmann uint32_t flags; \ 122baf410dcSBastian Koppelmann float32 f_result; \ 123baf410dcSBastian Koppelmann \ 124baf410dcSBastian Koppelmann f_result = float32_##op(arg2, arg1, &env->fp_status); \ 125baf410dcSBastian Koppelmann flags = f_get_excp_flags(env); \ 126baf410dcSBastian Koppelmann if (flags) { \ 127baf410dcSBastian Koppelmann /* If the output is a NaN, but the inputs aren't, \ 128baf410dcSBastian Koppelmann we return a unique value. */ \ 129baf410dcSBastian Koppelmann if ((flags & float_flag_invalid) \ 130baf410dcSBastian Koppelmann && !float32_is_any_nan(arg1) \ 131baf410dcSBastian Koppelmann && !float32_is_any_nan(arg2)) { \ 132baf410dcSBastian Koppelmann f_result = ADD_NAN; \ 133baf410dcSBastian Koppelmann } \ 134baf410dcSBastian Koppelmann f_update_psw_flags(env, flags); \ 135baf410dcSBastian Koppelmann } else { \ 136baf410dcSBastian Koppelmann env->FPU_FS = 0; \ 137baf410dcSBastian Koppelmann } \ 138baf410dcSBastian Koppelmann return (uint32_t)f_result; \ 139baf410dcSBastian Koppelmann } 140baf410dcSBastian Koppelmann FADD_SUB(add) 141baf410dcSBastian Koppelmann FADD_SUB(sub) 142daab3f7fSBastian Koppelmann 143daab3f7fSBastian Koppelmann uint32_t helper_fmul(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 144daab3f7fSBastian Koppelmann { 145daab3f7fSBastian Koppelmann uint32_t flags; 146daab3f7fSBastian Koppelmann float32 arg1 = make_float32(r1); 147daab3f7fSBastian Koppelmann float32 arg2 = make_float32(r2); 148daab3f7fSBastian Koppelmann float32 f_result; 149daab3f7fSBastian Koppelmann 150daab3f7fSBastian Koppelmann f_result = float32_mul(arg1, arg2, &env->fp_status); 151daab3f7fSBastian Koppelmann 152daab3f7fSBastian Koppelmann flags = f_get_excp_flags(env); 153daab3f7fSBastian Koppelmann if (flags) { 154daab3f7fSBastian Koppelmann /* If the output is a NaN, but the inputs aren't, 155daab3f7fSBastian Koppelmann we return a unique value. */ 156daab3f7fSBastian Koppelmann if ((flags & float_flag_invalid) 157daab3f7fSBastian Koppelmann && !float32_is_any_nan(arg1) 158daab3f7fSBastian Koppelmann && !float32_is_any_nan(arg2)) { 159daab3f7fSBastian Koppelmann f_result = MUL_NAN; 160daab3f7fSBastian Koppelmann } 161daab3f7fSBastian Koppelmann f_update_psw_flags(env, flags); 162daab3f7fSBastian Koppelmann } else { 163daab3f7fSBastian Koppelmann env->FPU_FS = 0; 164daab3f7fSBastian Koppelmann } 165daab3f7fSBastian Koppelmann return (uint32_t)f_result; 166daab3f7fSBastian Koppelmann 167daab3f7fSBastian Koppelmann } 168446ee5b2SBastian Koppelmann 169446ee5b2SBastian Koppelmann uint32_t helper_fdiv(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 170446ee5b2SBastian Koppelmann { 171446ee5b2SBastian Koppelmann uint32_t flags; 172446ee5b2SBastian Koppelmann float32 arg1 = make_float32(r1); 173446ee5b2SBastian Koppelmann float32 arg2 = make_float32(r2); 174446ee5b2SBastian Koppelmann float32 f_result; 175446ee5b2SBastian Koppelmann 176446ee5b2SBastian Koppelmann f_result = float32_div(arg1, arg2 , &env->fp_status); 177446ee5b2SBastian Koppelmann 178446ee5b2SBastian Koppelmann flags = f_get_excp_flags(env); 179446ee5b2SBastian Koppelmann if (flags) { 180446ee5b2SBastian Koppelmann /* If the output is a NaN, but the inputs aren't, 181446ee5b2SBastian Koppelmann we return a unique value. */ 182446ee5b2SBastian Koppelmann if ((flags & float_flag_invalid) 183446ee5b2SBastian Koppelmann && !float32_is_any_nan(arg1) 184446ee5b2SBastian Koppelmann && !float32_is_any_nan(arg2)) { 185446ee5b2SBastian Koppelmann f_result = DIV_NAN; 186446ee5b2SBastian Koppelmann } 187446ee5b2SBastian Koppelmann f_update_psw_flags(env, flags); 188446ee5b2SBastian Koppelmann } else { 189446ee5b2SBastian Koppelmann env->FPU_FS = 0; 190446ee5b2SBastian Koppelmann } 191446ee5b2SBastian Koppelmann 192446ee5b2SBastian Koppelmann return (uint32_t)f_result; 193446ee5b2SBastian Koppelmann } 194743cd09dSBastian Koppelmann 195ddd7feadSBastian Koppelmann uint32_t helper_fmadd(CPUTriCoreState *env, uint32_t r1, 196ddd7feadSBastian Koppelmann uint32_t r2, uint32_t r3) 197ddd7feadSBastian Koppelmann { 198ddd7feadSBastian Koppelmann uint32_t flags; 199ddd7feadSBastian Koppelmann float32 arg1 = make_float32(r1); 200ddd7feadSBastian Koppelmann float32 arg2 = make_float32(r2); 201ddd7feadSBastian Koppelmann float32 arg3 = make_float32(r3); 202ddd7feadSBastian Koppelmann float32 f_result; 203ddd7feadSBastian Koppelmann 204ddd7feadSBastian Koppelmann f_result = float32_muladd(arg1, arg2, arg3, 0, &env->fp_status); 205ddd7feadSBastian Koppelmann 206ddd7feadSBastian Koppelmann flags = f_get_excp_flags(env); 207ddd7feadSBastian Koppelmann if (flags) { 208ddd7feadSBastian Koppelmann if (flags & float_flag_invalid) { 209ddd7feadSBastian Koppelmann arg1 = float32_squash_input_denormal(arg1, &env->fp_status); 210ddd7feadSBastian Koppelmann arg2 = float32_squash_input_denormal(arg2, &env->fp_status); 211ddd7feadSBastian Koppelmann arg3 = float32_squash_input_denormal(arg3, &env->fp_status); 212ddd7feadSBastian Koppelmann f_result = f_maddsub_nan_result(arg1, arg2, arg3, f_result, 0); 213ddd7feadSBastian Koppelmann } 214ddd7feadSBastian Koppelmann f_update_psw_flags(env, flags); 215ddd7feadSBastian Koppelmann } else { 216ddd7feadSBastian Koppelmann env->FPU_FS = 0; 217ddd7feadSBastian Koppelmann } 218ddd7feadSBastian Koppelmann return (uint32_t)f_result; 219ddd7feadSBastian Koppelmann } 220ddd7feadSBastian Koppelmann 221ddd7feadSBastian Koppelmann uint32_t helper_fmsub(CPUTriCoreState *env, uint32_t r1, 222ddd7feadSBastian Koppelmann uint32_t r2, uint32_t r3) 223ddd7feadSBastian Koppelmann { 224ddd7feadSBastian Koppelmann uint32_t flags; 225ddd7feadSBastian Koppelmann float32 arg1 = make_float32(r1); 226ddd7feadSBastian Koppelmann float32 arg2 = make_float32(r2); 227ddd7feadSBastian Koppelmann float32 arg3 = make_float32(r3); 228ddd7feadSBastian Koppelmann float32 f_result; 229ddd7feadSBastian Koppelmann 230ddd7feadSBastian Koppelmann f_result = float32_muladd(arg1, arg2, arg3, float_muladd_negate_product, 231ddd7feadSBastian Koppelmann &env->fp_status); 232ddd7feadSBastian Koppelmann 233ddd7feadSBastian Koppelmann flags = f_get_excp_flags(env); 234ddd7feadSBastian Koppelmann if (flags) { 235ddd7feadSBastian Koppelmann if (flags & float_flag_invalid) { 236ddd7feadSBastian Koppelmann arg1 = float32_squash_input_denormal(arg1, &env->fp_status); 237ddd7feadSBastian Koppelmann arg2 = float32_squash_input_denormal(arg2, &env->fp_status); 238ddd7feadSBastian Koppelmann arg3 = float32_squash_input_denormal(arg3, &env->fp_status); 239ddd7feadSBastian Koppelmann 240ddd7feadSBastian Koppelmann f_result = f_maddsub_nan_result(arg1, arg2, arg3, f_result, 1); 241ddd7feadSBastian Koppelmann } 242ddd7feadSBastian Koppelmann f_update_psw_flags(env, flags); 243ddd7feadSBastian Koppelmann } else { 244ddd7feadSBastian Koppelmann env->FPU_FS = 0; 245ddd7feadSBastian Koppelmann } 246ddd7feadSBastian Koppelmann return (uint32_t)f_result; 247ddd7feadSBastian Koppelmann } 248ddd7feadSBastian Koppelmann 249743cd09dSBastian Koppelmann uint32_t helper_fcmp(CPUTriCoreState *env, uint32_t r1, uint32_t r2) 250743cd09dSBastian Koppelmann { 251743cd09dSBastian Koppelmann uint32_t result, flags; 252743cd09dSBastian Koppelmann float32 arg1 = make_float32(r1); 253743cd09dSBastian Koppelmann float32 arg2 = make_float32(r2); 254743cd09dSBastian Koppelmann 255743cd09dSBastian Koppelmann set_flush_inputs_to_zero(0, &env->fp_status); 256743cd09dSBastian Koppelmann 257743cd09dSBastian Koppelmann result = 1 << (float32_compare_quiet(arg1, arg2, &env->fp_status) + 1); 258b8c54700SEmilio G. Cota result |= float32_is_denormal(arg1) << 4; 259b8c54700SEmilio G. Cota result |= float32_is_denormal(arg2) << 5; 260743cd09dSBastian Koppelmann 261743cd09dSBastian Koppelmann flags = f_get_excp_flags(env); 262743cd09dSBastian Koppelmann if (flags) { 263743cd09dSBastian Koppelmann f_update_psw_flags(env, flags); 264743cd09dSBastian Koppelmann } else { 265743cd09dSBastian Koppelmann env->FPU_FS = 0; 266743cd09dSBastian Koppelmann } 267743cd09dSBastian Koppelmann 268743cd09dSBastian Koppelmann set_flush_inputs_to_zero(1, &env->fp_status); 269743cd09dSBastian Koppelmann return result; 270743cd09dSBastian Koppelmann } 2710d4c3b80SBastian Koppelmann 2720d4c3b80SBastian Koppelmann uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg) 2730d4c3b80SBastian Koppelmann { 2740d4c3b80SBastian Koppelmann float32 f_arg = make_float32(arg); 2750d4c3b80SBastian Koppelmann int32_t result, flags; 2760d4c3b80SBastian Koppelmann 2770d4c3b80SBastian Koppelmann result = float32_to_int32(f_arg, &env->fp_status); 2780d4c3b80SBastian Koppelmann 2790d4c3b80SBastian Koppelmann flags = f_get_excp_flags(env); 2800d4c3b80SBastian Koppelmann if (flags) { 2810d4c3b80SBastian Koppelmann if (float32_is_any_nan(f_arg)) { 2820d4c3b80SBastian Koppelmann result = 0; 2830d4c3b80SBastian Koppelmann } 2840d4c3b80SBastian Koppelmann f_update_psw_flags(env, flags); 2850d4c3b80SBastian Koppelmann } else { 2860d4c3b80SBastian Koppelmann env->FPU_FS = 0; 2870d4c3b80SBastian Koppelmann } 2880d4c3b80SBastian Koppelmann return (uint32_t)result; 2890d4c3b80SBastian Koppelmann } 2900d4c3b80SBastian Koppelmann 2910d4c3b80SBastian Koppelmann uint32_t helper_itof(CPUTriCoreState *env, uint32_t arg) 2920d4c3b80SBastian Koppelmann { 2930d4c3b80SBastian Koppelmann float32 f_result; 2940d4c3b80SBastian Koppelmann uint32_t flags; 2950d4c3b80SBastian Koppelmann f_result = int32_to_float32(arg, &env->fp_status); 2960d4c3b80SBastian Koppelmann 2970d4c3b80SBastian Koppelmann flags = f_get_excp_flags(env); 2980d4c3b80SBastian Koppelmann if (flags) { 2990d4c3b80SBastian Koppelmann f_update_psw_flags(env, flags); 3000d4c3b80SBastian Koppelmann } else { 3010d4c3b80SBastian Koppelmann env->FPU_FS = 0; 3020d4c3b80SBastian Koppelmann } 3030d4c3b80SBastian Koppelmann return (uint32_t)f_result; 3040d4c3b80SBastian Koppelmann } 3058f75983dSBastian Koppelmann 306*1fa79fb0SDavid Brenken uint32_t helper_ftoiz(CPUTriCoreState *env, uint32_t arg) 307*1fa79fb0SDavid Brenken { 308*1fa79fb0SDavid Brenken float32 f_arg = make_float32(arg); 309*1fa79fb0SDavid Brenken uint32_t result; 310*1fa79fb0SDavid Brenken int32_t flags; 311*1fa79fb0SDavid Brenken 312*1fa79fb0SDavid Brenken result = float32_to_int32_round_to_zero(f_arg, &env->fp_status); 313*1fa79fb0SDavid Brenken 314*1fa79fb0SDavid Brenken flags = f_get_excp_flags(env); 315*1fa79fb0SDavid Brenken if (flags & float_flag_invalid) { 316*1fa79fb0SDavid Brenken flags &= ~float_flag_inexact; 317*1fa79fb0SDavid Brenken if (float32_is_any_nan(f_arg)) { 318*1fa79fb0SDavid Brenken result = 0; 319*1fa79fb0SDavid Brenken } 320*1fa79fb0SDavid Brenken } 321*1fa79fb0SDavid Brenken 322*1fa79fb0SDavid Brenken if (flags) { 323*1fa79fb0SDavid Brenken f_update_psw_flags(env, flags); 324*1fa79fb0SDavid Brenken } else { 325*1fa79fb0SDavid Brenken env->FPU_FS = 0; 326*1fa79fb0SDavid Brenken } 327*1fa79fb0SDavid Brenken 328*1fa79fb0SDavid Brenken return result; 329*1fa79fb0SDavid Brenken } 330*1fa79fb0SDavid Brenken 3318f75983dSBastian Koppelmann uint32_t helper_ftouz(CPUTriCoreState *env, uint32_t arg) 3328f75983dSBastian Koppelmann { 3338f75983dSBastian Koppelmann float32 f_arg = make_float32(arg); 3348f75983dSBastian Koppelmann uint32_t result; 3358f75983dSBastian Koppelmann int32_t flags; 3368f75983dSBastian Koppelmann 3378f75983dSBastian Koppelmann result = float32_to_uint32_round_to_zero(f_arg, &env->fp_status); 3388f75983dSBastian Koppelmann 3398f75983dSBastian Koppelmann flags = f_get_excp_flags(env); 3408f75983dSBastian Koppelmann if (flags & float_flag_invalid) { 3418f75983dSBastian Koppelmann flags &= ~float_flag_inexact; 3428f75983dSBastian Koppelmann if (float32_is_any_nan(f_arg)) { 3438f75983dSBastian Koppelmann result = 0; 3448f75983dSBastian Koppelmann } 3458f75983dSBastian Koppelmann } else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) { 3468f75983dSBastian Koppelmann flags = float_flag_invalid; 3478f75983dSBastian Koppelmann result = 0; 3488f75983dSBastian Koppelmann } 3498f75983dSBastian Koppelmann 3508f75983dSBastian Koppelmann if (flags) { 3518f75983dSBastian Koppelmann f_update_psw_flags(env, flags); 3528f75983dSBastian Koppelmann } else { 3538f75983dSBastian Koppelmann env->FPU_FS = 0; 3548f75983dSBastian Koppelmann } 3558f75983dSBastian Koppelmann return result; 3568f75983dSBastian Koppelmann } 35750788a3fSBastian Koppelmann 35850788a3fSBastian Koppelmann void helper_updfl(CPUTriCoreState *env, uint32_t arg) 35950788a3fSBastian Koppelmann { 36050788a3fSBastian Koppelmann env->FPU_FS = extract32(arg, 7, 1) & extract32(arg, 15, 1); 36150788a3fSBastian Koppelmann env->FPU_FI = (extract32(arg, 6, 1) & extract32(arg, 14, 1)) << 31; 36250788a3fSBastian Koppelmann env->FPU_FV = (extract32(arg, 5, 1) & extract32(arg, 13, 1)) << 31; 36350788a3fSBastian Koppelmann env->FPU_FZ = (extract32(arg, 4, 1) & extract32(arg, 12, 1)) << 31; 36450788a3fSBastian Koppelmann env->FPU_FU = (extract32(arg, 3, 1) & extract32(arg, 11, 1)) << 31; 36550788a3fSBastian Koppelmann /* clear FX and RM */ 36650788a3fSBastian Koppelmann env->PSW &= ~(extract32(arg, 10, 1) << 26); 36750788a3fSBastian Koppelmann env->PSW |= (extract32(arg, 2, 1) & extract32(arg, 10, 1)) << 26; 36850788a3fSBastian Koppelmann 36950788a3fSBastian Koppelmann fpu_set_state(env); 37050788a3fSBastian Koppelmann } 371