xref: /qemu/target/tricore/fpu_helper.c (revision 8317ea0607a2d01b3cb6329aef1b8c8ca00471e1)
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