xref: /qemu/target/ppc/fpu_helper.c (revision 7cef6d686309e2792186504ae17cf4f3eb57ef68)
1 /*
2  *  PowerPC floating point and SPE emulation helpers for QEMU.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include "qemu/osdep.h"
20 #include "cpu.h"
21 #include "exec/helper-proto.h"
22 #include "internal.h"
23 #include "fpu/softfloat.h"
24 
float128_snan_to_qnan(float128 x)25 static inline float128 float128_snan_to_qnan(float128 x)
26 {
27     float128 r;
28 
29     r.high = x.high | 0x0000800000000000;
30     r.low = x.low;
31     return r;
32 }
33 
34 #define float64_snan_to_qnan(x) ((x) | 0x0008000000000000ULL)
35 #define float32_snan_to_qnan(x) ((x) | 0x00400000)
36 #define float16_snan_to_qnan(x) ((x) | 0x0200)
37 
bfp32_neg(float32 a)38 static inline float32 bfp32_neg(float32 a)
39 {
40     if (unlikely(float32_is_any_nan(a))) {
41         return a;
42     } else {
43         return float32_chs(a);
44     }
45 }
46 
fp_exceptions_enabled(CPUPPCState * env)47 static inline bool fp_exceptions_enabled(CPUPPCState *env)
48 {
49 #ifdef CONFIG_USER_ONLY
50     return true;
51 #else
52     return (env->msr & ((1U << MSR_FE0) | (1U << MSR_FE1))) != 0;
53 #endif
54 }
55 
56 /*****************************************************************************/
57 /* Floating point operations helpers */
58 
59 /*
60  * This is the non-arithmatic conversion that happens e.g. on loads.
61  * In the Power ISA pseudocode, this is called DOUBLE.
62  */
helper_todouble(uint32_t arg)63 uint64_t helper_todouble(uint32_t arg)
64 {
65     uint32_t abs_arg = arg & 0x7fffffff;
66     uint64_t ret;
67 
68     if (likely(abs_arg >= 0x00800000)) {
69         if (unlikely(extract32(arg, 23, 8) == 0xff)) {
70             /* Inf or NAN.  */
71             ret  = (uint64_t)extract32(arg, 31, 1) << 63;
72             ret |= (uint64_t)0x7ff << 52;
73             ret |= (uint64_t)extract32(arg, 0, 23) << 29;
74         } else {
75             /* Normalized operand.  */
76             ret  = (uint64_t)extract32(arg, 30, 2) << 62;
77             ret |= ((extract32(arg, 30, 1) ^ 1) * (uint64_t)7) << 59;
78             ret |= (uint64_t)extract32(arg, 0, 30) << 29;
79         }
80     } else {
81         /* Zero or Denormalized operand.  */
82         ret = (uint64_t)extract32(arg, 31, 1) << 63;
83         if (unlikely(abs_arg != 0)) {
84             /*
85              * Denormalized operand.
86              * Shift fraction so that the msb is in the implicit bit position.
87              * Thus, shift is in the range [1:23].
88              */
89             int shift = clz32(abs_arg) - 8;
90             /*
91              * The first 3 terms compute the float64 exponent.  We then bias
92              * this result by -1 so that we can swallow the implicit bit below.
93              */
94             int exp = -126 - shift + 1023 - 1;
95 
96             ret |= (uint64_t)exp << 52;
97             ret += (uint64_t)abs_arg << (52 - 23 + shift);
98         }
99     }
100     return ret;
101 }
102 
103 /*
104  * This is the non-arithmatic conversion that happens e.g. on stores.
105  * In the Power ISA pseudocode, this is called SINGLE.
106  */
helper_tosingle(uint64_t arg)107 uint32_t helper_tosingle(uint64_t arg)
108 {
109     int exp = extract64(arg, 52, 11);
110     uint32_t ret;
111 
112     if (likely(exp > 896)) {
113         /* No denormalization required (includes Inf, NaN).  */
114         ret  = extract64(arg, 62, 2) << 30;
115         ret |= extract64(arg, 29, 30);
116     } else {
117         /*
118          * Zero or Denormal result.  If the exponent is in bounds for
119          * a single-precision denormal result, extract the proper
120          * bits.  If the input is not zero, and the exponent is out of
121          * bounds, then the result is undefined; this underflows to
122          * zero.
123          */
124         ret = extract64(arg, 63, 1) << 31;
125         if (unlikely(exp >= 874)) {
126             /* Denormal result.  */
127             ret |= ((1ULL << 52) | extract64(arg, 0, 52)) >> (896 + 30 - exp);
128         }
129     }
130     return ret;
131 }
132 
ppc_float32_get_unbiased_exp(float32 f)133 static inline int ppc_float32_get_unbiased_exp(float32 f)
134 {
135     return ((f >> 23) & 0xFF) - 127;
136 }
137 
ppc_float64_get_unbiased_exp(float64 f)138 static inline int ppc_float64_get_unbiased_exp(float64 f)
139 {
140     return ((f >> 52) & 0x7FF) - 1023;
141 }
142 
143 #define COMPUTE_FPRF(tp)                                          \
144 void helper_compute_fprf_##tp(CPUPPCState *env, tp arg)           \
145 {                                                                 \
146     bool neg = tp##_is_neg(arg);                                  \
147     target_ulong fprf;                                            \
148     if (likely(tp##_is_normal(arg))) {                            \
149         fprf = neg ? 0x08 << FPSCR_FPRF : 0x04 << FPSCR_FPRF;     \
150     } else if (tp##_is_zero(arg)) {                               \
151         fprf = neg ? 0x12 << FPSCR_FPRF : 0x02 << FPSCR_FPRF;     \
152     } else if (tp##_is_zero_or_denormal(arg)) {                   \
153         fprf = neg ? 0x18 << FPSCR_FPRF : 0x14 << FPSCR_FPRF;     \
154     } else if (tp##_is_infinity(arg)) {                           \
155         fprf = neg ? 0x09 << FPSCR_FPRF : 0x05 << FPSCR_FPRF;     \
156     } else {                                                      \
157         if (tp##_is_signaling_nan(arg, &env->fp_status)) {        \
158             fprf = 0x00 << FPSCR_FPRF;                            \
159         } else {                                                  \
160             fprf = 0x11 << FPSCR_FPRF;                            \
161         }                                                         \
162     }                                                             \
163     env->fpscr = (env->fpscr & ~FP_FPRF) | fprf;                  \
164 }
165 
166 COMPUTE_FPRF(float16)
COMPUTE_FPRF(float32)167 COMPUTE_FPRF(float32)
168 COMPUTE_FPRF(float64)
169 COMPUTE_FPRF(float128)
170 
171 /* Floating-point invalid operations exception */
172 static void finish_invalid_op_excp(CPUPPCState *env, int op, uintptr_t retaddr)
173 {
174     /* Update the floating-point invalid operation summary */
175     env->fpscr |= FP_VX;
176     /* Update the floating-point exception summary */
177     env->fpscr |= FP_FX;
178     if (env->fpscr & FP_VE) {
179         /* Update the floating-point enabled exception summary */
180         env->fpscr |= FP_FEX;
181         if (fp_exceptions_enabled(env)) {
182             raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
183                                    POWERPC_EXCP_FP | op, retaddr);
184         }
185     }
186 }
187 
finish_invalid_op_arith(CPUPPCState * env,int op,bool set_fpcc,uintptr_t retaddr)188 static void finish_invalid_op_arith(CPUPPCState *env, int op,
189                                     bool set_fpcc, uintptr_t retaddr)
190 {
191     env->fpscr &= ~(FP_FR | FP_FI);
192     if (!(env->fpscr & FP_VE)) {
193         if (set_fpcc) {
194             env->fpscr &= ~FP_FPCC;
195             env->fpscr |= (FP_C | FP_FU);
196         }
197     }
198     finish_invalid_op_excp(env, op, retaddr);
199 }
200 
201 /* Signalling NaN */
float_invalid_op_vxsnan(CPUPPCState * env,uintptr_t retaddr)202 static void float_invalid_op_vxsnan(CPUPPCState *env, uintptr_t retaddr)
203 {
204     env->fpscr |= FP_VXSNAN;
205     finish_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, retaddr);
206 }
207 
208 /* Magnitude subtraction of infinities */
float_invalid_op_vxisi(CPUPPCState * env,bool set_fpcc,uintptr_t retaddr)209 static void float_invalid_op_vxisi(CPUPPCState *env, bool set_fpcc,
210                                    uintptr_t retaddr)
211 {
212     env->fpscr |= FP_VXISI;
213     finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXISI, set_fpcc, retaddr);
214 }
215 
216 /* Division of infinity by infinity */
float_invalid_op_vxidi(CPUPPCState * env,bool set_fpcc,uintptr_t retaddr)217 static void float_invalid_op_vxidi(CPUPPCState *env, bool set_fpcc,
218                                    uintptr_t retaddr)
219 {
220     env->fpscr |= FP_VXIDI;
221     finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXIDI, set_fpcc, retaddr);
222 }
223 
224 /* Division of zero by zero */
float_invalid_op_vxzdz(CPUPPCState * env,bool set_fpcc,uintptr_t retaddr)225 static void float_invalid_op_vxzdz(CPUPPCState *env, bool set_fpcc,
226                                    uintptr_t retaddr)
227 {
228     env->fpscr |= FP_VXZDZ;
229     finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXZDZ, set_fpcc, retaddr);
230 }
231 
232 /* Multiplication of zero by infinity */
float_invalid_op_vximz(CPUPPCState * env,bool set_fpcc,uintptr_t retaddr)233 static void float_invalid_op_vximz(CPUPPCState *env, bool set_fpcc,
234                                    uintptr_t retaddr)
235 {
236     env->fpscr |= FP_VXIMZ;
237     finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXIMZ, set_fpcc, retaddr);
238 }
239 
240 /* Square root of a negative number */
float_invalid_op_vxsqrt(CPUPPCState * env,bool set_fpcc,uintptr_t retaddr)241 static void float_invalid_op_vxsqrt(CPUPPCState *env, bool set_fpcc,
242                                     uintptr_t retaddr)
243 {
244     env->fpscr |= FP_VXSQRT;
245     finish_invalid_op_arith(env, POWERPC_EXCP_FP_VXSQRT, set_fpcc, retaddr);
246 }
247 
248 /* Ordered comparison of NaN */
float_invalid_op_vxvc(CPUPPCState * env,bool set_fpcc,uintptr_t retaddr)249 static void float_invalid_op_vxvc(CPUPPCState *env, bool set_fpcc,
250                                   uintptr_t retaddr)
251 {
252     env->fpscr |= FP_VXVC;
253     if (set_fpcc) {
254         env->fpscr &= ~FP_FPCC;
255         env->fpscr |= (FP_C | FP_FU);
256     }
257     /* Update the floating-point invalid operation summary */
258     env->fpscr |= FP_VX;
259     /* Update the floating-point exception summary */
260     env->fpscr |= FP_FX;
261     /* We must update the target FPR before raising the exception */
262     if (env->fpscr & FP_VE) {
263         CPUState *cs = env_cpu(env);
264 
265         cs->exception_index = POWERPC_EXCP_PROGRAM;
266         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
267         /* Update the floating-point enabled exception summary */
268         env->fpscr |= FP_FEX;
269         /* Exception is deferred */
270     }
271 }
272 
273 /* Invalid conversion */
float_invalid_op_vxcvi(CPUPPCState * env,bool set_fpcc,uintptr_t retaddr)274 static void float_invalid_op_vxcvi(CPUPPCState *env, bool set_fpcc,
275                                    uintptr_t retaddr)
276 {
277     env->fpscr |= FP_VXCVI;
278     env->fpscr &= ~(FP_FR | FP_FI);
279     if (!(env->fpscr & FP_VE)) {
280         if (set_fpcc) {
281             env->fpscr &= ~FP_FPCC;
282             env->fpscr |= (FP_C | FP_FU);
283         }
284     }
285     finish_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, retaddr);
286 }
287 
float_zero_divide_excp(CPUPPCState * env,uintptr_t raddr)288 static inline void float_zero_divide_excp(CPUPPCState *env, uintptr_t raddr)
289 {
290     env->fpscr |= FP_ZX;
291     env->fpscr &= ~(FP_FR | FP_FI);
292     /* Update the floating-point exception summary */
293     env->fpscr |= FP_FX;
294     if (env->fpscr & FP_ZE) {
295         /* Update the floating-point enabled exception summary */
296         env->fpscr |= FP_FEX;
297         if (fp_exceptions_enabled(env)) {
298             raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
299                                    POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX,
300                                    raddr);
301         }
302     }
303 }
304 
float_overflow_excp(CPUPPCState * env)305 static inline int float_overflow_excp(CPUPPCState *env)
306 {
307     CPUState *cs = env_cpu(env);
308 
309     env->fpscr |= FP_OX;
310     /* Update the floating-point exception summary */
311     env->fpscr |= FP_FX;
312 
313     bool overflow_enabled = !!(env->fpscr & FP_OE);
314     if (overflow_enabled) {
315         /* Update the floating-point enabled exception summary */
316         env->fpscr |= FP_FEX;
317         /* We must update the target FPR before raising the exception */
318         cs->exception_index = POWERPC_EXCP_PROGRAM;
319         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
320     }
321 
322     return overflow_enabled ? 0 : float_flag_inexact;
323 }
324 
float_underflow_excp(CPUPPCState * env)325 static inline void float_underflow_excp(CPUPPCState *env)
326 {
327     CPUState *cs = env_cpu(env);
328 
329     env->fpscr |= FP_UX;
330     /* Update the floating-point exception summary */
331     env->fpscr |= FP_FX;
332     if (env->fpscr & FP_UE) {
333         /* Update the floating-point enabled exception summary */
334         env->fpscr |= FP_FEX;
335         /* We must update the target FPR before raising the exception */
336         cs->exception_index = POWERPC_EXCP_PROGRAM;
337         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
338     }
339 }
340 
float_inexact_excp(CPUPPCState * env)341 static inline void float_inexact_excp(CPUPPCState *env)
342 {
343     CPUState *cs = env_cpu(env);
344 
345     env->fpscr |= FP_XX;
346     /* Update the floating-point exception summary */
347     env->fpscr |= FP_FX;
348     if (env->fpscr & FP_XE) {
349         /* Update the floating-point enabled exception summary */
350         env->fpscr |= FP_FEX;
351         /* We must update the target FPR before raising the exception */
352         cs->exception_index = POWERPC_EXCP_PROGRAM;
353         env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
354     }
355 }
356 
helper_fpscr_clrbit(CPUPPCState * env,uint32_t bit)357 void helper_fpscr_clrbit(CPUPPCState *env, uint32_t bit)
358 {
359     uint32_t mask = 1u << bit;
360     if (env->fpscr & mask) {
361         ppc_store_fpscr(env, env->fpscr & ~(target_ulong)mask);
362     }
363 }
364 
helper_fpscr_setbit(CPUPPCState * env,uint32_t bit)365 void helper_fpscr_setbit(CPUPPCState *env, uint32_t bit)
366 {
367     uint32_t mask = 1u << bit;
368     if (!(env->fpscr & mask)) {
369         ppc_store_fpscr(env, env->fpscr | mask);
370     }
371 }
372 
helper_store_fpscr(CPUPPCState * env,uint64_t val,uint32_t nibbles)373 void helper_store_fpscr(CPUPPCState *env, uint64_t val, uint32_t nibbles)
374 {
375     target_ulong mask = 0;
376     int i;
377 
378     /* TODO: push this extension back to translation time */
379     for (i = 0; i < sizeof(target_ulong) * 2; i++) {
380         if (nibbles & (1 << i)) {
381             mask |= (target_ulong) 0xf << (4 * i);
382         }
383     }
384     val = (val & mask) | (env->fpscr & ~mask);
385     ppc_store_fpscr(env, val);
386 }
387 
do_fpscr_check_status(CPUPPCState * env,uintptr_t raddr)388 static void do_fpscr_check_status(CPUPPCState *env, uintptr_t raddr)
389 {
390     CPUState *cs = env_cpu(env);
391     target_ulong fpscr = env->fpscr;
392     int error = 0;
393 
394     if ((fpscr & FP_OX) && (fpscr & FP_OE)) {
395         error = POWERPC_EXCP_FP_OX;
396     } else if ((fpscr & FP_UX) && (fpscr & FP_UE)) {
397         error = POWERPC_EXCP_FP_UX;
398     } else if ((fpscr & FP_XX) && (fpscr & FP_XE)) {
399         error = POWERPC_EXCP_FP_XX;
400     } else if ((fpscr & FP_ZX) && (fpscr & FP_ZE)) {
401         error = POWERPC_EXCP_FP_ZX;
402     } else if (fpscr & FP_VE) {
403         if (fpscr & FP_VXSOFT) {
404             error = POWERPC_EXCP_FP_VXSOFT;
405         } else if (fpscr & FP_VXSNAN) {
406             error = POWERPC_EXCP_FP_VXSNAN;
407         } else if (fpscr & FP_VXISI) {
408             error = POWERPC_EXCP_FP_VXISI;
409         } else if (fpscr & FP_VXIDI) {
410             error = POWERPC_EXCP_FP_VXIDI;
411         } else if (fpscr & FP_VXZDZ) {
412             error = POWERPC_EXCP_FP_VXZDZ;
413         } else if (fpscr & FP_VXIMZ) {
414             error = POWERPC_EXCP_FP_VXIMZ;
415         } else if (fpscr & FP_VXVC) {
416             error = POWERPC_EXCP_FP_VXVC;
417         } else if (fpscr & FP_VXSQRT) {
418             error = POWERPC_EXCP_FP_VXSQRT;
419         } else if (fpscr & FP_VXCVI) {
420             error = POWERPC_EXCP_FP_VXCVI;
421         } else {
422             return;
423         }
424     } else {
425         return;
426     }
427     cs->exception_index = POWERPC_EXCP_PROGRAM;
428     env->error_code = error | POWERPC_EXCP_FP;
429     env->fpscr |= FP_FEX;
430     /* Deferred floating-point exception after target FPSCR update */
431     if (fp_exceptions_enabled(env)) {
432         raise_exception_err_ra(env, cs->exception_index,
433                                env->error_code, raddr);
434     }
435 }
436 
helper_fpscr_check_status(CPUPPCState * env)437 void helper_fpscr_check_status(CPUPPCState *env)
438 {
439     do_fpscr_check_status(env, GETPC());
440 }
441 
do_float_check_status(CPUPPCState * env,bool change_fi,uintptr_t raddr)442 static void do_float_check_status(CPUPPCState *env, bool change_fi,
443                                   uintptr_t raddr)
444 {
445     CPUState *cs = env_cpu(env);
446     int status = get_float_exception_flags(&env->fp_status);
447 
448     if (status & float_flag_overflow) {
449         status |= float_overflow_excp(env);
450     } else if (status & float_flag_underflow) {
451         float_underflow_excp(env);
452     }
453     if (status & float_flag_inexact) {
454         float_inexact_excp(env);
455     }
456     if (change_fi) {
457         env->fpscr = FIELD_DP64(env->fpscr, FPSCR, FI,
458                                 !!(status & float_flag_inexact));
459     }
460 
461     if (cs->exception_index == POWERPC_EXCP_PROGRAM &&
462         (env->error_code & POWERPC_EXCP_FP)) {
463         /* Deferred floating-point exception after target FPR update */
464         if (fp_exceptions_enabled(env)) {
465             raise_exception_err_ra(env, cs->exception_index,
466                                    env->error_code, raddr);
467         }
468     }
469 }
470 
helper_float_check_status(CPUPPCState * env)471 void helper_float_check_status(CPUPPCState *env)
472 {
473     do_float_check_status(env, true, GETPC());
474 }
475 
helper_reset_fpstatus(CPUPPCState * env)476 void helper_reset_fpstatus(CPUPPCState *env)
477 {
478     set_float_exception_flags(0, &env->fp_status);
479 }
480 
float_invalid_op_addsub(CPUPPCState * env,int flags,bool set_fpcc,uintptr_t retaddr)481 static void float_invalid_op_addsub(CPUPPCState *env, int flags,
482                                     bool set_fpcc, uintptr_t retaddr)
483 {
484     if (flags & float_flag_invalid_isi) {
485         float_invalid_op_vxisi(env, set_fpcc, retaddr);
486     } else if (flags & float_flag_invalid_snan) {
487         float_invalid_op_vxsnan(env, retaddr);
488     }
489 }
490 
addsub_flags_handler(CPUPPCState * env,int flags,uintptr_t ra)491 static inline void addsub_flags_handler(CPUPPCState *env, int flags,
492                                         uintptr_t ra)
493 {
494     if (unlikely(flags & float_flag_invalid)) {
495         float_invalid_op_addsub(env, flags, 1, ra);
496     }
497 }
498 
float_invalid_op_mul(CPUPPCState * env,int flags,bool set_fprc,uintptr_t retaddr)499 static void float_invalid_op_mul(CPUPPCState *env, int flags,
500                                  bool set_fprc, uintptr_t retaddr)
501 {
502     if (flags & float_flag_invalid_imz) {
503         float_invalid_op_vximz(env, set_fprc, retaddr);
504     } else if (flags & float_flag_invalid_snan) {
505         float_invalid_op_vxsnan(env, retaddr);
506     }
507 }
508 
mul_flags_handler(CPUPPCState * env,int flags,uintptr_t ra)509 static inline void mul_flags_handler(CPUPPCState *env, int flags, uintptr_t ra)
510 {
511     if (unlikely(flags & float_flag_invalid)) {
512         float_invalid_op_mul(env, flags, 1, ra);
513     }
514 }
515 
float_invalid_op_div(CPUPPCState * env,int flags,bool set_fprc,uintptr_t retaddr)516 static void float_invalid_op_div(CPUPPCState *env, int flags,
517                                  bool set_fprc, uintptr_t retaddr)
518 {
519     if (flags & float_flag_invalid_idi) {
520         float_invalid_op_vxidi(env, set_fprc, retaddr);
521     } else if (flags & float_flag_invalid_zdz) {
522         float_invalid_op_vxzdz(env, set_fprc, retaddr);
523     } else if (flags & float_flag_invalid_snan) {
524         float_invalid_op_vxsnan(env, retaddr);
525     }
526 }
527 
div_flags_handler(CPUPPCState * env,int flags,uintptr_t ra)528 static inline void div_flags_handler(CPUPPCState *env, int flags, uintptr_t ra)
529 {
530     if (unlikely(flags & float_flag_invalid)) {
531         float_invalid_op_div(env, flags, 1, ra);
532     }
533     if (unlikely(flags & float_flag_divbyzero)) {
534         float_zero_divide_excp(env, ra);
535     }
536 }
537 
float_invalid_cvt(CPUPPCState * env,int flags,uint64_t ret,uint64_t ret_nan,bool set_fprc,uintptr_t retaddr)538 static uint64_t float_invalid_cvt(CPUPPCState *env, int flags,
539                                   uint64_t ret, uint64_t ret_nan,
540                                   bool set_fprc, uintptr_t retaddr)
541 {
542     /*
543      * VXCVI is different from most in that it sets two exception bits,
544      * VXCVI and VXSNAN for an SNaN input.
545      */
546     if (flags & float_flag_invalid_snan) {
547         env->fpscr |= FP_VXSNAN;
548     }
549     float_invalid_op_vxcvi(env, set_fprc, retaddr);
550 
551     return flags & float_flag_invalid_cvti ? ret : ret_nan;
552 }
553 
554 #define FPU_FCTI(op, cvt, nanval)                                      \
555 uint64_t helper_##op(CPUPPCState *env, float64 arg)                    \
556 {                                                                      \
557     uint64_t ret = float64_to_##cvt(arg, &env->fp_status);             \
558     int flags = get_float_exception_flags(&env->fp_status);            \
559     if (unlikely(flags & float_flag_invalid)) {                        \
560         ret = float_invalid_cvt(env, flags, ret, nanval, 1, GETPC());  \
561     }                                                                  \
562     return ret;                                                        \
563 }
564 
565 FPU_FCTI(fctiw, int32, 0x80000000U)
566 FPU_FCTI(fctiwz, int32_round_to_zero, 0x80000000U)
567 FPU_FCTI(fctiwu, uint32, 0x00000000U)
568 FPU_FCTI(fctiwuz, uint32_round_to_zero, 0x00000000U)
569 FPU_FCTI(fctid, int64, 0x8000000000000000ULL)
570 FPU_FCTI(fctidz, int64_round_to_zero, 0x8000000000000000ULL)
571 FPU_FCTI(fctidu, uint64, 0x0000000000000000ULL)
572 FPU_FCTI(fctiduz, uint64_round_to_zero, 0x0000000000000000ULL)
573 
574 #define FPU_FCFI(op, cvtr, is_single)                      \
575 uint64_t helper_##op(CPUPPCState *env, uint64_t arg)       \
576 {                                                          \
577     CPU_DoubleU farg;                                      \
578                                                            \
579     if (is_single) {                                       \
580         float32 tmp = cvtr(arg, &env->fp_status);          \
581         farg.d = float32_to_float64(tmp, &env->fp_status); \
582     } else {                                               \
583         farg.d = cvtr(arg, &env->fp_status);               \
584     }                                                      \
585     do_float_check_status(env, true, GETPC());             \
586     return farg.ll;                                        \
587 }
588 
589 FPU_FCFI(fcfid, int64_to_float64, 0)
590 FPU_FCFI(fcfids, int64_to_float32, 1)
591 FPU_FCFI(fcfidu, uint64_to_float64, 0)
592 FPU_FCFI(fcfidus, uint64_to_float32, 1)
593 
do_fri(CPUPPCState * env,uint64_t arg,FloatRoundMode rounding_mode)594 static uint64_t do_fri(CPUPPCState *env, uint64_t arg,
595                        FloatRoundMode rounding_mode)
596 {
597     FloatRoundMode old_rounding_mode = get_float_rounding_mode(&env->fp_status);
598     int flags;
599 
600     set_float_rounding_mode(rounding_mode, &env->fp_status);
601     arg = float64_round_to_int(arg, &env->fp_status);
602     set_float_rounding_mode(old_rounding_mode, &env->fp_status);
603 
604     flags = get_float_exception_flags(&env->fp_status);
605     if (flags & float_flag_invalid_snan) {
606         float_invalid_op_vxsnan(env, GETPC());
607     }
608 
609     /* fri* does not set FPSCR[XX] */
610     set_float_exception_flags(flags & ~float_flag_inexact, &env->fp_status);
611     do_float_check_status(env, true, GETPC());
612 
613     return arg;
614 }
615 
helper_frin(CPUPPCState * env,uint64_t arg)616 uint64_t helper_frin(CPUPPCState *env, uint64_t arg)
617 {
618     return do_fri(env, arg, float_round_ties_away);
619 }
620 
helper_friz(CPUPPCState * env,uint64_t arg)621 uint64_t helper_friz(CPUPPCState *env, uint64_t arg)
622 {
623     return do_fri(env, arg, float_round_to_zero);
624 }
625 
helper_frip(CPUPPCState * env,uint64_t arg)626 uint64_t helper_frip(CPUPPCState *env, uint64_t arg)
627 {
628     return do_fri(env, arg, float_round_up);
629 }
630 
helper_frim(CPUPPCState * env,uint64_t arg)631 uint64_t helper_frim(CPUPPCState *env, uint64_t arg)
632 {
633     return do_fri(env, arg, float_round_down);
634 }
635 
float_invalid_op_madd(CPUPPCState * env,int flags,bool set_fpcc,uintptr_t retaddr)636 static void float_invalid_op_madd(CPUPPCState *env, int flags,
637                                   bool set_fpcc, uintptr_t retaddr)
638 {
639     if (flags & float_flag_invalid_imz) {
640         float_invalid_op_vximz(env, set_fpcc, retaddr);
641     } else {
642         float_invalid_op_addsub(env, flags, set_fpcc, retaddr);
643     }
644 }
645 
do_fmadd(CPUPPCState * env,float64 a,float64 b,float64 c,int madd_flags,uintptr_t retaddr)646 static float64 do_fmadd(CPUPPCState *env, float64 a, float64 b,
647                          float64 c, int madd_flags, uintptr_t retaddr)
648 {
649     float64 ret = float64_muladd(a, b, c, madd_flags, &env->fp_status);
650     int flags = get_float_exception_flags(&env->fp_status);
651 
652     if (unlikely(flags & float_flag_invalid)) {
653         float_invalid_op_madd(env, flags, 1, retaddr);
654     }
655     return ret;
656 }
657 
do_fmadds(CPUPPCState * env,float64 a,float64 b,float64 c,int madd_flags,uintptr_t retaddr)658 static uint64_t do_fmadds(CPUPPCState *env, float64 a, float64 b,
659                           float64 c, int madd_flags, uintptr_t retaddr)
660 {
661     float64 ret = float64r32_muladd(a, b, c, madd_flags, &env->fp_status);
662     int flags = get_float_exception_flags(&env->fp_status);
663 
664     if (unlikely(flags & float_flag_invalid)) {
665         float_invalid_op_madd(env, flags, 1, retaddr);
666     }
667     return ret;
668 }
669 
670 #define FPU_FMADD(op, madd_flags)                                    \
671     uint64_t helper_##op(CPUPPCState *env, uint64_t arg1,            \
672                          uint64_t arg2, uint64_t arg3)               \
673     { return do_fmadd(env, arg1, arg2, arg3, madd_flags, GETPC()); } \
674     uint64_t helper_##op##S(CPUPPCState *env, uint64_t arg1,         \
675                          uint64_t arg2, uint64_t arg3)               \
676     { return do_fmadds(env, arg1, arg2, arg3, madd_flags, GETPC()); }
677 
678 #define MADD_FLGS 0
679 #define MSUB_FLGS float_muladd_negate_c
680 #define NMADD_FLGS float_muladd_negate_result
681 #define NMSUB_FLGS (float_muladd_negate_c | float_muladd_negate_result)
682 
FPU_FMADD(FMADD,MADD_FLGS)683 FPU_FMADD(FMADD, MADD_FLGS)
684 FPU_FMADD(FNMADD, NMADD_FLGS)
685 FPU_FMADD(FMSUB, MSUB_FLGS)
686 FPU_FMADD(FNMSUB, NMSUB_FLGS)
687 
688 /* frsp - frsp. */
689 static uint64_t do_frsp(CPUPPCState *env, uint64_t arg, uintptr_t retaddr)
690 {
691     float32 f32 = float64_to_float32(arg, &env->fp_status);
692     int flags = get_float_exception_flags(&env->fp_status);
693 
694     if (unlikely(flags & float_flag_invalid_snan)) {
695         float_invalid_op_vxsnan(env, retaddr);
696     }
697     return helper_todouble(f32);
698 }
699 
helper_frsp(CPUPPCState * env,uint64_t arg)700 uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
701 {
702     return do_frsp(env, arg, GETPC());
703 }
704 
float_invalid_op_sqrt(CPUPPCState * env,int flags,bool set_fpcc,uintptr_t retaddr)705 static void float_invalid_op_sqrt(CPUPPCState *env, int flags,
706                                   bool set_fpcc, uintptr_t retaddr)
707 {
708     if (unlikely(flags & float_flag_invalid_sqrt)) {
709         float_invalid_op_vxsqrt(env, set_fpcc, retaddr);
710     } else if (unlikely(flags & float_flag_invalid_snan)) {
711         float_invalid_op_vxsnan(env, retaddr);
712     }
713 }
714 
715 #define FPU_FSQRT(name, op)                                                   \
716 float64 helper_##name(CPUPPCState *env, float64 arg)                          \
717 {                                                                             \
718     float64 ret = op(arg, &env->fp_status);                                   \
719     int flags = get_float_exception_flags(&env->fp_status);                   \
720                                                                               \
721     if (unlikely(flags & float_flag_invalid)) {                               \
722         float_invalid_op_sqrt(env, flags, 1, GETPC());                        \
723     }                                                                         \
724                                                                               \
725     return ret;                                                               \
726 }
727 
FPU_FSQRT(FSQRT,float64_sqrt)728 FPU_FSQRT(FSQRT, float64_sqrt)
729 FPU_FSQRT(FSQRTS, float64r32_sqrt)
730 
731 #define FPU_FRE(name, op)                                                     \
732 float64 helper_##name(CPUPPCState *env, float64 arg)                          \
733 {                                                                             \
734     /* "Estimate" the reciprocal with actual division.  */                    \
735     float64 ret = op(float64_one, arg, &env->fp_status);                      \
736     int flags = get_float_exception_flags(&env->fp_status);                   \
737                                                                               \
738     if (unlikely(flags & float_flag_invalid_snan)) {                          \
739         float_invalid_op_vxsnan(env, GETPC());                                \
740     }                                                                         \
741     if (unlikely(flags & float_flag_divbyzero)) {                             \
742         float_zero_divide_excp(env, GETPC());                                 \
743         /* For FPSCR.ZE == 0, the result is 1/2.  */                          \
744         ret = float64_set_sign(float64_half, float64_is_neg(arg));            \
745     }                                                                         \
746                                                                               \
747     return ret;                                                               \
748 }
749 
750 #define FPU_FRSQRTE(name, op)                                                 \
751 float64 helper_##name(CPUPPCState *env, float64 arg)                          \
752 {                                                                             \
753     /* "Estimate" the reciprocal with actual division.  */                    \
754     float64 rets = float64_sqrt(arg, &env->fp_status);                        \
755     float64 retd = op(float64_one, rets, &env->fp_status);                    \
756     int flags = get_float_exception_flags(&env->fp_status);                   \
757                                                                               \
758     if (unlikely(flags & float_flag_invalid)) {                               \
759         float_invalid_op_sqrt(env, flags, 1, GETPC());                        \
760     }                                                                         \
761     if (unlikely(flags & float_flag_divbyzero)) {                             \
762         /* Reciprocal of (square root of) zero.  */                           \
763         float_zero_divide_excp(env, GETPC());                                 \
764     }                                                                         \
765                                                                               \
766     return retd;                                                              \
767 }
768 
769 #define FPU_HELPER(name, op, flags_handler)                                   \
770 float64 helper_##name(CPUPPCState *env, float64 arg1, float64 arg2)           \
771 {                                                                             \
772     float64 ret = op(arg1, arg2, &env->fp_status);                            \
773     int flags = get_float_exception_flags(&env->fp_status);                   \
774     uintptr_t ra = GETPC();                                                   \
775     flags_handler(env, flags, ra);                                            \
776     return ret;                                                               \
777 }
778 
779 FPU_FRE(FRE, float64_div)
780 FPU_FRE(FRES, float64r32_div)
781 FPU_FRSQRTE(FRSQRTE, float64_div)
782 FPU_FRSQRTE(FRSQRTES, float64r32_div)
783 FPU_HELPER(FADD, float64_add, addsub_flags_handler)
784 FPU_HELPER(FADDS, float64r32_add, addsub_flags_handler)
785 FPU_HELPER(FSUB, float64_sub, addsub_flags_handler)
786 FPU_HELPER(FSUBS, float64r32_sub, addsub_flags_handler)
787 FPU_HELPER(FMUL, float64_mul, mul_flags_handler)
788 FPU_HELPER(FMULS, float64r32_mul, mul_flags_handler)
789 FPU_HELPER(FDIV, float64_div, div_flags_handler)
790 FPU_HELPER(FDIVS, float64r32_div, div_flags_handler)
791 
792 /* fsel - fsel. */
793 uint64_t helper_FSEL(uint64_t a, uint64_t b, uint64_t c)
794 {
795     CPU_DoubleU fa;
796 
797     fa.ll = a;
798 
799     if ((!float64_is_neg(fa.d) || float64_is_zero(fa.d)) &&
800         !float64_is_any_nan(fa.d)) {
801         return c;
802     } else {
803         return b;
804     }
805 }
806 
helper_FTDIV(uint64_t fra,uint64_t frb)807 uint32_t helper_FTDIV(uint64_t fra, uint64_t frb)
808 {
809     int fe_flag = 0;
810     int fg_flag = 0;
811 
812     if (unlikely(float64_is_infinity(fra) ||
813                  float64_is_infinity(frb) ||
814                  float64_is_zero(frb))) {
815         fe_flag = 1;
816         fg_flag = 1;
817     } else {
818         int e_a = ppc_float64_get_unbiased_exp(fra);
819         int e_b = ppc_float64_get_unbiased_exp(frb);
820 
821         if (unlikely(float64_is_any_nan(fra) ||
822                      float64_is_any_nan(frb))) {
823             fe_flag = 1;
824         } else if ((e_b <= -1022) || (e_b >= 1021)) {
825             fe_flag = 1;
826         } else if (!float64_is_zero(fra) &&
827                    (((e_a - e_b) >= 1023) ||
828                     ((e_a - e_b) <= -1021) ||
829                     (e_a <= -970))) {
830             fe_flag = 1;
831         }
832 
833         if (unlikely(float64_is_zero_or_denormal(frb))) {
834             /* XB is not zero because of the above check and */
835             /* so must be denormalized.                      */
836             fg_flag = 1;
837         }
838     }
839 
840     return 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0);
841 }
842 
helper_FTSQRT(uint64_t frb)843 uint32_t helper_FTSQRT(uint64_t frb)
844 {
845     int fe_flag = 0;
846     int fg_flag = 0;
847 
848     if (unlikely(float64_is_infinity(frb) || float64_is_zero(frb))) {
849         fe_flag = 1;
850         fg_flag = 1;
851     } else {
852         int e_b = ppc_float64_get_unbiased_exp(frb);
853 
854         if (unlikely(float64_is_any_nan(frb))) {
855             fe_flag = 1;
856         } else if (unlikely(float64_is_zero(frb))) {
857             fe_flag = 1;
858         } else if (unlikely(float64_is_neg(frb))) {
859             fe_flag = 1;
860         } else if (!float64_is_zero(frb) && (e_b <= (-1022 + 52))) {
861             fe_flag = 1;
862         }
863 
864         if (unlikely(float64_is_zero_or_denormal(frb))) {
865             /* XB is not zero because of the above check and */
866             /* therefore must be denormalized.               */
867             fg_flag = 1;
868         }
869     }
870 
871     return 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0);
872 }
873 
helper_fcmpu(CPUPPCState * env,uint64_t arg1,uint64_t arg2,uint32_t crfD)874 void helper_fcmpu(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
875                   uint32_t crfD)
876 {
877     CPU_DoubleU farg1, farg2;
878     uint32_t ret = 0;
879 
880     farg1.ll = arg1;
881     farg2.ll = arg2;
882 
883     if (unlikely(float64_is_any_nan(farg1.d) ||
884                  float64_is_any_nan(farg2.d))) {
885         ret = 0x01UL;
886     } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
887         ret = 0x08UL;
888     } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
889         ret = 0x04UL;
890     } else {
891         ret = 0x02UL;
892     }
893 
894     env->fpscr &= ~FP_FPCC;
895     env->fpscr |= ret << FPSCR_FPCC;
896     env->crf[crfD] = ret;
897     if (unlikely(ret == 0x01UL
898                  && (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
899                      float64_is_signaling_nan(farg2.d, &env->fp_status)))) {
900         /* sNaN comparison */
901         float_invalid_op_vxsnan(env, GETPC());
902     }
903 }
904 
helper_fcmpo(CPUPPCState * env,uint64_t arg1,uint64_t arg2,uint32_t crfD)905 void helper_fcmpo(CPUPPCState *env, uint64_t arg1, uint64_t arg2,
906                   uint32_t crfD)
907 {
908     CPU_DoubleU farg1, farg2;
909     uint32_t ret = 0;
910 
911     farg1.ll = arg1;
912     farg2.ll = arg2;
913 
914     if (unlikely(float64_is_any_nan(farg1.d) ||
915                  float64_is_any_nan(farg2.d))) {
916         ret = 0x01UL;
917     } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
918         ret = 0x08UL;
919     } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
920         ret = 0x04UL;
921     } else {
922         ret = 0x02UL;
923     }
924 
925     env->fpscr &= ~FP_FPCC;
926     env->fpscr |= ret << FPSCR_FPCC;
927     env->crf[crfD] = (uint32_t) ret;
928     if (unlikely(ret == 0x01UL)) {
929         float_invalid_op_vxvc(env, 1, GETPC());
930         if (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
931             float64_is_signaling_nan(farg2.d, &env->fp_status)) {
932             /* sNaN comparison */
933             float_invalid_op_vxsnan(env, GETPC());
934         }
935     }
936 }
937 
938 /* Single-precision floating-point conversions */
efscfsi(CPUPPCState * env,uint32_t val)939 static inline uint32_t efscfsi(CPUPPCState *env, uint32_t val)
940 {
941     CPU_FloatU u;
942 
943     u.f = int32_to_float32(val, &env->vec_status);
944 
945     return u.l;
946 }
947 
efscfui(CPUPPCState * env,uint32_t val)948 static inline uint32_t efscfui(CPUPPCState *env, uint32_t val)
949 {
950     CPU_FloatU u;
951 
952     u.f = uint32_to_float32(val, &env->vec_status);
953 
954     return u.l;
955 }
956 
efsctsi(CPUPPCState * env,uint32_t val)957 static inline int32_t efsctsi(CPUPPCState *env, uint32_t val)
958 {
959     CPU_FloatU u;
960 
961     u.l = val;
962     /* NaN are not treated the same way IEEE 754 does */
963     if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
964         return 0;
965     }
966 
967     return float32_to_int32(u.f, &env->vec_status);
968 }
969 
efsctui(CPUPPCState * env,uint32_t val)970 static inline uint32_t efsctui(CPUPPCState *env, uint32_t val)
971 {
972     CPU_FloatU u;
973 
974     u.l = val;
975     /* NaN are not treated the same way IEEE 754 does */
976     if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
977         return 0;
978     }
979 
980     return float32_to_uint32(u.f, &env->vec_status);
981 }
982 
efsctsiz(CPUPPCState * env,uint32_t val)983 static inline uint32_t efsctsiz(CPUPPCState *env, uint32_t val)
984 {
985     CPU_FloatU u;
986 
987     u.l = val;
988     /* NaN are not treated the same way IEEE 754 does */
989     if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
990         return 0;
991     }
992 
993     return float32_to_int32_round_to_zero(u.f, &env->vec_status);
994 }
995 
efsctuiz(CPUPPCState * env,uint32_t val)996 static inline uint32_t efsctuiz(CPUPPCState *env, uint32_t val)
997 {
998     CPU_FloatU u;
999 
1000     u.l = val;
1001     /* NaN are not treated the same way IEEE 754 does */
1002     if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
1003         return 0;
1004     }
1005 
1006     return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
1007 }
1008 
efscfsf(CPUPPCState * env,uint32_t val)1009 static inline uint32_t efscfsf(CPUPPCState *env, uint32_t val)
1010 {
1011     CPU_FloatU u;
1012     float32 tmp;
1013 
1014     u.f = int32_to_float32(val, &env->vec_status);
1015     tmp = int64_to_float32(1ULL << 32, &env->vec_status);
1016     u.f = float32_div(u.f, tmp, &env->vec_status);
1017 
1018     return u.l;
1019 }
1020 
efscfuf(CPUPPCState * env,uint32_t val)1021 static inline uint32_t efscfuf(CPUPPCState *env, uint32_t val)
1022 {
1023     CPU_FloatU u;
1024     float32 tmp;
1025 
1026     u.f = uint32_to_float32(val, &env->vec_status);
1027     tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1028     u.f = float32_div(u.f, tmp, &env->vec_status);
1029 
1030     return u.l;
1031 }
1032 
efsctsf(CPUPPCState * env,uint32_t val)1033 static inline uint32_t efsctsf(CPUPPCState *env, uint32_t val)
1034 {
1035     CPU_FloatU u;
1036     float32 tmp;
1037 
1038     u.l = val;
1039     /* NaN are not treated the same way IEEE 754 does */
1040     if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
1041         return 0;
1042     }
1043     tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1044     u.f = float32_mul(u.f, tmp, &env->vec_status);
1045 
1046     return float32_to_int32(u.f, &env->vec_status);
1047 }
1048 
efsctuf(CPUPPCState * env,uint32_t val)1049 static inline uint32_t efsctuf(CPUPPCState *env, uint32_t val)
1050 {
1051     CPU_FloatU u;
1052     float32 tmp;
1053 
1054     u.l = val;
1055     /* NaN are not treated the same way IEEE 754 does */
1056     if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
1057         return 0;
1058     }
1059     tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
1060     u.f = float32_mul(u.f, tmp, &env->vec_status);
1061 
1062     return float32_to_uint32(u.f, &env->vec_status);
1063 }
1064 
1065 #define HELPER_SPE_SINGLE_CONV(name)                              \
1066     uint32_t helper_e##name(CPUPPCState *env, uint32_t val)       \
1067     {                                                             \
1068         return e##name(env, val);                                 \
1069     }
1070 /* efscfsi */
1071 HELPER_SPE_SINGLE_CONV(fscfsi);
1072 /* efscfui */
1073 HELPER_SPE_SINGLE_CONV(fscfui);
1074 /* efscfuf */
1075 HELPER_SPE_SINGLE_CONV(fscfuf);
1076 /* efscfsf */
1077 HELPER_SPE_SINGLE_CONV(fscfsf);
1078 /* efsctsi */
1079 HELPER_SPE_SINGLE_CONV(fsctsi);
1080 /* efsctui */
1081 HELPER_SPE_SINGLE_CONV(fsctui);
1082 /* efsctsiz */
1083 HELPER_SPE_SINGLE_CONV(fsctsiz);
1084 /* efsctuiz */
1085 HELPER_SPE_SINGLE_CONV(fsctuiz);
1086 /* efsctsf */
1087 HELPER_SPE_SINGLE_CONV(fsctsf);
1088 /* efsctuf */
1089 HELPER_SPE_SINGLE_CONV(fsctuf);
1090 
1091 #define HELPER_SPE_VECTOR_CONV(name)                            \
1092     uint64_t helper_ev##name(CPUPPCState *env, uint64_t val)    \
1093     {                                                           \
1094         return ((uint64_t)e##name(env, val >> 32) << 32) |      \
1095             (uint64_t)e##name(env, val);                        \
1096     }
1097 /* evfscfsi */
1098 HELPER_SPE_VECTOR_CONV(fscfsi);
1099 /* evfscfui */
1100 HELPER_SPE_VECTOR_CONV(fscfui);
1101 /* evfscfuf */
1102 HELPER_SPE_VECTOR_CONV(fscfuf);
1103 /* evfscfsf */
1104 HELPER_SPE_VECTOR_CONV(fscfsf);
1105 /* evfsctsi */
1106 HELPER_SPE_VECTOR_CONV(fsctsi);
1107 /* evfsctui */
1108 HELPER_SPE_VECTOR_CONV(fsctui);
1109 /* evfsctsiz */
1110 HELPER_SPE_VECTOR_CONV(fsctsiz);
1111 /* evfsctuiz */
1112 HELPER_SPE_VECTOR_CONV(fsctuiz);
1113 /* evfsctsf */
1114 HELPER_SPE_VECTOR_CONV(fsctsf);
1115 /* evfsctuf */
1116 HELPER_SPE_VECTOR_CONV(fsctuf);
1117 
1118 /* Single-precision floating-point arithmetic */
efsadd(CPUPPCState * env,uint32_t op1,uint32_t op2)1119 static inline uint32_t efsadd(CPUPPCState *env, uint32_t op1, uint32_t op2)
1120 {
1121     CPU_FloatU u1, u2;
1122 
1123     u1.l = op1;
1124     u2.l = op2;
1125     u1.f = float32_add(u1.f, u2.f, &env->vec_status);
1126     return u1.l;
1127 }
1128 
efssub(CPUPPCState * env,uint32_t op1,uint32_t op2)1129 static inline uint32_t efssub(CPUPPCState *env, uint32_t op1, uint32_t op2)
1130 {
1131     CPU_FloatU u1, u2;
1132 
1133     u1.l = op1;
1134     u2.l = op2;
1135     u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
1136     return u1.l;
1137 }
1138 
efsmul(CPUPPCState * env,uint32_t op1,uint32_t op2)1139 static inline uint32_t efsmul(CPUPPCState *env, uint32_t op1, uint32_t op2)
1140 {
1141     CPU_FloatU u1, u2;
1142 
1143     u1.l = op1;
1144     u2.l = op2;
1145     u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
1146     return u1.l;
1147 }
1148 
efsdiv(CPUPPCState * env,uint32_t op1,uint32_t op2)1149 static inline uint32_t efsdiv(CPUPPCState *env, uint32_t op1, uint32_t op2)
1150 {
1151     CPU_FloatU u1, u2;
1152 
1153     u1.l = op1;
1154     u2.l = op2;
1155     u1.f = float32_div(u1.f, u2.f, &env->vec_status);
1156     return u1.l;
1157 }
1158 
1159 #define HELPER_SPE_SINGLE_ARITH(name)                                   \
1160     uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1161     {                                                                   \
1162         return e##name(env, op1, op2);                                  \
1163     }
1164 /* efsadd */
1165 HELPER_SPE_SINGLE_ARITH(fsadd);
1166 /* efssub */
1167 HELPER_SPE_SINGLE_ARITH(fssub);
1168 /* efsmul */
1169 HELPER_SPE_SINGLE_ARITH(fsmul);
1170 /* efsdiv */
1171 HELPER_SPE_SINGLE_ARITH(fsdiv);
1172 
1173 #define HELPER_SPE_VECTOR_ARITH(name)                                   \
1174     uint64_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1175     {                                                                   \
1176         return ((uint64_t)e##name(env, op1 >> 32, op2 >> 32) << 32) |   \
1177             (uint64_t)e##name(env, op1, op2);                           \
1178     }
1179 /* evfsadd */
1180 HELPER_SPE_VECTOR_ARITH(fsadd);
1181 /* evfssub */
1182 HELPER_SPE_VECTOR_ARITH(fssub);
1183 /* evfsmul */
1184 HELPER_SPE_VECTOR_ARITH(fsmul);
1185 /* evfsdiv */
1186 HELPER_SPE_VECTOR_ARITH(fsdiv);
1187 
1188 /* Single-precision floating-point comparisons */
efscmplt(CPUPPCState * env,uint32_t op1,uint32_t op2)1189 static inline uint32_t efscmplt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1190 {
1191     CPU_FloatU u1, u2;
1192 
1193     u1.l = op1;
1194     u2.l = op2;
1195     return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1196 }
1197 
efscmpgt(CPUPPCState * env,uint32_t op1,uint32_t op2)1198 static inline uint32_t efscmpgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1199 {
1200     CPU_FloatU u1, u2;
1201 
1202     u1.l = op1;
1203     u2.l = op2;
1204     return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
1205 }
1206 
efscmpeq(CPUPPCState * env,uint32_t op1,uint32_t op2)1207 static inline uint32_t efscmpeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1208 {
1209     CPU_FloatU u1, u2;
1210 
1211     u1.l = op1;
1212     u2.l = op2;
1213     return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
1214 }
1215 
efststlt(CPUPPCState * env,uint32_t op1,uint32_t op2)1216 static inline uint32_t efststlt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1217 {
1218     /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1219     return efscmplt(env, op1, op2);
1220 }
1221 
efststgt(CPUPPCState * env,uint32_t op1,uint32_t op2)1222 static inline uint32_t efststgt(CPUPPCState *env, uint32_t op1, uint32_t op2)
1223 {
1224     /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1225     return efscmpgt(env, op1, op2);
1226 }
1227 
efststeq(CPUPPCState * env,uint32_t op1,uint32_t op2)1228 static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
1229 {
1230     /* XXX: TODO: ignore special values (NaN, infinites, ...) */
1231     return efscmpeq(env, op1, op2);
1232 }
1233 
1234 #define HELPER_SINGLE_SPE_CMP(name)                                     \
1235     uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
1236     {                                                                   \
1237         return e##name(env, op1, op2);                                  \
1238     }
1239 /* efststlt */
1240 HELPER_SINGLE_SPE_CMP(fststlt);
1241 /* efststgt */
1242 HELPER_SINGLE_SPE_CMP(fststgt);
1243 /* efststeq */
1244 HELPER_SINGLE_SPE_CMP(fststeq);
1245 /* efscmplt */
1246 HELPER_SINGLE_SPE_CMP(fscmplt);
1247 /* efscmpgt */
1248 HELPER_SINGLE_SPE_CMP(fscmpgt);
1249 /* efscmpeq */
1250 HELPER_SINGLE_SPE_CMP(fscmpeq);
1251 
evcmp_merge(int t0,int t1)1252 static inline uint32_t evcmp_merge(int t0, int t1)
1253 {
1254     return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1255 }
1256 
1257 #define HELPER_VECTOR_SPE_CMP(name)                                     \
1258     uint32_t helper_ev##name(CPUPPCState *env, uint64_t op1, uint64_t op2) \
1259     {                                                                   \
1260         return evcmp_merge(e##name(env, op1 >> 32, op2 >> 32),          \
1261                            e##name(env, op1, op2));                     \
1262     }
1263 /* evfststlt */
1264 HELPER_VECTOR_SPE_CMP(fststlt);
1265 /* evfststgt */
1266 HELPER_VECTOR_SPE_CMP(fststgt);
1267 /* evfststeq */
1268 HELPER_VECTOR_SPE_CMP(fststeq);
1269 /* evfscmplt */
1270 HELPER_VECTOR_SPE_CMP(fscmplt);
1271 /* evfscmpgt */
1272 HELPER_VECTOR_SPE_CMP(fscmpgt);
1273 /* evfscmpeq */
1274 HELPER_VECTOR_SPE_CMP(fscmpeq);
1275 
1276 /* Double-precision floating-point conversion */
helper_efdcfsi(CPUPPCState * env,uint32_t val)1277 uint64_t helper_efdcfsi(CPUPPCState *env, uint32_t val)
1278 {
1279     CPU_DoubleU u;
1280 
1281     u.d = int32_to_float64(val, &env->vec_status);
1282 
1283     return u.ll;
1284 }
1285 
helper_efdcfsid(CPUPPCState * env,uint64_t val)1286 uint64_t helper_efdcfsid(CPUPPCState *env, uint64_t val)
1287 {
1288     CPU_DoubleU u;
1289 
1290     u.d = int64_to_float64(val, &env->vec_status);
1291 
1292     return u.ll;
1293 }
1294 
helper_efdcfui(CPUPPCState * env,uint32_t val)1295 uint64_t helper_efdcfui(CPUPPCState *env, uint32_t val)
1296 {
1297     CPU_DoubleU u;
1298 
1299     u.d = uint32_to_float64(val, &env->vec_status);
1300 
1301     return u.ll;
1302 }
1303 
helper_efdcfuid(CPUPPCState * env,uint64_t val)1304 uint64_t helper_efdcfuid(CPUPPCState *env, uint64_t val)
1305 {
1306     CPU_DoubleU u;
1307 
1308     u.d = uint64_to_float64(val, &env->vec_status);
1309 
1310     return u.ll;
1311 }
1312 
helper_efdctsi(CPUPPCState * env,uint64_t val)1313 uint32_t helper_efdctsi(CPUPPCState *env, uint64_t val)
1314 {
1315     CPU_DoubleU u;
1316 
1317     u.ll = val;
1318     /* NaN are not treated the same way IEEE 754 does */
1319     if (unlikely(float64_is_any_nan(u.d))) {
1320         return 0;
1321     }
1322 
1323     return float64_to_int32(u.d, &env->vec_status);
1324 }
1325 
helper_efdctui(CPUPPCState * env,uint64_t val)1326 uint32_t helper_efdctui(CPUPPCState *env, uint64_t val)
1327 {
1328     CPU_DoubleU u;
1329 
1330     u.ll = val;
1331     /* NaN are not treated the same way IEEE 754 does */
1332     if (unlikely(float64_is_any_nan(u.d))) {
1333         return 0;
1334     }
1335 
1336     return float64_to_uint32(u.d, &env->vec_status);
1337 }
1338 
helper_efdctsiz(CPUPPCState * env,uint64_t val)1339 uint32_t helper_efdctsiz(CPUPPCState *env, uint64_t val)
1340 {
1341     CPU_DoubleU u;
1342 
1343     u.ll = val;
1344     /* NaN are not treated the same way IEEE 754 does */
1345     if (unlikely(float64_is_any_nan(u.d))) {
1346         return 0;
1347     }
1348 
1349     return float64_to_int32_round_to_zero(u.d, &env->vec_status);
1350 }
1351 
helper_efdctsidz(CPUPPCState * env,uint64_t val)1352 uint64_t helper_efdctsidz(CPUPPCState *env, uint64_t val)
1353 {
1354     CPU_DoubleU u;
1355 
1356     u.ll = val;
1357     /* NaN are not treated the same way IEEE 754 does */
1358     if (unlikely(float64_is_any_nan(u.d))) {
1359         return 0;
1360     }
1361 
1362     return float64_to_int64_round_to_zero(u.d, &env->vec_status);
1363 }
1364 
helper_efdctuiz(CPUPPCState * env,uint64_t val)1365 uint32_t helper_efdctuiz(CPUPPCState *env, uint64_t val)
1366 {
1367     CPU_DoubleU u;
1368 
1369     u.ll = val;
1370     /* NaN are not treated the same way IEEE 754 does */
1371     if (unlikely(float64_is_any_nan(u.d))) {
1372         return 0;
1373     }
1374 
1375     return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
1376 }
1377 
helper_efdctuidz(CPUPPCState * env,uint64_t val)1378 uint64_t helper_efdctuidz(CPUPPCState *env, uint64_t val)
1379 {
1380     CPU_DoubleU u;
1381 
1382     u.ll = val;
1383     /* NaN are not treated the same way IEEE 754 does */
1384     if (unlikely(float64_is_any_nan(u.d))) {
1385         return 0;
1386     }
1387 
1388     return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
1389 }
1390 
helper_efdcfsf(CPUPPCState * env,uint32_t val)1391 uint64_t helper_efdcfsf(CPUPPCState *env, uint32_t val)
1392 {
1393     CPU_DoubleU u;
1394     float64 tmp;
1395 
1396     u.d = int32_to_float64(val, &env->vec_status);
1397     tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1398     u.d = float64_div(u.d, tmp, &env->vec_status);
1399 
1400     return u.ll;
1401 }
1402 
helper_efdcfuf(CPUPPCState * env,uint32_t val)1403 uint64_t helper_efdcfuf(CPUPPCState *env, uint32_t val)
1404 {
1405     CPU_DoubleU u;
1406     float64 tmp;
1407 
1408     u.d = uint32_to_float64(val, &env->vec_status);
1409     tmp = int64_to_float64(1ULL << 32, &env->vec_status);
1410     u.d = float64_div(u.d, tmp, &env->vec_status);
1411 
1412     return u.ll;
1413 }
1414 
helper_efdctsf(CPUPPCState * env,uint64_t val)1415 uint32_t helper_efdctsf(CPUPPCState *env, uint64_t val)
1416 {
1417     CPU_DoubleU u;
1418     float64 tmp;
1419 
1420     u.ll = val;
1421     /* NaN are not treated the same way IEEE 754 does */
1422     if (unlikely(float64_is_any_nan(u.d))) {
1423         return 0;
1424     }
1425     tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1426     u.d = float64_mul(u.d, tmp, &env->vec_status);
1427 
1428     return float64_to_int32(u.d, &env->vec_status);
1429 }
1430 
helper_efdctuf(CPUPPCState * env,uint64_t val)1431 uint32_t helper_efdctuf(CPUPPCState *env, uint64_t val)
1432 {
1433     CPU_DoubleU u;
1434     float64 tmp;
1435 
1436     u.ll = val;
1437     /* NaN are not treated the same way IEEE 754 does */
1438     if (unlikely(float64_is_any_nan(u.d))) {
1439         return 0;
1440     }
1441     tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
1442     u.d = float64_mul(u.d, tmp, &env->vec_status);
1443 
1444     return float64_to_uint32(u.d, &env->vec_status);
1445 }
1446 
helper_efscfd(CPUPPCState * env,uint64_t val)1447 uint32_t helper_efscfd(CPUPPCState *env, uint64_t val)
1448 {
1449     CPU_DoubleU u1;
1450     CPU_FloatU u2;
1451 
1452     u1.ll = val;
1453     u2.f = float64_to_float32(u1.d, &env->vec_status);
1454 
1455     return u2.l;
1456 }
1457 
helper_efdcfs(CPUPPCState * env,uint32_t val)1458 uint64_t helper_efdcfs(CPUPPCState *env, uint32_t val)
1459 {
1460     CPU_DoubleU u2;
1461     CPU_FloatU u1;
1462 
1463     u1.l = val;
1464     u2.d = float32_to_float64(u1.f, &env->vec_status);
1465 
1466     return u2.ll;
1467 }
1468 
1469 /* Double precision fixed-point arithmetic */
helper_efdadd(CPUPPCState * env,uint64_t op1,uint64_t op2)1470 uint64_t helper_efdadd(CPUPPCState *env, uint64_t op1, uint64_t op2)
1471 {
1472     CPU_DoubleU u1, u2;
1473 
1474     u1.ll = op1;
1475     u2.ll = op2;
1476     u1.d = float64_add(u1.d, u2.d, &env->vec_status);
1477     return u1.ll;
1478 }
1479 
helper_efdsub(CPUPPCState * env,uint64_t op1,uint64_t op2)1480 uint64_t helper_efdsub(CPUPPCState *env, uint64_t op1, uint64_t op2)
1481 {
1482     CPU_DoubleU u1, u2;
1483 
1484     u1.ll = op1;
1485     u2.ll = op2;
1486     u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
1487     return u1.ll;
1488 }
1489 
helper_efdmul(CPUPPCState * env,uint64_t op1,uint64_t op2)1490 uint64_t helper_efdmul(CPUPPCState *env, uint64_t op1, uint64_t op2)
1491 {
1492     CPU_DoubleU u1, u2;
1493 
1494     u1.ll = op1;
1495     u2.ll = op2;
1496     u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
1497     return u1.ll;
1498 }
1499 
helper_efddiv(CPUPPCState * env,uint64_t op1,uint64_t op2)1500 uint64_t helper_efddiv(CPUPPCState *env, uint64_t op1, uint64_t op2)
1501 {
1502     CPU_DoubleU u1, u2;
1503 
1504     u1.ll = op1;
1505     u2.ll = op2;
1506     u1.d = float64_div(u1.d, u2.d, &env->vec_status);
1507     return u1.ll;
1508 }
1509 
1510 /* Double precision floating point helpers */
helper_efdtstlt(CPUPPCState * env,uint64_t op1,uint64_t op2)1511 uint32_t helper_efdtstlt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1512 {
1513     CPU_DoubleU u1, u2;
1514 
1515     u1.ll = op1;
1516     u2.ll = op2;
1517     return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1518 }
1519 
helper_efdtstgt(CPUPPCState * env,uint64_t op1,uint64_t op2)1520 uint32_t helper_efdtstgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1521 {
1522     CPU_DoubleU u1, u2;
1523 
1524     u1.ll = op1;
1525     u2.ll = op2;
1526     return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
1527 }
1528 
helper_efdtsteq(CPUPPCState * env,uint64_t op1,uint64_t op2)1529 uint32_t helper_efdtsteq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1530 {
1531     CPU_DoubleU u1, u2;
1532 
1533     u1.ll = op1;
1534     u2.ll = op2;
1535     return float64_eq_quiet(u1.d, u2.d, &env->vec_status) ? 4 : 0;
1536 }
1537 
helper_efdcmplt(CPUPPCState * env,uint64_t op1,uint64_t op2)1538 uint32_t helper_efdcmplt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1539 {
1540     /* XXX: TODO: test special values (NaN, infinites, ...) */
1541     return helper_efdtstlt(env, op1, op2);
1542 }
1543 
helper_efdcmpgt(CPUPPCState * env,uint64_t op1,uint64_t op2)1544 uint32_t helper_efdcmpgt(CPUPPCState *env, uint64_t op1, uint64_t op2)
1545 {
1546     /* XXX: TODO: test special values (NaN, infinites, ...) */
1547     return helper_efdtstgt(env, op1, op2);
1548 }
1549 
helper_efdcmpeq(CPUPPCState * env,uint64_t op1,uint64_t op2)1550 uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2)
1551 {
1552     /* XXX: TODO: test special values (NaN, infinites, ...) */
1553     return helper_efdtsteq(env, op1, op2);
1554 }
1555 
1556 #define float64_to_float64(x, env) x
1557 
1558 
1559 /*
1560  * VSX_ADD_SUB - VSX floating point add/subtract
1561  *   name  - instruction mnemonic
1562  *   op    - operation (add or sub)
1563  *   nels  - number of elements (1, 2 or 4)
1564  *   tp    - type (float32 or float64)
1565  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
1566  *   sfifprf - set FI and FPRF
1567  */
1568 #define VSX_ADD_SUB(name, op, nels, tp, fld, sfifprf, r2sp)                  \
1569 void helper_##name(CPUPPCState *env, ppc_vsr_t *xt,                          \
1570                    ppc_vsr_t *xa, ppc_vsr_t *xb)                             \
1571 {                                                                            \
1572     ppc_vsr_t t = { };                                                       \
1573     int i;                                                                   \
1574                                                                              \
1575     helper_reset_fpstatus(env);                                              \
1576                                                                              \
1577     for (i = 0; i < nels; i++) {                                             \
1578         float_status tstat = env->fp_status;                                 \
1579         set_float_exception_flags(0, &tstat);                                \
1580         t.fld = tp##_##op(xa->fld, xb->fld, &tstat);                         \
1581         env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1582                                                                              \
1583         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
1584             float_invalid_op_addsub(env, tstat.float_exception_flags,        \
1585                                     sfifprf, GETPC());                       \
1586         }                                                                    \
1587                                                                              \
1588         if (r2sp) {                                                          \
1589             t.fld = do_frsp(env, t.fld, GETPC());                            \
1590         }                                                                    \
1591                                                                              \
1592         if (sfifprf) {                                                       \
1593             helper_compute_fprf_float64(env, t.fld);                         \
1594         }                                                                    \
1595     }                                                                        \
1596     *xt = t;                                                                 \
1597     do_float_check_status(env, sfifprf, GETPC());                            \
1598 }
1599 
1600 VSX_ADD_SUB(XSADDDP, add, 1, float64, VsrD(0), 1, 0)
1601 VSX_ADD_SUB(XSADDSP, add, 1, float64, VsrD(0), 1, 1)
1602 VSX_ADD_SUB(XVADDDP, add, 2, float64, VsrD(i), 0, 0)
1603 VSX_ADD_SUB(XVADDSP, add, 4, float32, VsrW(i), 0, 0)
1604 VSX_ADD_SUB(XSSUBDP, sub, 1, float64, VsrD(0), 1, 0)
1605 VSX_ADD_SUB(XSSUBSP, sub, 1, float64, VsrD(0), 1, 1)
1606 VSX_ADD_SUB(XVSUBDP, sub, 2, float64, VsrD(i), 0, 0)
1607 VSX_ADD_SUB(XVSUBSP, sub, 4, float32, VsrW(i), 0, 0)
1608 
helper_xsaddqp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xt,ppc_vsr_t * xa,ppc_vsr_t * xb)1609 void helper_xsaddqp(CPUPPCState *env, uint32_t opcode,
1610                     ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb)
1611 {
1612     ppc_vsr_t t = *xt;
1613     float_status tstat;
1614 
1615     helper_reset_fpstatus(env);
1616 
1617     tstat = env->fp_status;
1618     if (unlikely(Rc(opcode) != 0)) {
1619         tstat.float_rounding_mode = float_round_to_odd;
1620     }
1621 
1622     set_float_exception_flags(0, &tstat);
1623     t.f128 = float128_add(xa->f128, xb->f128, &tstat);
1624     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
1625 
1626     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
1627         float_invalid_op_addsub(env, tstat.float_exception_flags, 1, GETPC());
1628     }
1629 
1630     helper_compute_fprf_float128(env, t.f128);
1631 
1632     *xt = t;
1633     do_float_check_status(env, true, GETPC());
1634 }
1635 
1636 /*
1637  * VSX_MUL - VSX floating point multiply
1638  *   op    - instruction mnemonic
1639  *   nels  - number of elements (1, 2 or 4)
1640  *   tp    - type (float32 or float64)
1641  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
1642  *   sfifprf - set FI and FPRF
1643  */
1644 #define VSX_MUL(op, nels, tp, fld, sfifprf, r2sp)                            \
1645 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt,                            \
1646                  ppc_vsr_t *xa, ppc_vsr_t *xb)                               \
1647 {                                                                            \
1648     ppc_vsr_t t = { };                                                       \
1649     int i;                                                                   \
1650                                                                              \
1651     helper_reset_fpstatus(env);                                              \
1652                                                                              \
1653     for (i = 0; i < nels; i++) {                                             \
1654         float_status tstat = env->fp_status;                                 \
1655         set_float_exception_flags(0, &tstat);                                \
1656         t.fld = tp##_mul(xa->fld, xb->fld, &tstat);                          \
1657         env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1658                                                                              \
1659         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
1660             float_invalid_op_mul(env, tstat.float_exception_flags,           \
1661                                  sfifprf, GETPC());                          \
1662         }                                                                    \
1663                                                                              \
1664         if (r2sp) {                                                          \
1665             t.fld = do_frsp(env, t.fld, GETPC());                            \
1666         }                                                                    \
1667                                                                              \
1668         if (sfifprf) {                                                       \
1669             helper_compute_fprf_float64(env, t.fld);                         \
1670         }                                                                    \
1671     }                                                                        \
1672                                                                              \
1673     *xt = t;                                                                 \
1674     do_float_check_status(env, sfifprf, GETPC());                            \
1675 }
1676 
1677 VSX_MUL(XSMULDP, 1, float64, VsrD(0), 1, 0)
1678 VSX_MUL(XSMULSP, 1, float64, VsrD(0), 1, 1)
1679 VSX_MUL(XVMULDP, 2, float64, VsrD(i), 0, 0)
1680 VSX_MUL(XVMULSP, 4, float32, VsrW(i), 0, 0)
1681 
helper_xsmulqp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xt,ppc_vsr_t * xa,ppc_vsr_t * xb)1682 void helper_xsmulqp(CPUPPCState *env, uint32_t opcode,
1683                     ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb)
1684 {
1685     ppc_vsr_t t = *xt;
1686     float_status tstat;
1687 
1688     helper_reset_fpstatus(env);
1689     tstat = env->fp_status;
1690     if (unlikely(Rc(opcode) != 0)) {
1691         tstat.float_rounding_mode = float_round_to_odd;
1692     }
1693 
1694     set_float_exception_flags(0, &tstat);
1695     t.f128 = float128_mul(xa->f128, xb->f128, &tstat);
1696     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
1697 
1698     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
1699         float_invalid_op_mul(env, tstat.float_exception_flags, 1, GETPC());
1700     }
1701     helper_compute_fprf_float128(env, t.f128);
1702 
1703     *xt = t;
1704     do_float_check_status(env, true, GETPC());
1705 }
1706 
1707 /*
1708  * VSX_DIV - VSX floating point divide
1709  *   op    - instruction mnemonic
1710  *   nels  - number of elements (1, 2 or 4)
1711  *   tp    - type (float32 or float64)
1712  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
1713  *   sfifprf - set FI and FPRF
1714  */
1715 #define VSX_DIV(op, nels, tp, fld, sfifprf, r2sp)                             \
1716 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt,                             \
1717                  ppc_vsr_t *xa, ppc_vsr_t *xb)                                \
1718 {                                                                             \
1719     ppc_vsr_t t = { };                                                        \
1720     int i;                                                                    \
1721                                                                               \
1722     helper_reset_fpstatus(env);                                               \
1723                                                                               \
1724     for (i = 0; i < nels; i++) {                                              \
1725         float_status tstat = env->fp_status;                                  \
1726         set_float_exception_flags(0, &tstat);                                 \
1727         t.fld = tp##_div(xa->fld, xb->fld, &tstat);                           \
1728         env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
1729                                                                               \
1730         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
1731             float_invalid_op_div(env, tstat.float_exception_flags,            \
1732                                  sfifprf, GETPC());                           \
1733         }                                                                     \
1734         if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {   \
1735             float_zero_divide_excp(env, GETPC());                             \
1736         }                                                                     \
1737                                                                               \
1738         if (r2sp) {                                                           \
1739             t.fld = do_frsp(env, t.fld, GETPC());                             \
1740         }                                                                     \
1741                                                                               \
1742         if (sfifprf) {                                                        \
1743             helper_compute_fprf_float64(env, t.fld);                          \
1744         }                                                                     \
1745     }                                                                         \
1746                                                                               \
1747     *xt = t;                                                                  \
1748     do_float_check_status(env, sfifprf, GETPC());                             \
1749 }
1750 
1751 VSX_DIV(XSDIVDP, 1, float64, VsrD(0), 1, 0)
1752 VSX_DIV(XSDIVSP, 1, float64, VsrD(0), 1, 1)
1753 VSX_DIV(XVDIVDP, 2, float64, VsrD(i), 0, 0)
1754 VSX_DIV(XVDIVSP, 4, float32, VsrW(i), 0, 0)
1755 
helper_xsdivqp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xt,ppc_vsr_t * xa,ppc_vsr_t * xb)1756 void helper_xsdivqp(CPUPPCState *env, uint32_t opcode,
1757                     ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb)
1758 {
1759     ppc_vsr_t t = *xt;
1760     float_status tstat;
1761 
1762     helper_reset_fpstatus(env);
1763     tstat = env->fp_status;
1764     if (unlikely(Rc(opcode) != 0)) {
1765         tstat.float_rounding_mode = float_round_to_odd;
1766     }
1767 
1768     set_float_exception_flags(0, &tstat);
1769     t.f128 = float128_div(xa->f128, xb->f128, &tstat);
1770     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
1771 
1772     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
1773         float_invalid_op_div(env, tstat.float_exception_flags, 1, GETPC());
1774     }
1775     if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {
1776         float_zero_divide_excp(env, GETPC());
1777     }
1778 
1779     helper_compute_fprf_float128(env, t.f128);
1780     *xt = t;
1781     do_float_check_status(env, true, GETPC());
1782 }
1783 
1784 /*
1785  * VSX_RE  - VSX floating point reciprocal estimate
1786  *   op    - instruction mnemonic
1787  *   nels  - number of elements (1, 2 or 4)
1788  *   tp    - type (float32 or float64)
1789  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
1790  *   sfifprf - set FI and FPRF
1791  */
1792 #define VSX_RE(op, nels, tp, fld, sfifprf, r2sp)                              \
1793 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)              \
1794 {                                                                             \
1795     ppc_vsr_t t = { };                                                        \
1796     int i;                                                                    \
1797                                                                               \
1798     helper_reset_fpstatus(env);                                               \
1799                                                                               \
1800     for (i = 0; i < nels; i++) {                                              \
1801         if (unlikely(tp##_is_signaling_nan(xb->fld, &env->fp_status))) {      \
1802             float_invalid_op_vxsnan(env, GETPC());                            \
1803         }                                                                     \
1804         t.fld = tp##_div(tp##_one, xb->fld, &env->fp_status);                 \
1805                                                                               \
1806         if (r2sp) {                                                           \
1807             t.fld = do_frsp(env, t.fld, GETPC());                             \
1808         }                                                                     \
1809                                                                               \
1810         if (sfifprf) {                                                        \
1811             helper_compute_fprf_float64(env, t.fld);                          \
1812         }                                                                     \
1813     }                                                                         \
1814                                                                               \
1815     *xt = t;                                                                  \
1816     do_float_check_status(env, sfifprf, GETPC());                             \
1817 }
1818 
1819 VSX_RE(xsredp, 1, float64, VsrD(0), 1, 0)
1820 VSX_RE(xsresp, 1, float64, VsrD(0), 1, 1)
1821 VSX_RE(xvredp, 2, float64, VsrD(i), 0, 0)
1822 VSX_RE(xvresp, 4, float32, VsrW(i), 0, 0)
1823 
1824 /*
1825  * VSX_SQRT - VSX floating point square root
1826  *   op    - instruction mnemonic
1827  *   nels  - number of elements (1, 2 or 4)
1828  *   tp    - type (float32 or float64)
1829  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
1830  *   sfifprf - set FI and FPRF
1831  */
1832 #define VSX_SQRT(op, nels, tp, fld, sfifprf, r2sp)                           \
1833 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)             \
1834 {                                                                            \
1835     ppc_vsr_t t = { };                                                       \
1836     int i;                                                                   \
1837                                                                              \
1838     helper_reset_fpstatus(env);                                              \
1839                                                                              \
1840     for (i = 0; i < nels; i++) {                                             \
1841         float_status tstat = env->fp_status;                                 \
1842         set_float_exception_flags(0, &tstat);                                \
1843         t.fld = tp##_sqrt(xb->fld, &tstat);                                  \
1844         env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1845                                                                              \
1846         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
1847             float_invalid_op_sqrt(env, tstat.float_exception_flags,          \
1848                                   sfifprf, GETPC());                         \
1849         }                                                                    \
1850                                                                              \
1851         if (r2sp) {                                                          \
1852             t.fld = do_frsp(env, t.fld, GETPC());                            \
1853         }                                                                    \
1854                                                                              \
1855         if (sfifprf) {                                                       \
1856             helper_compute_fprf_float64(env, t.fld);                         \
1857         }                                                                    \
1858     }                                                                        \
1859                                                                              \
1860     *xt = t;                                                                 \
1861     do_float_check_status(env, sfifprf, GETPC());                            \
1862 }
1863 
1864 VSX_SQRT(xssqrtdp, 1, float64, VsrD(0), 1, 0)
1865 VSX_SQRT(xssqrtsp, 1, float64, VsrD(0), 1, 1)
1866 VSX_SQRT(xvsqrtdp, 2, float64, VsrD(i), 0, 0)
1867 VSX_SQRT(xvsqrtsp, 4, float32, VsrW(i), 0, 0)
1868 
1869 /*
1870  *VSX_RSQRTE - VSX floating point reciprocal square root estimate
1871  *   op    - instruction mnemonic
1872  *   nels  - number of elements (1, 2 or 4)
1873  *   tp    - type (float32 or float64)
1874  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
1875  *   sfifprf - set FI and FPRF
1876  */
1877 #define VSX_RSQRTE(op, nels, tp, fld, sfifprf, r2sp)                         \
1878 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)             \
1879 {                                                                            \
1880     ppc_vsr_t t = { };                                                       \
1881     int i;                                                                   \
1882                                                                              \
1883     helper_reset_fpstatus(env);                                              \
1884                                                                              \
1885     for (i = 0; i < nels; i++) {                                             \
1886         float_status tstat = env->fp_status;                                 \
1887         set_float_exception_flags(0, &tstat);                                \
1888         t.fld = tp##_sqrt(xb->fld, &tstat);                                  \
1889         t.fld = tp##_div(tp##_one, t.fld, &tstat);                           \
1890         env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
1891         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
1892             float_invalid_op_sqrt(env, tstat.float_exception_flags,          \
1893                                   sfifprf, GETPC());                         \
1894         }                                                                    \
1895         if (r2sp) {                                                          \
1896             t.fld = do_frsp(env, t.fld, GETPC());                            \
1897         }                                                                    \
1898                                                                              \
1899         if (sfifprf) {                                                       \
1900             helper_compute_fprf_float64(env, t.fld);                         \
1901         }                                                                    \
1902     }                                                                        \
1903                                                                              \
1904     *xt = t;                                                                 \
1905     do_float_check_status(env, sfifprf, GETPC());                            \
1906 }
1907 
1908 VSX_RSQRTE(xsrsqrtedp, 1, float64, VsrD(0), 1, 0)
1909 VSX_RSQRTE(xsrsqrtesp, 1, float64, VsrD(0), 1, 1)
1910 VSX_RSQRTE(xvrsqrtedp, 2, float64, VsrD(i), 0, 0)
1911 VSX_RSQRTE(xvrsqrtesp, 4, float32, VsrW(i), 0, 0)
1912 
1913 /*
1914  * VSX_TDIV - VSX floating point test for divide
1915  *   op    - instruction mnemonic
1916  *   nels  - number of elements (1, 2 or 4)
1917  *   tp    - type (float32 or float64)
1918  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
1919  *   emin  - minimum unbiased exponent
1920  *   emax  - maximum unbiased exponent
1921  *   nbits - number of fraction bits
1922  */
1923 #define VSX_TDIV(op, nels, tp, fld, emin, emax, nbits)                  \
1924 void helper_##op(CPUPPCState *env, uint32_t opcode,                     \
1925                  ppc_vsr_t *xa, ppc_vsr_t *xb)                          \
1926 {                                                                       \
1927     int i;                                                              \
1928     int fe_flag = 0;                                                    \
1929     int fg_flag = 0;                                                    \
1930                                                                         \
1931     for (i = 0; i < nels; i++) {                                        \
1932         if (unlikely(tp##_is_infinity(xa->fld) ||                       \
1933                      tp##_is_infinity(xb->fld) ||                       \
1934                      tp##_is_zero(xb->fld))) {                          \
1935             fe_flag = 1;                                                \
1936             fg_flag = 1;                                                \
1937         } else {                                                        \
1938             int e_a = ppc_##tp##_get_unbiased_exp(xa->fld);             \
1939             int e_b = ppc_##tp##_get_unbiased_exp(xb->fld);             \
1940                                                                         \
1941             if (unlikely(tp##_is_any_nan(xa->fld) ||                    \
1942                          tp##_is_any_nan(xb->fld))) {                   \
1943                 fe_flag = 1;                                            \
1944             } else if ((e_b <= emin) || (e_b >= (emax - 2))) {          \
1945                 fe_flag = 1;                                            \
1946             } else if (!tp##_is_zero(xa->fld) &&                        \
1947                        (((e_a - e_b) >= emax) ||                        \
1948                         ((e_a - e_b) <= (emin + 1)) ||                  \
1949                         (e_a <= (emin + nbits)))) {                     \
1950                 fe_flag = 1;                                            \
1951             }                                                           \
1952                                                                         \
1953             if (unlikely(tp##_is_zero_or_denormal(xb->fld))) {          \
1954                 /*                                                      \
1955                  * XB is not zero because of the above check and so     \
1956                  * must be denormalized.                                \
1957                  */                                                     \
1958                 fg_flag = 1;                                            \
1959             }                                                           \
1960         }                                                               \
1961     }                                                                   \
1962                                                                         \
1963     env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
1964 }
1965 
1966 VSX_TDIV(xstdivdp, 1, float64, VsrD(0), -1022, 1023, 52)
1967 VSX_TDIV(xvtdivdp, 2, float64, VsrD(i), -1022, 1023, 52)
1968 VSX_TDIV(xvtdivsp, 4, float32, VsrW(i), -126, 127, 23)
1969 
1970 /*
1971  * VSX_TSQRT - VSX floating point test for square root
1972  *   op    - instruction mnemonic
1973  *   nels  - number of elements (1, 2 or 4)
1974  *   tp    - type (float32 or float64)
1975  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
1976  *   emin  - minimum unbiased exponent
1977  *   emax  - maximum unbiased exponent
1978  *   nbits - number of fraction bits
1979  */
1980 #define VSX_TSQRT(op, nels, tp, fld, emin, nbits)                       \
1981 void helper_##op(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xb)      \
1982 {                                                                       \
1983     int i;                                                              \
1984     int fe_flag = 0;                                                    \
1985     int fg_flag = 0;                                                    \
1986                                                                         \
1987     for (i = 0; i < nels; i++) {                                        \
1988         if (unlikely(tp##_is_infinity(xb->fld) ||                       \
1989                      tp##_is_zero(xb->fld))) {                          \
1990             fe_flag = 1;                                                \
1991             fg_flag = 1;                                                \
1992         } else {                                                        \
1993             int e_b = ppc_##tp##_get_unbiased_exp(xb->fld);             \
1994                                                                         \
1995             if (unlikely(tp##_is_any_nan(xb->fld))) {                   \
1996                 fe_flag = 1;                                            \
1997             } else if (unlikely(tp##_is_zero(xb->fld))) {               \
1998                 fe_flag = 1;                                            \
1999             } else if (unlikely(tp##_is_neg(xb->fld))) {                \
2000                 fe_flag = 1;                                            \
2001             } else if (!tp##_is_zero(xb->fld) &&                        \
2002                        (e_b <= (emin + nbits))) {                       \
2003                 fe_flag = 1;                                            \
2004             }                                                           \
2005                                                                         \
2006             if (unlikely(tp##_is_zero_or_denormal(xb->fld))) {          \
2007                 /*                                                      \
2008                  * XB is not zero because of the above check and        \
2009                  * therefore must be denormalized.                      \
2010                  */                                                     \
2011                 fg_flag = 1;                                            \
2012             }                                                           \
2013         }                                                               \
2014     }                                                                   \
2015                                                                         \
2016     env->crf[BF(opcode)] = 0x8 | (fg_flag ? 4 : 0) | (fe_flag ? 2 : 0); \
2017 }
2018 
2019 VSX_TSQRT(xstsqrtdp, 1, float64, VsrD(0), -1022, 52)
2020 VSX_TSQRT(xvtsqrtdp, 2, float64, VsrD(i), -1022, 52)
2021 VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23)
2022 
2023 /*
2024  * VSX_MADD - VSX floating point muliply/add variations
2025  *   op    - instruction mnemonic
2026  *   nels  - number of elements (1, 2 or 4)
2027  *   tp    - type (float32 or float64)
2028  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
2029  *   maddflgs - flags for the float*muladd routine that control the
2030  *           various forms (madd, msub, nmadd, nmsub)
2031  *   sfifprf - set FI and FPRF
2032  */
2033 #define VSX_MADD(op, nels, tp, fld, maddflgs, sfifprf)                        \
2034 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt,                             \
2035                  ppc_vsr_t *s1, ppc_vsr_t *s2, ppc_vsr_t *s3)                 \
2036 {                                                                             \
2037     ppc_vsr_t t = { };                                                        \
2038     int i;                                                                    \
2039                                                                               \
2040     helper_reset_fpstatus(env);                                               \
2041                                                                               \
2042     for (i = 0; i < nels; i++) {                                              \
2043         float_status tstat = env->fp_status;                                  \
2044         set_float_exception_flags(0, &tstat);                                 \
2045         t.fld = tp##_muladd(s1->fld, s3->fld, s2->fld, maddflgs, &tstat);     \
2046         env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
2047                                                                               \
2048         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
2049             float_invalid_op_madd(env, tstat.float_exception_flags,           \
2050                                   sfifprf, GETPC());                          \
2051         }                                                                     \
2052                                                                               \
2053         if (sfifprf) {                                                        \
2054             helper_compute_fprf_float64(env, t.fld);                          \
2055         }                                                                     \
2056     }                                                                         \
2057     *xt = t;                                                                  \
2058     do_float_check_status(env, sfifprf, GETPC());                             \
2059 }
2060 
2061 VSX_MADD(XSMADDDP, 1, float64, VsrD(0), MADD_FLGS, 1)
2062 VSX_MADD(XSMSUBDP, 1, float64, VsrD(0), MSUB_FLGS, 1)
2063 VSX_MADD(XSNMADDDP, 1, float64, VsrD(0), NMADD_FLGS, 1)
2064 VSX_MADD(XSNMSUBDP, 1, float64, VsrD(0), NMSUB_FLGS, 1)
2065 VSX_MADD(XSMADDSP, 1, float64r32, VsrD(0), MADD_FLGS, 1)
2066 VSX_MADD(XSMSUBSP, 1, float64r32, VsrD(0), MSUB_FLGS, 1)
2067 VSX_MADD(XSNMADDSP, 1, float64r32, VsrD(0), NMADD_FLGS, 1)
2068 VSX_MADD(XSNMSUBSP, 1, float64r32, VsrD(0), NMSUB_FLGS, 1)
2069 
2070 VSX_MADD(xvmadddp, 2, float64, VsrD(i), MADD_FLGS, 0)
2071 VSX_MADD(xvmsubdp, 2, float64, VsrD(i), MSUB_FLGS, 0)
2072 VSX_MADD(xvnmadddp, 2, float64, VsrD(i), NMADD_FLGS, 0)
2073 VSX_MADD(xvnmsubdp, 2, float64, VsrD(i), NMSUB_FLGS, 0)
2074 
2075 VSX_MADD(xvmaddsp, 4, float32, VsrW(i), MADD_FLGS, 0)
2076 VSX_MADD(xvmsubsp, 4, float32, VsrW(i), MSUB_FLGS, 0)
2077 VSX_MADD(xvnmaddsp, 4, float32, VsrW(i), NMADD_FLGS, 0)
2078 VSX_MADD(xvnmsubsp, 4, float32, VsrW(i), NMSUB_FLGS, 0)
2079 
2080 /*
2081  * VSX_MADDQ - VSX floating point quad-precision muliply/add
2082  *   op    - instruction mnemonic
2083  *   maddflgs - flags for the float*muladd routine that control the
2084  *           various forms (madd, msub, nmadd, nmsub)
2085  *   ro    - round to odd
2086  */
2087 #define VSX_MADDQ(op, maddflgs, ro)                                            \
2088 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *s1, ppc_vsr_t *s2,\
2089                  ppc_vsr_t *s3)                                                \
2090 {                                                                              \
2091     ppc_vsr_t t = *xt;                                                         \
2092                                                                                \
2093     helper_reset_fpstatus(env);                                                \
2094                                                                                \
2095     float_status tstat = env->fp_status;                                       \
2096     set_float_exception_flags(0, &tstat);                                      \
2097     if (ro) {                                                                  \
2098         tstat.float_rounding_mode = float_round_to_odd;                        \
2099     }                                                                          \
2100     t.f128 = float128_muladd(s1->f128, s3->f128, s2->f128, maddflgs, &tstat);  \
2101     env->fp_status.float_exception_flags |= tstat.float_exception_flags;       \
2102                                                                                \
2103     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {          \
2104         float_invalid_op_madd(env, tstat.float_exception_flags,                \
2105                               false, GETPC());                                 \
2106     }                                                                          \
2107                                                                                \
2108     helper_compute_fprf_float128(env, t.f128);                                 \
2109     *xt = t;                                                                   \
2110     do_float_check_status(env, true, GETPC());                                 \
2111 }
2112 
2113 VSX_MADDQ(XSMADDQP, MADD_FLGS, 0)
2114 VSX_MADDQ(XSMADDQPO, MADD_FLGS, 1)
2115 VSX_MADDQ(XSMSUBQP, MSUB_FLGS, 0)
2116 VSX_MADDQ(XSMSUBQPO, MSUB_FLGS, 1)
2117 VSX_MADDQ(XSNMADDQP, NMADD_FLGS, 0)
2118 VSX_MADDQ(XSNMADDQPO, NMADD_FLGS, 1)
2119 VSX_MADDQ(XSNMSUBQP, NMSUB_FLGS, 0)
2120 VSX_MADDQ(XSNMSUBQPO, NMSUB_FLGS, 0)
2121 
2122 /*
2123  * VSX_SCALAR_CMP - VSX scalar floating point compare
2124  *   op    - instruction mnemonic
2125  *   tp    - type
2126  *   cmp   - comparison operation
2127  *   fld   - vsr_t field
2128  *   svxvc - set VXVC bit
2129  */
2130 #define VSX_SCALAR_CMP(op, tp, cmp, fld, svxvc)                               \
2131         void helper_##op(CPUPPCState *env, ppc_vsr_t *xt,                     \
2132                 ppc_vsr_t *xa, ppc_vsr_t *xb)                                 \
2133 {                                                                             \
2134     int flags;                                                                \
2135     bool r, vxvc;                                                             \
2136                                                                               \
2137     helper_reset_fpstatus(env);                                               \
2138                                                                               \
2139     if (svxvc) {                                                              \
2140         r = tp##_##cmp(xb->fld, xa->fld, &env->fp_status);                    \
2141     } else {                                                                  \
2142         r = tp##_##cmp##_quiet(xb->fld, xa->fld, &env->fp_status);            \
2143     }                                                                         \
2144                                                                               \
2145     flags = get_float_exception_flags(&env->fp_status);                       \
2146     if (unlikely(flags & float_flag_invalid)) {                               \
2147         vxvc = svxvc;                                                         \
2148         if (flags & float_flag_invalid_snan) {                                \
2149             float_invalid_op_vxsnan(env, GETPC());                            \
2150             vxvc &= !(env->fpscr & FP_VE);                                    \
2151         }                                                                     \
2152         if (vxvc) {                                                           \
2153             float_invalid_op_vxvc(env, 0, GETPC());                           \
2154         }                                                                     \
2155     }                                                                         \
2156                                                                               \
2157     memset(xt, 0, sizeof(*xt));                                               \
2158     memset(&xt->fld, -r, sizeof(xt->fld));                                    \
2159     do_float_check_status(env, false, GETPC());                               \
2160 }
2161 
2162 VSX_SCALAR_CMP(XSCMPEQDP, float64, eq, VsrD(0), 0)
2163 VSX_SCALAR_CMP(XSCMPGEDP, float64, le, VsrD(0), 1)
2164 VSX_SCALAR_CMP(XSCMPGTDP, float64, lt, VsrD(0), 1)
2165 VSX_SCALAR_CMP(XSCMPEQQP, float128, eq, f128, 0)
2166 VSX_SCALAR_CMP(XSCMPGEQP, float128, le, f128, 1)
2167 VSX_SCALAR_CMP(XSCMPGTQP, float128, lt, f128, 1)
2168 
helper_xscmpexpdp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xa,ppc_vsr_t * xb)2169 void helper_xscmpexpdp(CPUPPCState *env, uint32_t opcode,
2170                        ppc_vsr_t *xa, ppc_vsr_t *xb)
2171 {
2172     int64_t exp_a, exp_b;
2173     uint32_t cc;
2174 
2175     exp_a = extract64(xa->VsrD(0), 52, 11);
2176     exp_b = extract64(xb->VsrD(0), 52, 11);
2177 
2178     if (unlikely(float64_is_any_nan(xa->VsrD(0)) ||
2179                  float64_is_any_nan(xb->VsrD(0)))) {
2180         cc = CRF_SO;
2181     } else {
2182         if (exp_a < exp_b) {
2183             cc = CRF_LT;
2184         } else if (exp_a > exp_b) {
2185             cc = CRF_GT;
2186         } else {
2187             cc = CRF_EQ;
2188         }
2189     }
2190 
2191     env->fpscr &= ~FP_FPCC;
2192     env->fpscr |= cc << FPSCR_FPCC;
2193     env->crf[BF(opcode)] = cc;
2194 
2195     do_float_check_status(env, false, GETPC());
2196 }
2197 
helper_xscmpexpqp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xa,ppc_vsr_t * xb)2198 void helper_xscmpexpqp(CPUPPCState *env, uint32_t opcode,
2199                        ppc_vsr_t *xa, ppc_vsr_t *xb)
2200 {
2201     int64_t exp_a, exp_b;
2202     uint32_t cc;
2203 
2204     exp_a = extract64(xa->VsrD(0), 48, 15);
2205     exp_b = extract64(xb->VsrD(0), 48, 15);
2206 
2207     if (unlikely(float128_is_any_nan(xa->f128) ||
2208                  float128_is_any_nan(xb->f128))) {
2209         cc = CRF_SO;
2210     } else {
2211         if (exp_a < exp_b) {
2212             cc = CRF_LT;
2213         } else if (exp_a > exp_b) {
2214             cc = CRF_GT;
2215         } else {
2216             cc = CRF_EQ;
2217         }
2218     }
2219 
2220     env->fpscr &= ~FP_FPCC;
2221     env->fpscr |= cc << FPSCR_FPCC;
2222     env->crf[BF(opcode)] = cc;
2223 
2224     do_float_check_status(env, false, GETPC());
2225 }
2226 
do_scalar_cmp(CPUPPCState * env,ppc_vsr_t * xa,ppc_vsr_t * xb,int crf_idx,bool ordered)2227 static inline void do_scalar_cmp(CPUPPCState *env, ppc_vsr_t *xa, ppc_vsr_t *xb,
2228                                  int crf_idx, bool ordered)
2229 {
2230     uint32_t cc;
2231     bool vxsnan_flag = false, vxvc_flag = false;
2232 
2233     helper_reset_fpstatus(env);
2234 
2235     switch (float64_compare(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) {
2236     case float_relation_less:
2237         cc = CRF_LT;
2238         break;
2239     case float_relation_equal:
2240         cc = CRF_EQ;
2241         break;
2242     case float_relation_greater:
2243         cc = CRF_GT;
2244         break;
2245     case float_relation_unordered:
2246         cc = CRF_SO;
2247 
2248         if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status) ||
2249             float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) {
2250             vxsnan_flag = true;
2251             if (!(env->fpscr & FP_VE) && ordered) {
2252                 vxvc_flag = true;
2253             }
2254         } else if (float64_is_quiet_nan(xa->VsrD(0), &env->fp_status) ||
2255                    float64_is_quiet_nan(xb->VsrD(0), &env->fp_status)) {
2256             if (ordered) {
2257                 vxvc_flag = true;
2258             }
2259         }
2260 
2261         break;
2262     default:
2263         g_assert_not_reached();
2264     }
2265 
2266     env->fpscr &= ~FP_FPCC;
2267     env->fpscr |= cc << FPSCR_FPCC;
2268     env->crf[crf_idx] = cc;
2269 
2270     if (vxsnan_flag) {
2271         float_invalid_op_vxsnan(env, GETPC());
2272     }
2273     if (vxvc_flag) {
2274         float_invalid_op_vxvc(env, 0, GETPC());
2275     }
2276 
2277     do_float_check_status(env, false, GETPC());
2278 }
2279 
helper_xscmpodp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xa,ppc_vsr_t * xb)2280 void helper_xscmpodp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
2281                      ppc_vsr_t *xb)
2282 {
2283     do_scalar_cmp(env, xa, xb, BF(opcode), true);
2284 }
2285 
helper_xscmpudp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xa,ppc_vsr_t * xb)2286 void helper_xscmpudp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
2287                      ppc_vsr_t *xb)
2288 {
2289     do_scalar_cmp(env, xa, xb, BF(opcode), false);
2290 }
2291 
do_scalar_cmpq(CPUPPCState * env,ppc_vsr_t * xa,ppc_vsr_t * xb,int crf_idx,bool ordered)2292 static inline void do_scalar_cmpq(CPUPPCState *env, ppc_vsr_t *xa,
2293                                   ppc_vsr_t *xb, int crf_idx, bool ordered)
2294 {
2295     uint32_t cc;
2296     bool vxsnan_flag = false, vxvc_flag = false;
2297 
2298     helper_reset_fpstatus(env);
2299 
2300     switch (float128_compare(xa->f128, xb->f128, &env->fp_status)) {
2301     case float_relation_less:
2302         cc = CRF_LT;
2303         break;
2304     case float_relation_equal:
2305         cc = CRF_EQ;
2306         break;
2307     case float_relation_greater:
2308         cc = CRF_GT;
2309         break;
2310     case float_relation_unordered:
2311         cc = CRF_SO;
2312 
2313         if (float128_is_signaling_nan(xa->f128, &env->fp_status) ||
2314             float128_is_signaling_nan(xb->f128, &env->fp_status)) {
2315             vxsnan_flag = true;
2316             if (!(env->fpscr & FP_VE) && ordered) {
2317                 vxvc_flag = true;
2318             }
2319         } else if (float128_is_quiet_nan(xa->f128, &env->fp_status) ||
2320                    float128_is_quiet_nan(xb->f128, &env->fp_status)) {
2321             if (ordered) {
2322                 vxvc_flag = true;
2323             }
2324         }
2325 
2326         break;
2327     default:
2328         g_assert_not_reached();
2329     }
2330 
2331     env->fpscr &= ~FP_FPCC;
2332     env->fpscr |= cc << FPSCR_FPCC;
2333     env->crf[crf_idx] = cc;
2334 
2335     if (vxsnan_flag) {
2336         float_invalid_op_vxsnan(env, GETPC());
2337     }
2338     if (vxvc_flag) {
2339         float_invalid_op_vxvc(env, 0, GETPC());
2340     }
2341 
2342     do_float_check_status(env, false, GETPC());
2343 }
2344 
helper_xscmpoqp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xa,ppc_vsr_t * xb)2345 void helper_xscmpoqp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
2346                      ppc_vsr_t *xb)
2347 {
2348     do_scalar_cmpq(env, xa, xb, BF(opcode), true);
2349 }
2350 
helper_xscmpuqp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xa,ppc_vsr_t * xb)2351 void helper_xscmpuqp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xa,
2352                      ppc_vsr_t *xb)
2353 {
2354     do_scalar_cmpq(env, xa, xb, BF(opcode), false);
2355 }
2356 
2357 /*
2358  * VSX_MAX_MIN - VSX floating point maximum/minimum
2359  *   name  - instruction mnemonic
2360  *   op    - operation (max or min)
2361  *   nels  - number of elements (1, 2 or 4)
2362  *   tp    - type (float32 or float64)
2363  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
2364  */
2365 #define VSX_MAX_MIN(name, op, nels, tp, fld)                                  \
2366 void helper_##name(CPUPPCState *env, ppc_vsr_t *xt,                           \
2367                    ppc_vsr_t *xa, ppc_vsr_t *xb)                              \
2368 {                                                                             \
2369     ppc_vsr_t t = { };                                                        \
2370     int i;                                                                    \
2371                                                                               \
2372     for (i = 0; i < nels; i++) {                                              \
2373         t.fld = tp##_##op(xa->fld, xb->fld, &env->fp_status);                 \
2374         if (unlikely(tp##_is_signaling_nan(xa->fld, &env->fp_status) ||       \
2375                      tp##_is_signaling_nan(xb->fld, &env->fp_status))) {      \
2376             float_invalid_op_vxsnan(env, GETPC());                            \
2377         }                                                                     \
2378     }                                                                         \
2379                                                                               \
2380     *xt = t;                                                                  \
2381     do_float_check_status(env, false, GETPC());                               \
2382 }
2383 
2384 VSX_MAX_MIN(XSMAXDP, maxnum, 1, float64, VsrD(0))
2385 VSX_MAX_MIN(XVMAXDP, maxnum, 2, float64, VsrD(i))
2386 VSX_MAX_MIN(XVMAXSP, maxnum, 4, float32, VsrW(i))
2387 VSX_MAX_MIN(XSMINDP, minnum, 1, float64, VsrD(0))
2388 VSX_MAX_MIN(XVMINDP, minnum, 2, float64, VsrD(i))
2389 VSX_MAX_MIN(XVMINSP, minnum, 4, float32, VsrW(i))
2390 
2391 #define VSX_MAX_MINC(name, max, tp, fld)                                      \
2392 void helper_##name(CPUPPCState *env,                                          \
2393                    ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb)               \
2394 {                                                                             \
2395     ppc_vsr_t t = { };                                                        \
2396     bool first;                                                               \
2397                                                                               \
2398     helper_reset_fpstatus(env);                                               \
2399                                                                               \
2400     if (max) {                                                                \
2401         first = tp##_le_quiet(xb->fld, xa->fld, &env->fp_status);             \
2402     } else {                                                                  \
2403         first = tp##_lt_quiet(xa->fld, xb->fld, &env->fp_status);             \
2404     }                                                                         \
2405                                                                               \
2406     if (first) {                                                              \
2407         t.fld = xa->fld;                                                      \
2408     } else {                                                                  \
2409         t.fld = xb->fld;                                                      \
2410         if (env->fp_status.float_exception_flags & float_flag_invalid_snan) { \
2411             float_invalid_op_vxsnan(env, GETPC());                            \
2412         }                                                                     \
2413     }                                                                         \
2414                                                                               \
2415     *xt = t;                                                                  \
2416 }
2417 
2418 VSX_MAX_MINC(XSMAXCDP, true, float64, VsrD(0));
2419 VSX_MAX_MINC(XSMINCDP, false, float64, VsrD(0));
2420 VSX_MAX_MINC(XSMAXCQP, true, float128, f128);
2421 VSX_MAX_MINC(XSMINCQP, false, float128, f128);
2422 
2423 #define VSX_MAX_MINJ(name, max)                                               \
2424 void helper_##name(CPUPPCState *env,                                          \
2425                    ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb)               \
2426 {                                                                             \
2427     ppc_vsr_t t = { };                                                        \
2428     bool vxsnan_flag = false, vex_flag = false;                               \
2429                                                                               \
2430     if (unlikely(float64_is_any_nan(xa->VsrD(0)))) {                          \
2431         if (float64_is_signaling_nan(xa->VsrD(0), &env->fp_status)) {         \
2432             vxsnan_flag = true;                                               \
2433         }                                                                     \
2434         t.VsrD(0) = xa->VsrD(0);                                              \
2435     } else if (unlikely(float64_is_any_nan(xb->VsrD(0)))) {                   \
2436         if (float64_is_signaling_nan(xb->VsrD(0), &env->fp_status)) {         \
2437             vxsnan_flag = true;                                               \
2438         }                                                                     \
2439         t.VsrD(0) = xb->VsrD(0);                                              \
2440     } else if (float64_is_zero(xa->VsrD(0)) &&                                \
2441                float64_is_zero(xb->VsrD(0))) {                                \
2442         if (max) {                                                            \
2443             if (!float64_is_neg(xa->VsrD(0)) ||                               \
2444                 !float64_is_neg(xb->VsrD(0))) {                               \
2445                 t.VsrD(0) = 0ULL;                                             \
2446             } else {                                                          \
2447                 t.VsrD(0) = 0x8000000000000000ULL;                            \
2448             }                                                                 \
2449         } else {                                                              \
2450             if (float64_is_neg(xa->VsrD(0)) ||                                \
2451                 float64_is_neg(xb->VsrD(0))) {                                \
2452                 t.VsrD(0) = 0x8000000000000000ULL;                            \
2453             } else {                                                          \
2454                 t.VsrD(0) = 0ULL;                                             \
2455             }                                                                 \
2456         }                                                                     \
2457     } else if ((max &&                                                        \
2458                !float64_lt(xa->VsrD(0), xb->VsrD(0), &env->fp_status)) ||     \
2459                (!max &&                                                       \
2460                float64_lt(xa->VsrD(0), xb->VsrD(0), &env->fp_status))) {      \
2461         t.VsrD(0) = xa->VsrD(0);                                              \
2462     } else {                                                                  \
2463         t.VsrD(0) = xb->VsrD(0);                                              \
2464     }                                                                         \
2465                                                                               \
2466     vex_flag = (env->fpscr & FP_VE) && vxsnan_flag;                           \
2467     if (vxsnan_flag) {                                                        \
2468         float_invalid_op_vxsnan(env, GETPC());                                \
2469     }                                                                         \
2470     if (!vex_flag) {                                                          \
2471         *xt = t;                                                              \
2472     }                                                                         \
2473 }                                                                             \
2474 
2475 VSX_MAX_MINJ(XSMAXJDP, 1);
2476 VSX_MAX_MINJ(XSMINJDP, 0);
2477 
2478 /*
2479  * VSX_CMP - VSX floating point compare
2480  *   op    - instruction mnemonic
2481  *   nels  - number of elements (1, 2 or 4)
2482  *   tp    - type (float32 or float64)
2483  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
2484  *   cmp   - comparison operation
2485  *   svxvc - set VXVC bit
2486  *   exp   - expected result of comparison
2487  */
2488 #define VSX_CMP(op, nels, tp, fld, cmp, svxvc, exp)                       \
2489 uint32_t helper_##op(CPUPPCState *env, ppc_vsr_t *xt,                     \
2490                      ppc_vsr_t *xa, ppc_vsr_t *xb)                        \
2491 {                                                                         \
2492     ppc_vsr_t t = *xt;                                                    \
2493     uint32_t crf6 = 0;                                                    \
2494     int i;                                                                \
2495     int all_true = 1;                                                     \
2496     int all_false = 1;                                                    \
2497                                                                           \
2498     helper_reset_fpstatus(env);                                           \
2499                                                                           \
2500     for (i = 0; i < nels; i++) {                                          \
2501         if (unlikely(tp##_is_any_nan(xa->fld) ||                          \
2502                      tp##_is_any_nan(xb->fld))) {                         \
2503             if (tp##_is_signaling_nan(xa->fld, &env->fp_status) ||        \
2504                 tp##_is_signaling_nan(xb->fld, &env->fp_status)) {        \
2505                 float_invalid_op_vxsnan(env, GETPC());                    \
2506             }                                                             \
2507             if (svxvc) {                                                  \
2508                 float_invalid_op_vxvc(env, 0, GETPC());                   \
2509             }                                                             \
2510             t.fld = 0;                                                    \
2511             all_true = 0;                                                 \
2512         } else {                                                          \
2513             if (tp##_##cmp(xb->fld, xa->fld, &env->fp_status) == exp) {   \
2514                 t.fld = -1;                                               \
2515                 all_false = 0;                                            \
2516             } else {                                                      \
2517                 t.fld = 0;                                                \
2518                 all_true = 0;                                             \
2519             }                                                             \
2520         }                                                                 \
2521     }                                                                     \
2522                                                                           \
2523     *xt = t;                                                              \
2524     crf6 = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0);                  \
2525     return crf6;                                                          \
2526 }
2527 
2528 VSX_CMP(XVCMPEQDP, 2, float64, VsrD(i), eq, 0, 1)
2529 VSX_CMP(XVCMPGEDP, 2, float64, VsrD(i), le, 1, 1)
2530 VSX_CMP(XVCMPGTDP, 2, float64, VsrD(i), lt, 1, 1)
2531 VSX_CMP(XVCMPNEDP, 2, float64, VsrD(i), eq, 0, 0)
2532 VSX_CMP(XVCMPEQSP, 4, float32, VsrW(i), eq, 0, 1)
2533 VSX_CMP(XVCMPGESP, 4, float32, VsrW(i), le, 1, 1)
2534 VSX_CMP(XVCMPGTSP, 4, float32, VsrW(i), lt, 1, 1)
2535 VSX_CMP(XVCMPNESP, 4, float32, VsrW(i), eq, 0, 0)
2536 
2537 /*
2538  * VSX_CVT_FP_TO_FP - VSX floating point/floating point conversion
2539  *   op    - instruction mnemonic
2540  *   nels  - number of elements (1, 2 or 4)
2541  *   stp   - source type (float32 or float64)
2542  *   ttp   - target type (float32 or float64)
2543  *   sfld  - source vsr_t field
2544  *   tfld  - target vsr_t field (f32 or f64)
2545  *   sfifprf - set FI and FPRF
2546  */
2547 #define VSX_CVT_FP_TO_FP(op, nels, stp, ttp, sfld, tfld, sfifprf)  \
2548 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)   \
2549 {                                                                  \
2550     ppc_vsr_t t = { };                                             \
2551     int i;                                                         \
2552                                                                    \
2553     helper_reset_fpstatus(env);                                    \
2554                                                                    \
2555     for (i = 0; i < nels; i++) {                                   \
2556         t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status);        \
2557         if (unlikely(stp##_is_signaling_nan(xb->sfld,              \
2558                                             &env->fp_status))) {   \
2559             float_invalid_op_vxsnan(env, GETPC());                 \
2560             t.tfld = ttp##_snan_to_qnan(t.tfld);                   \
2561         }                                                          \
2562         if (sfifprf) {                                             \
2563             helper_compute_fprf_##ttp(env, t.tfld);                \
2564         }                                                          \
2565     }                                                              \
2566                                                                    \
2567     *xt = t;                                                       \
2568     do_float_check_status(env, sfifprf, GETPC());                  \
2569 }
2570 
2571 VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, VsrW(0), VsrD(0), 1)
2572 VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, VsrW(2 * i), VsrD(i), 0)
2573 
2574 #define VSX_CVT_FP_TO_FP2(op, nels, stp, ttp, sfifprf)                \
2575 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)      \
2576 {                                                                     \
2577     ppc_vsr_t t = { };                                                \
2578     int i;                                                            \
2579                                                                       \
2580     helper_reset_fpstatus(env);                                       \
2581                                                                       \
2582     for (i = 0; i < nels; i++) {                                      \
2583         t.VsrW(2 * i) = stp##_to_##ttp(xb->VsrD(i), &env->fp_status); \
2584         if (unlikely(stp##_is_signaling_nan(xb->VsrD(i),              \
2585                                             &env->fp_status))) {      \
2586             float_invalid_op_vxsnan(env, GETPC());                    \
2587             t.VsrW(2 * i) = ttp##_snan_to_qnan(t.VsrW(2 * i));        \
2588         }                                                             \
2589         if (sfifprf) {                                                \
2590             helper_compute_fprf_##ttp(env, t.VsrW(2 * i));            \
2591         }                                                             \
2592         t.VsrW(2 * i + 1) = t.VsrW(2 * i);                            \
2593     }                                                                 \
2594                                                                       \
2595     *xt = t;                                                          \
2596     do_float_check_status(env, sfifprf, GETPC());                     \
2597 }
2598 
2599 VSX_CVT_FP_TO_FP2(xvcvdpsp, 2, float64, float32, 0)
2600 VSX_CVT_FP_TO_FP2(xscvdpsp, 1, float64, float32, 1)
2601 
2602 /*
2603  * VSX_CVT_FP_TO_FP_VECTOR - VSX floating point/floating point conversion
2604  *   op    - instruction mnemonic
2605  *   nels  - number of elements (1, 2 or 4)
2606  *   stp   - source type (float32 or float64)
2607  *   ttp   - target type (float32 or float64)
2608  *   sfld  - source vsr_t field
2609  *   tfld  - target vsr_t field (f32 or f64)
2610  *   sfprf - set FPRF
2611  */
2612 #define VSX_CVT_FP_TO_FP_VECTOR(op, nels, stp, ttp, sfld, tfld, sfprf)  \
2613 void helper_##op(CPUPPCState *env, uint32_t opcode,                     \
2614                  ppc_vsr_t *xt, ppc_vsr_t *xb)                          \
2615 {                                                                       \
2616     ppc_vsr_t t = *xt;                                                  \
2617     int i;                                                              \
2618                                                                         \
2619     helper_reset_fpstatus(env);                                         \
2620                                                                         \
2621     for (i = 0; i < nels; i++) {                                        \
2622         t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status);             \
2623         if (unlikely(stp##_is_signaling_nan(xb->sfld,                   \
2624                                             &env->fp_status))) {        \
2625             float_invalid_op_vxsnan(env, GETPC());                      \
2626             t.tfld = ttp##_snan_to_qnan(t.tfld);                        \
2627         }                                                               \
2628         if (sfprf) {                                                    \
2629             helper_compute_fprf_##ttp(env, t.tfld);                     \
2630         }                                                               \
2631     }                                                                   \
2632                                                                         \
2633     *xt = t;                                                            \
2634     do_float_check_status(env, true, GETPC());                          \
2635 }
2636 
2637 VSX_CVT_FP_TO_FP_VECTOR(xscvdpqp, 1, float64, float128, VsrD(0), f128, 1)
2638 
2639 /*
2640  * VSX_CVT_FP_TO_FP_HP - VSX floating point/floating point conversion
2641  *                       involving one half precision value
2642  *   op    - instruction mnemonic
2643  *   nels  - number of elements (1, 2 or 4)
2644  *   stp   - source type
2645  *   ttp   - target type
2646  *   sfld  - source vsr_t field
2647  *   tfld  - target vsr_t field
2648  *   sfifprf - set FI and FPRF
2649  */
2650 #define VSX_CVT_FP_TO_FP_HP(op, nels, stp, ttp, sfld, tfld, sfifprf) \
2651 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)   \
2652 {                                                                  \
2653     ppc_vsr_t t = { };                                             \
2654     int i;                                                         \
2655                                                                    \
2656     helper_reset_fpstatus(env);                                    \
2657                                                                    \
2658     for (i = 0; i < nels; i++) {                                   \
2659         t.tfld = stp##_to_##ttp(xb->sfld, 1, &env->fp_status);     \
2660         if (unlikely(stp##_is_signaling_nan(xb->sfld,              \
2661                                             &env->fp_status))) {   \
2662             float_invalid_op_vxsnan(env, GETPC());                 \
2663             t.tfld = ttp##_snan_to_qnan(t.tfld);                   \
2664         }                                                          \
2665         if (sfifprf) {                                             \
2666             helper_compute_fprf_##ttp(env, t.tfld);                \
2667         }                                                          \
2668     }                                                              \
2669                                                                    \
2670     *xt = t;                                                       \
2671     do_float_check_status(env, sfifprf, GETPC());                  \
2672 }
2673 
2674 VSX_CVT_FP_TO_FP_HP(xscvdphp, 1, float64, float16, VsrD(0), VsrH(3), 1)
2675 VSX_CVT_FP_TO_FP_HP(xscvhpdp, 1, float16, float64, VsrH(3), VsrD(0), 1)
2676 VSX_CVT_FP_TO_FP_HP(xvcvsphp, 4, float32, float16, VsrW(i), VsrH(2 * i  + 1), 0)
2677 VSX_CVT_FP_TO_FP_HP(xvcvhpsp, 4, float16, float32, VsrH(2 * i + 1), VsrW(i), 0)
2678 
helper_XVCVSPBF16(CPUPPCState * env,ppc_vsr_t * xt,ppc_vsr_t * xb)2679 void helper_XVCVSPBF16(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)
2680 {
2681     ppc_vsr_t t = { };
2682     int i, status;
2683 
2684     helper_reset_fpstatus(env);
2685 
2686     for (i = 0; i < 4; i++) {
2687         t.VsrH(2 * i + 1) = float32_to_bfloat16(xb->VsrW(i), &env->fp_status);
2688     }
2689 
2690     status = get_float_exception_flags(&env->fp_status);
2691     if (unlikely(status & float_flag_invalid_snan)) {
2692         float_invalid_op_vxsnan(env, GETPC());
2693     }
2694 
2695     *xt = t;
2696     do_float_check_status(env, false, GETPC());
2697 }
2698 
helper_XSCVQPDP(CPUPPCState * env,uint32_t ro,ppc_vsr_t * xt,ppc_vsr_t * xb)2699 void helper_XSCVQPDP(CPUPPCState *env, uint32_t ro, ppc_vsr_t *xt,
2700                      ppc_vsr_t *xb)
2701 {
2702     ppc_vsr_t t = { };
2703     float_status tstat;
2704 
2705     helper_reset_fpstatus(env);
2706 
2707     tstat = env->fp_status;
2708     if (ro != 0) {
2709         tstat.float_rounding_mode = float_round_to_odd;
2710     }
2711 
2712     t.VsrD(0) = float128_to_float64(xb->f128, &tstat);
2713     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
2714     if (unlikely(float128_is_signaling_nan(xb->f128, &tstat))) {
2715         float_invalid_op_vxsnan(env, GETPC());
2716         t.VsrD(0) = float64_snan_to_qnan(t.VsrD(0));
2717     }
2718     helper_compute_fprf_float64(env, t.VsrD(0));
2719 
2720     *xt = t;
2721     do_float_check_status(env, true, GETPC());
2722 }
2723 
helper_xscvdpspn(CPUPPCState * env,uint64_t xb)2724 uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
2725 {
2726     uint64_t result, sign, exp, frac;
2727 
2728     helper_reset_fpstatus(env);
2729     float_status tstat = env->fp_status;
2730     set_float_exception_flags(0, &tstat);
2731 
2732     sign = extract64(xb, 63,  1);
2733     exp  = extract64(xb, 52, 11);
2734     frac = extract64(xb,  0, 52) | 0x10000000000000ULL;
2735 
2736     if (unlikely(exp == 0 && extract64(frac, 0, 52) != 0)) {
2737         /* DP denormal operand.  */
2738         /* Exponent override to DP min exp.  */
2739         exp = 1;
2740         /* Implicit bit override to 0.  */
2741         frac = deposit64(frac, 53, 1, 0);
2742     }
2743 
2744     if (unlikely(exp < 897 && frac != 0)) {
2745         /* SP tiny operand.  */
2746         if (897 - exp > 63) {
2747             frac = 0;
2748         } else {
2749             /* Denormalize until exp = SP min exp.  */
2750             frac >>= (897 - exp);
2751         }
2752         /* Exponent override to SP min exp - 1.  */
2753         exp = 896;
2754     }
2755 
2756     result = sign << 31;
2757     result |= extract64(exp, 10, 1) << 30;
2758     result |= extract64(exp, 0, 7) << 23;
2759     result |= extract64(frac, 29, 23);
2760 
2761     /* hardware replicates result to both words of the doubleword result.  */
2762     return (result << 32) | result;
2763 }
2764 
helper_XSCVSPDPN(uint64_t xb)2765 uint64_t helper_XSCVSPDPN(uint64_t xb)
2766 {
2767     return helper_todouble(xb >> 32);
2768 }
2769 
2770 /*
2771  * VSX_CVT_FP_TO_INT - VSX floating point to integer conversion
2772  *   op    - instruction mnemonic
2773  *   nels  - number of elements (1, 2 or 4)
2774  *   stp   - source type (float32 or float64)
2775  *   ttp   - target type (int32, uint32, int64 or uint64)
2776  *   sfld  - source vsr_t field
2777  *   tfld  - target vsr_t field
2778  *   sfi   - set FI
2779  *   rnan  - resulting NaN
2780  */
2781 #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, sfi, rnan)         \
2782 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)             \
2783 {                                                                            \
2784     int all_flags = 0;                                                       \
2785     ppc_vsr_t t = { };                                                       \
2786     int i, flags;                                                            \
2787                                                                              \
2788     for (i = 0; i < nels; i++) {                                             \
2789         helper_reset_fpstatus(env);                                          \
2790         t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status);  \
2791         flags = env->fp_status.float_exception_flags;                        \
2792         all_flags |= flags;                                                  \
2793         if (unlikely(flags & float_flag_invalid)) {                          \
2794             t.tfld = float_invalid_cvt(env, flags, t.tfld, rnan, 0, GETPC());\
2795         }                                                                    \
2796     }                                                                        \
2797                                                                              \
2798     *xt = t;                                                                 \
2799     env->fp_status.float_exception_flags = all_flags;                        \
2800     do_float_check_status(env, sfi, GETPC());                                \
2801 }
2802 
2803 VSX_CVT_FP_TO_INT(xscvdpsxds, 1, float64, int64, VsrD(0), VsrD(0), true, \
2804                   0x8000000000000000ULL)
2805 VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, VsrD(0), VsrD(0), true, 0ULL)
2806 VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, VsrD(i), VsrD(i), false, \
2807                   0x8000000000000000ULL)
2808 VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, VsrD(i), VsrD(i), false, \
2809                   0ULL)
2810 VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, VsrW(2 * i), VsrD(i), false, \
2811                   0x8000000000000000ULL)
2812 VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), false, \
2813                   0x80000000ULL)
2814 VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2 * i), VsrD(i), \
2815                   false, 0ULL)
2816 VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), false, 0U)
2817 
2818 #define VSX_CVT_FP_TO_INT128(op, tp, rnan)                                     \
2819 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)               \
2820 {                                                                              \
2821     ppc_vsr_t t;                                                               \
2822     int flags;                                                                 \
2823                                                                                \
2824     helper_reset_fpstatus(env);                                                \
2825     t.s128 = float128_to_##tp##_round_to_zero(xb->f128, &env->fp_status);      \
2826     flags = get_float_exception_flags(&env->fp_status);                        \
2827     if (unlikely(flags & float_flag_invalid)) {                                \
2828         t.VsrD(0) = float_invalid_cvt(env, flags, t.VsrD(0), rnan, 0, GETPC());\
2829         t.VsrD(1) = -(t.VsrD(0) & 1);                                          \
2830     }                                                                          \
2831                                                                                \
2832     *xt = t;                                                                   \
2833     do_float_check_status(env, true, GETPC());                                 \
2834 }
2835 
2836 VSX_CVT_FP_TO_INT128(XSCVQPUQZ, uint128, 0)
2837 VSX_CVT_FP_TO_INT128(XSCVQPSQZ, int128, 0x8000000000000000ULL);
2838 
2839 /*
2840  * Likewise, except that the result is duplicated into both subwords.
2841  * Power ISA v3.1 has Programming Notes for these insns:
2842  *     Previous versions of the architecture allowed the contents of
2843  *     word 0 of the result register to be undefined. However, all
2844  *     processors that support this instruction write the result into
2845  *     words 0 and 1 (and words 2 and 3) of the result register, as
2846  *     is required by this version of the architecture.
2847  */
2848 #define VSX_CVT_FP_TO_INT2(op, nels, stp, ttp, sfi, rnan)                    \
2849 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)             \
2850 {                                                                            \
2851     int all_flags = 0;                                                       \
2852     ppc_vsr_t t = { };                                                       \
2853     int i, flags;                                                            \
2854                                                                              \
2855     for (i = 0; i < nels; i++) {                                             \
2856         helper_reset_fpstatus(env);                                          \
2857         t.VsrW(2 * i) = stp##_to_##ttp##_round_to_zero(xb->VsrD(i),          \
2858                                                        &env->fp_status);     \
2859         flags = env->fp_status.float_exception_flags;                        \
2860         all_flags |= flags;                                                  \
2861         if (unlikely(flags & float_flag_invalid)) {                          \
2862             t.VsrW(2 * i) = float_invalid_cvt(env, flags, t.VsrW(2 * i),     \
2863                                               rnan, 0, GETPC());             \
2864         }                                                                    \
2865         t.VsrW(2 * i + 1) = t.VsrW(2 * i);                                   \
2866     }                                                                        \
2867                                                                              \
2868     *xt = t;                                                                 \
2869     env->fp_status.float_exception_flags = all_flags;                        \
2870     do_float_check_status(env, sfi, GETPC());                                \
2871 }
2872 
2873 VSX_CVT_FP_TO_INT2(xscvdpsxws, 1, float64, int32, true, 0x80000000U)
2874 VSX_CVT_FP_TO_INT2(xscvdpuxws, 1, float64, uint32, true, 0U)
2875 VSX_CVT_FP_TO_INT2(xvcvdpsxws, 2, float64, int32, false, 0x80000000U)
2876 VSX_CVT_FP_TO_INT2(xvcvdpuxws, 2, float64, uint32, false, 0U)
2877 
2878 /*
2879  * VSX_CVT_FP_TO_INT_VECTOR - VSX floating point to integer conversion
2880  *   op    - instruction mnemonic
2881  *   stp   - source type (float32 or float64)
2882  *   ttp   - target type (int32, uint32, int64 or uint64)
2883  *   sfld  - source vsr_t field
2884  *   tfld  - target vsr_t field
2885  *   rnan  - resulting NaN
2886  */
2887 #define VSX_CVT_FP_TO_INT_VECTOR(op, stp, ttp, sfld, tfld, rnan)             \
2888 void helper_##op(CPUPPCState *env, uint32_t opcode,                          \
2889                  ppc_vsr_t *xt, ppc_vsr_t *xb)                               \
2890 {                                                                            \
2891     ppc_vsr_t t = { };                                                       \
2892     int flags;                                                               \
2893                                                                              \
2894     helper_reset_fpstatus(env);                                              \
2895                                                                              \
2896     t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status);      \
2897     flags = get_float_exception_flags(&env->fp_status);                      \
2898     if (flags & float_flag_invalid) {                                        \
2899         t.tfld = float_invalid_cvt(env, flags, t.tfld, rnan, 0, GETPC());    \
2900     }                                                                        \
2901                                                                              \
2902     *xt = t;                                                                 \
2903     do_float_check_status(env, true, GETPC());                               \
2904 }
2905 
2906 VSX_CVT_FP_TO_INT_VECTOR(xscvqpsdz, float128, int64, f128, VsrD(0),          \
2907                   0x8000000000000000ULL)
2908 VSX_CVT_FP_TO_INT_VECTOR(xscvqpswz, float128, int32, f128, VsrD(0),          \
2909                   0xffffffff80000000ULL)
2910 VSX_CVT_FP_TO_INT_VECTOR(xscvqpudz, float128, uint64, f128, VsrD(0), 0x0ULL)
2911 VSX_CVT_FP_TO_INT_VECTOR(xscvqpuwz, float128, uint32, f128, VsrD(0), 0x0ULL)
2912 
2913 /*
2914  * VSX_CVT_INT_TO_FP - VSX integer to floating point conversion
2915  *   op    - instruction mnemonic
2916  *   nels  - number of elements (1, 2 or 4)
2917  *   stp   - source type (int32, uint32, int64 or uint64)
2918  *   ttp   - target type (float32 or float64)
2919  *   sfld  - source vsr_t field
2920  *   tfld  - target vsr_t field
2921  *   jdef  - definition of the j index (i or 2*i)
2922  *   sfifprf - set FI and FPRF
2923  */
2924 #define VSX_CVT_INT_TO_FP(op, nels, stp, ttp, sfld, tfld, sfifprf, r2sp)\
2925 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)        \
2926 {                                                                       \
2927     ppc_vsr_t t = { };                                                  \
2928     int i;                                                              \
2929                                                                         \
2930     helper_reset_fpstatus(env);                                         \
2931                                                                         \
2932     for (i = 0; i < nels; i++) {                                        \
2933         t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status);             \
2934         if (r2sp) {                                                     \
2935             t.tfld = do_frsp(env, t.tfld, GETPC());                     \
2936         }                                                               \
2937         if (sfifprf) {                                                  \
2938             helper_compute_fprf_float64(env, t.tfld);                   \
2939         }                                                               \
2940     }                                                                   \
2941                                                                         \
2942     *xt = t;                                                            \
2943     do_float_check_status(env, sfifprf, GETPC());                       \
2944 }
2945 
2946 VSX_CVT_INT_TO_FP(xscvsxddp, 1, int64, float64, VsrD(0), VsrD(0), 1, 0)
2947 VSX_CVT_INT_TO_FP(xscvuxddp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 0)
2948 VSX_CVT_INT_TO_FP(xscvsxdsp, 1, int64, float64, VsrD(0), VsrD(0), 1, 1)
2949 VSX_CVT_INT_TO_FP(xscvuxdsp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 1)
2950 VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, VsrD(i), VsrD(i), 0, 0)
2951 VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, VsrD(i), VsrD(i), 0, 0)
2952 VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, VsrW(2 * i), VsrD(i), 0, 0)
2953 VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, VsrW(2 * i), VsrD(i), 0, 0)
2954 VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, VsrW(i), VsrW(i), 0, 0)
2955 VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, VsrW(i), VsrW(i), 0, 0)
2956 
2957 #define VSX_CVT_INT_TO_FP2(op, stp, ttp)                                \
2958 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)        \
2959 {                                                                       \
2960     ppc_vsr_t t = { };                                                  \
2961     int i;                                                              \
2962                                                                         \
2963     for (i = 0; i < 2; i++) {                                           \
2964         t.VsrW(2 * i) = stp##_to_##ttp(xb->VsrD(i), &env->fp_status);   \
2965         t.VsrW(2 * i + 1) = t.VsrW(2 * i);                              \
2966     }                                                                   \
2967                                                                         \
2968     *xt = t;                                                            \
2969     do_float_check_status(env, false, GETPC());                         \
2970 }
2971 
2972 VSX_CVT_INT_TO_FP2(xvcvsxdsp, int64, float32)
2973 VSX_CVT_INT_TO_FP2(xvcvuxdsp, uint64, float32)
2974 
2975 #define VSX_CVT_INT128_TO_FP(op, tp)                            \
2976 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)\
2977 {                                                               \
2978     helper_reset_fpstatus(env);                                 \
2979     xt->f128 = tp##_to_float128(xb->s128, &env->fp_status);     \
2980     helper_compute_fprf_float128(env, xt->f128);                \
2981     do_float_check_status(env, true, GETPC());                  \
2982 }
2983 
2984 VSX_CVT_INT128_TO_FP(XSCVUQQP, uint128);
2985 VSX_CVT_INT128_TO_FP(XSCVSQQP, int128);
2986 
2987 /*
2988  * VSX_CVT_INT_TO_FP_VECTOR - VSX integer to floating point conversion
2989  *   op    - instruction mnemonic
2990  *   stp   - source type (int32, uint32, int64 or uint64)
2991  *   ttp   - target type (float32 or float64)
2992  *   sfld  - source vsr_t field
2993  *   tfld  - target vsr_t field
2994  */
2995 #define VSX_CVT_INT_TO_FP_VECTOR(op, stp, ttp, sfld, tfld)              \
2996 void helper_##op(CPUPPCState *env, uint32_t opcode,                     \
2997                  ppc_vsr_t *xt, ppc_vsr_t *xb)                          \
2998 {                                                                       \
2999     ppc_vsr_t t = *xt;                                                  \
3000                                                                         \
3001     helper_reset_fpstatus(env);                                         \
3002     t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status);                 \
3003     helper_compute_fprf_##ttp(env, t.tfld);                             \
3004                                                                         \
3005     *xt = t;                                                            \
3006     do_float_check_status(env, true, GETPC());                          \
3007 }
3008 
3009 VSX_CVT_INT_TO_FP_VECTOR(xscvsdqp, int64, float128, VsrD(0), f128)
3010 VSX_CVT_INT_TO_FP_VECTOR(xscvudqp, uint64, float128, VsrD(0), f128)
3011 
3012 /*
3013  * For "use current rounding mode", define a value that will not be
3014  * one of the existing rounding model enums.
3015  */
3016 #define FLOAT_ROUND_CURRENT (float_round_nearest_even + float_round_down + \
3017   float_round_up + float_round_to_zero)
3018 
3019 /*
3020  * VSX_ROUND - VSX floating point round
3021  *   op    - instruction mnemonic
3022  *   nels  - number of elements (1, 2 or 4)
3023  *   tp    - type (float32 or float64)
3024  *   fld   - vsr_t field (VsrD(*) or VsrW(*))
3025  *   rmode - rounding mode
3026  *   sfifprf - set FI and FPRF
3027  */
3028 #define VSX_ROUND(op, nels, tp, fld, rmode, sfifprf)                   \
3029 void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)       \
3030 {                                                                      \
3031     ppc_vsr_t t = { };                                                 \
3032     int i;                                                             \
3033     FloatRoundMode curr_rounding_mode;                                 \
3034                                                                        \
3035     helper_reset_fpstatus(env);                                        \
3036                                                                        \
3037     if (rmode != FLOAT_ROUND_CURRENT) {                                \
3038         curr_rounding_mode = get_float_rounding_mode(&env->fp_status); \
3039         set_float_rounding_mode(rmode, &env->fp_status);               \
3040     }                                                                  \
3041                                                                        \
3042     for (i = 0; i < nels; i++) {                                       \
3043         if (unlikely(tp##_is_signaling_nan(xb->fld,                    \
3044                                            &env->fp_status))) {        \
3045             float_invalid_op_vxsnan(env, GETPC());                     \
3046             t.fld = tp##_snan_to_qnan(xb->fld);                        \
3047         } else {                                                       \
3048             t.fld = tp##_round_to_int(xb->fld, &env->fp_status);       \
3049         }                                                              \
3050         if (sfifprf) {                                                 \
3051             helper_compute_fprf_float64(env, t.fld);                   \
3052         }                                                              \
3053     }                                                                  \
3054                                                                        \
3055     /*                                                                 \
3056      * If this is not a "use current rounding mode" instruction,       \
3057      * then inhibit setting of the XX bit and restore rounding         \
3058      * mode from FPSCR                                                 \
3059      */                                                                \
3060     if (rmode != FLOAT_ROUND_CURRENT) {                                \
3061         set_float_rounding_mode(curr_rounding_mode, &env->fp_status);  \
3062         env->fp_status.float_exception_flags &= ~float_flag_inexact;   \
3063     }                                                                  \
3064                                                                        \
3065     *xt = t;                                                           \
3066     do_float_check_status(env, sfifprf, GETPC());                      \
3067 }
3068 
3069 VSX_ROUND(xsrdpi, 1, float64, VsrD(0), float_round_ties_away, 1)
3070 VSX_ROUND(xsrdpic, 1, float64, VsrD(0), FLOAT_ROUND_CURRENT, 1)
3071 VSX_ROUND(xsrdpim, 1, float64, VsrD(0), float_round_down, 1)
3072 VSX_ROUND(xsrdpip, 1, float64, VsrD(0), float_round_up, 1)
3073 VSX_ROUND(xsrdpiz, 1, float64, VsrD(0), float_round_to_zero, 1)
3074 
3075 VSX_ROUND(xvrdpi, 2, float64, VsrD(i), float_round_ties_away, 0)
3076 VSX_ROUND(xvrdpic, 2, float64, VsrD(i), FLOAT_ROUND_CURRENT, 0)
3077 VSX_ROUND(xvrdpim, 2, float64, VsrD(i), float_round_down, 0)
3078 VSX_ROUND(xvrdpip, 2, float64, VsrD(i), float_round_up, 0)
3079 VSX_ROUND(xvrdpiz, 2, float64, VsrD(i), float_round_to_zero, 0)
3080 
3081 VSX_ROUND(xvrspi, 4, float32, VsrW(i), float_round_ties_away, 0)
3082 VSX_ROUND(xvrspic, 4, float32, VsrW(i), FLOAT_ROUND_CURRENT, 0)
3083 VSX_ROUND(xvrspim, 4, float32, VsrW(i), float_round_down, 0)
3084 VSX_ROUND(xvrspip, 4, float32, VsrW(i), float_round_up, 0)
3085 VSX_ROUND(xvrspiz, 4, float32, VsrW(i), float_round_to_zero, 0)
3086 
helper_xsrsp(CPUPPCState * env,uint64_t xb)3087 uint64_t helper_xsrsp(CPUPPCState *env, uint64_t xb)
3088 {
3089     helper_reset_fpstatus(env);
3090 
3091     uint64_t xt = do_frsp(env, xb, GETPC());
3092 
3093     helper_compute_fprf_float64(env, xt);
3094     do_float_check_status(env, true, GETPC());
3095     return xt;
3096 }
3097 
helper_XVXSIGSP(ppc_vsr_t * xt,ppc_vsr_t * xb)3098 void helper_XVXSIGSP(ppc_vsr_t *xt, ppc_vsr_t *xb)
3099 {
3100     ppc_vsr_t t = { };
3101     uint32_t exp, i, fraction;
3102 
3103     for (i = 0; i < 4; i++) {
3104         exp = (xb->VsrW(i) >> 23) & 0xFF;
3105         fraction = xb->VsrW(i) & 0x7FFFFF;
3106         if (exp != 0 && exp != 255) {
3107             t.VsrW(i) = fraction | 0x00800000;
3108         } else {
3109             t.VsrW(i) = fraction;
3110         }
3111     }
3112     *xt = t;
3113 }
3114 
3115 #define VSX_TSTDC(tp)                                       \
3116 static int32_t tp##_tstdc(tp b, uint32_t dcmx)              \
3117 {                                                           \
3118     uint32_t match = 0;                                     \
3119     uint32_t sign = tp##_is_neg(b);                         \
3120     if (tp##_is_any_nan(b)) {                               \
3121         match = extract32(dcmx, 6, 1);                      \
3122     } else if (tp##_is_infinity(b)) {                       \
3123         match = extract32(dcmx, 4 + !sign, 1);              \
3124     } else if (tp##_is_zero(b)) {                           \
3125         match = extract32(dcmx, 2 + !sign, 1);              \
3126     } else if (tp##_is_zero_or_denormal(b)) {               \
3127         match = extract32(dcmx, 0 + !sign, 1);              \
3128     }                                                       \
3129     return (match != 0);                                    \
3130 }
3131 
3132 VSX_TSTDC(float32)
VSX_TSTDC(float64)3133 VSX_TSTDC(float64)
3134 VSX_TSTDC(float128)
3135 #undef VSX_TSTDC
3136 
3137 void helper_XVTSTDCDP(ppc_vsr_t *t, ppc_vsr_t *b, uint64_t dcmx, uint32_t v)
3138 {
3139     int i;
3140     for (i = 0; i < 2; i++) {
3141         t->s64[i] = (int64_t)-float64_tstdc(b->f64[i], dcmx);
3142     }
3143 }
3144 
helper_XVTSTDCSP(ppc_vsr_t * t,ppc_vsr_t * b,uint64_t dcmx,uint32_t v)3145 void helper_XVTSTDCSP(ppc_vsr_t *t, ppc_vsr_t *b, uint64_t dcmx, uint32_t v)
3146 {
3147     int i;
3148     for (i = 0; i < 4; i++) {
3149         t->s32[i] = (int32_t)-float32_tstdc(b->f32[i], dcmx);
3150     }
3151 }
3152 
not_SP_value(float64 val)3153 static bool not_SP_value(float64 val)
3154 {
3155     return val != helper_todouble(helper_tosingle(val));
3156 }
3157 
3158 /*
3159  * VSX_XS_TSTDC - VSX Scalar Test Data Class
3160  *   NAME  - instruction name
3161  *   FLD   - vsr_t field (VsrD(0) or f128)
3162  *   TP    - type (float64 or float128)
3163  */
3164 #define VSX_XS_TSTDC(NAME, FLD, TP)                                         \
3165     void helper_##NAME(CPUPPCState *env, uint32_t bf,                       \
3166                        uint32_t dcmx, ppc_vsr_t *b)                         \
3167     {                                                                       \
3168         uint32_t cc, match, sign = TP##_is_neg(b->FLD);                     \
3169         match = TP##_tstdc(b->FLD, dcmx);                                   \
3170         cc = sign << CRF_LT_BIT | match << CRF_EQ_BIT;                      \
3171         env->fpscr &= ~FP_FPCC;                                             \
3172         env->fpscr |= cc << FPSCR_FPCC;                                     \
3173         env->crf[bf] = cc;                                                  \
3174     }
3175 
3176 VSX_XS_TSTDC(XSTSTDCDP, VsrD(0), float64)
VSX_XS_TSTDC(XSTSTDCQP,f128,float128)3177 VSX_XS_TSTDC(XSTSTDCQP, f128, float128)
3178 #undef VSX_XS_TSTDC
3179 
3180 void helper_XSTSTDCSP(CPUPPCState *env, uint32_t bf,
3181                       uint32_t dcmx, ppc_vsr_t *b)
3182 {
3183     uint32_t cc, match, sign = float64_is_neg(b->VsrD(0));
3184     uint32_t exp = (b->VsrD(0) >> 52) & 0x7FF;
3185     int not_sp = (int)not_SP_value(b->VsrD(0));
3186     match = float64_tstdc(b->VsrD(0), dcmx) || (exp > 0 && exp < 0x381);
3187     cc = sign << CRF_LT_BIT | match << CRF_EQ_BIT | not_sp << CRF_SO_BIT;
3188     env->fpscr &= ~FP_FPCC;
3189     env->fpscr |= cc << FPSCR_FPCC;
3190     env->crf[bf] = cc;
3191 }
3192 
helper_xsrqpi(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xt,ppc_vsr_t * xb)3193 void helper_xsrqpi(CPUPPCState *env, uint32_t opcode,
3194                    ppc_vsr_t *xt, ppc_vsr_t *xb)
3195 {
3196     ppc_vsr_t t = { };
3197     uint8_t r = Rrm(opcode);
3198     uint8_t ex = Rc(opcode);
3199     uint8_t rmc = RMC(opcode);
3200     uint8_t rmode = 0;
3201     float_status tstat;
3202 
3203     helper_reset_fpstatus(env);
3204 
3205     if (r == 0 && rmc == 0) {
3206         rmode = float_round_ties_away;
3207     } else if (r == 0 && rmc == 0x3) {
3208         rmode = env->fpscr & FP_RN;
3209     } else if (r == 1) {
3210         switch (rmc) {
3211         case 0:
3212             rmode = float_round_nearest_even;
3213             break;
3214         case 1:
3215             rmode = float_round_to_zero;
3216             break;
3217         case 2:
3218             rmode = float_round_up;
3219             break;
3220         case 3:
3221             rmode = float_round_down;
3222             break;
3223         default:
3224             abort();
3225         }
3226     }
3227 
3228     tstat = env->fp_status;
3229     set_float_exception_flags(0, &tstat);
3230     set_float_rounding_mode(rmode, &tstat);
3231     t.f128 = float128_round_to_int(xb->f128, &tstat);
3232     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
3233 
3234     if (unlikely(tstat.float_exception_flags & float_flag_invalid_snan)) {
3235         float_invalid_op_vxsnan(env, GETPC());
3236     }
3237 
3238     if (ex == 0 && (tstat.float_exception_flags & float_flag_inexact)) {
3239         env->fp_status.float_exception_flags &= ~float_flag_inexact;
3240     }
3241 
3242     helper_compute_fprf_float128(env, t.f128);
3243     do_float_check_status(env, true, GETPC());
3244     *xt = t;
3245 }
3246 
helper_xsrqpxp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xt,ppc_vsr_t * xb)3247 void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode,
3248                     ppc_vsr_t *xt, ppc_vsr_t *xb)
3249 {
3250     ppc_vsr_t t = { };
3251     uint8_t r = Rrm(opcode);
3252     uint8_t rmc = RMC(opcode);
3253     uint8_t rmode = 0;
3254     floatx80 round_res;
3255     float_status tstat;
3256 
3257     helper_reset_fpstatus(env);
3258 
3259     if (r == 0 && rmc == 0) {
3260         rmode = float_round_ties_away;
3261     } else if (r == 0 && rmc == 0x3) {
3262         rmode = env->fpscr & FP_RN;
3263     } else if (r == 1) {
3264         switch (rmc) {
3265         case 0:
3266             rmode = float_round_nearest_even;
3267             break;
3268         case 1:
3269             rmode = float_round_to_zero;
3270             break;
3271         case 2:
3272             rmode = float_round_up;
3273             break;
3274         case 3:
3275             rmode = float_round_down;
3276             break;
3277         default:
3278             abort();
3279         }
3280     }
3281 
3282     tstat = env->fp_status;
3283     set_float_exception_flags(0, &tstat);
3284     set_float_rounding_mode(rmode, &tstat);
3285     round_res = float128_to_floatx80(xb->f128, &tstat);
3286     t.f128 = floatx80_to_float128(round_res, &tstat);
3287     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
3288 
3289     if (unlikely(tstat.float_exception_flags & float_flag_invalid_snan)) {
3290         float_invalid_op_vxsnan(env, GETPC());
3291         t.f128 = float128_snan_to_qnan(t.f128);
3292     }
3293 
3294     helper_compute_fprf_float128(env, t.f128);
3295     *xt = t;
3296     do_float_check_status(env, true, GETPC());
3297 }
3298 
helper_xssqrtqp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xt,ppc_vsr_t * xb)3299 void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode,
3300                      ppc_vsr_t *xt, ppc_vsr_t *xb)
3301 {
3302     ppc_vsr_t t = { };
3303     float_status tstat;
3304 
3305     helper_reset_fpstatus(env);
3306 
3307     tstat = env->fp_status;
3308     if (unlikely(Rc(opcode) != 0)) {
3309         tstat.float_rounding_mode = float_round_to_odd;
3310     }
3311 
3312     set_float_exception_flags(0, &tstat);
3313     t.f128 = float128_sqrt(xb->f128, &tstat);
3314     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
3315 
3316     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
3317         float_invalid_op_sqrt(env, tstat.float_exception_flags, 1, GETPC());
3318     }
3319 
3320     helper_compute_fprf_float128(env, t.f128);
3321     *xt = t;
3322     do_float_check_status(env, true, GETPC());
3323 }
3324 
helper_xssubqp(CPUPPCState * env,uint32_t opcode,ppc_vsr_t * xt,ppc_vsr_t * xa,ppc_vsr_t * xb)3325 void helper_xssubqp(CPUPPCState *env, uint32_t opcode,
3326                     ppc_vsr_t *xt, ppc_vsr_t *xa, ppc_vsr_t *xb)
3327 {
3328     ppc_vsr_t t = *xt;
3329     float_status tstat;
3330 
3331     helper_reset_fpstatus(env);
3332 
3333     tstat = env->fp_status;
3334     if (unlikely(Rc(opcode) != 0)) {
3335         tstat.float_rounding_mode = float_round_to_odd;
3336     }
3337 
3338     set_float_exception_flags(0, &tstat);
3339     t.f128 = float128_sub(xa->f128, xb->f128, &tstat);
3340     env->fp_status.float_exception_flags |= tstat.float_exception_flags;
3341 
3342     if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
3343         float_invalid_op_addsub(env, tstat.float_exception_flags, 1, GETPC());
3344     }
3345 
3346     helper_compute_fprf_float128(env, t.f128);
3347     *xt = t;
3348     do_float_check_status(env, true, GETPC());
3349 }
3350 
vsxger_excp(CPUPPCState * env,uintptr_t retaddr)3351 static inline void vsxger_excp(CPUPPCState *env, uintptr_t retaddr)
3352 {
3353     /*
3354      * XV*GER instructions execute and set the FPSCR as if exceptions
3355      * are disabled and only at the end throw an exception
3356      */
3357     target_ulong enable;
3358     enable = env->fpscr & (FP_ENABLES | FP_FI | FP_FR);
3359     env->fpscr &= ~(FP_ENABLES | FP_FI | FP_FR);
3360     int status = get_float_exception_flags(&env->fp_status);
3361     if (unlikely(status & float_flag_invalid)) {
3362         if (status & float_flag_invalid_snan) {
3363             float_invalid_op_vxsnan(env, 0);
3364         }
3365         if (status & float_flag_invalid_imz) {
3366             float_invalid_op_vximz(env, false, 0);
3367         }
3368         if (status & float_flag_invalid_isi) {
3369             float_invalid_op_vxisi(env, false, 0);
3370         }
3371     }
3372     do_float_check_status(env, false, retaddr);
3373     env->fpscr |= enable;
3374     do_fpscr_check_status(env, retaddr);
3375 }
3376 
3377 typedef float64 extract_f16(float16, float_status *);
3378 
extract_hf16(float16 in,float_status * fp_status)3379 static float64 extract_hf16(float16 in, float_status *fp_status)
3380 {
3381     return float16_to_float64(in, true, fp_status);
3382 }
3383 
extract_bf16(bfloat16 in,float_status * fp_status)3384 static float64 extract_bf16(bfloat16 in, float_status *fp_status)
3385 {
3386     return bfloat16_to_float64(in, fp_status);
3387 }
3388 
vsxger16(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask,bool acc,bool neg_mul,bool neg_acc,extract_f16 extract)3389 static void vsxger16(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3390                      ppc_acc_t  *at, uint32_t mask, bool acc,
3391                      bool neg_mul, bool neg_acc, extract_f16 extract)
3392 {
3393     float32 r, aux_acc;
3394     float64 psum, va, vb, vc, vd;
3395     int i, j, xmsk_bit, ymsk_bit;
3396     uint8_t pmsk = FIELD_EX32(mask, GER_MSK, PMSK),
3397             xmsk = FIELD_EX32(mask, GER_MSK, XMSK),
3398             ymsk = FIELD_EX32(mask, GER_MSK, YMSK);
3399     float_status *excp_ptr = &env->fp_status;
3400     for (i = 0, xmsk_bit = 1 << 3; i < 4; i++, xmsk_bit >>= 1) {
3401         for (j = 0, ymsk_bit = 1 << 3; j < 4; j++, ymsk_bit >>= 1) {
3402             if ((xmsk_bit & xmsk) && (ymsk_bit & ymsk)) {
3403                 va = !(pmsk & 2) ? float64_zero :
3404                                    extract(a->VsrHF(2 * i), excp_ptr);
3405                 vb = !(pmsk & 2) ? float64_zero :
3406                                    extract(b->VsrHF(2 * j), excp_ptr);
3407                 vc = !(pmsk & 1) ? float64_zero :
3408                                    extract(a->VsrHF(2 * i + 1), excp_ptr);
3409                 vd = !(pmsk & 1) ? float64_zero :
3410                                    extract(b->VsrHF(2 * j + 1), excp_ptr);
3411                 psum = float64_mul(va, vb, excp_ptr);
3412                 psum = float64r32_muladd(vc, vd, psum, 0, excp_ptr);
3413                 r = float64_to_float32(psum, excp_ptr);
3414                 if (acc) {
3415                     aux_acc = at[i].VsrSF(j);
3416                     if (neg_mul) {
3417                         r = bfp32_neg(r);
3418                     }
3419                     if (neg_acc) {
3420                         aux_acc = bfp32_neg(aux_acc);
3421                     }
3422                     r = float32_add(r, aux_acc, excp_ptr);
3423                 }
3424                 at[i].VsrSF(j) = r;
3425             } else {
3426                 at[i].VsrSF(j) = float32_zero;
3427             }
3428         }
3429     }
3430     vsxger_excp(env, GETPC());
3431 }
3432 
3433 typedef void vsxger_zero(ppc_vsr_t *at, int, int);
3434 
3435 typedef void vsxger_muladd_f(ppc_vsr_t *, ppc_vsr_t *, ppc_vsr_t *, int, int,
3436                              int flags, float_status *s);
3437 
vsxger_muladd32(ppc_vsr_t * at,ppc_vsr_t * a,ppc_vsr_t * b,int i,int j,int flags,float_status * s)3438 static void vsxger_muladd32(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
3439                             int j, int flags, float_status *s)
3440 {
3441     at[i].VsrSF(j) = float32_muladd(a->VsrSF(i), b->VsrSF(j),
3442                                     at[i].VsrSF(j), flags, s);
3443 }
3444 
vsxger_mul32(ppc_vsr_t * at,ppc_vsr_t * a,ppc_vsr_t * b,int i,int j,int flags,float_status * s)3445 static void vsxger_mul32(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
3446                          int j, int flags, float_status *s)
3447 {
3448     at[i].VsrSF(j) = float32_mul(a->VsrSF(i), b->VsrSF(j), s);
3449 }
3450 
vsxger_zero32(ppc_vsr_t * at,int i,int j)3451 static void vsxger_zero32(ppc_vsr_t *at, int i, int j)
3452 {
3453     at[i].VsrSF(j) = float32_zero;
3454 }
3455 
vsxger_muladd64(ppc_vsr_t * at,ppc_vsr_t * a,ppc_vsr_t * b,int i,int j,int flags,float_status * s)3456 static void vsxger_muladd64(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
3457                             int j, int flags, float_status *s)
3458 {
3459     if (j >= 2) {
3460         j -= 2;
3461         at[i].VsrDF(j) = float64_muladd(a[i / 2].VsrDF(i % 2), b->VsrDF(j),
3462                                         at[i].VsrDF(j), flags, s);
3463     }
3464 }
3465 
vsxger_mul64(ppc_vsr_t * at,ppc_vsr_t * a,ppc_vsr_t * b,int i,int j,int flags,float_status * s)3466 static void vsxger_mul64(ppc_vsr_t *at, ppc_vsr_t *a, ppc_vsr_t *b, int i,
3467                          int j, int flags, float_status *s)
3468 {
3469     if (j >= 2) {
3470         j -= 2;
3471         at[i].VsrDF(j) = float64_mul(a[i / 2].VsrDF(i % 2), b->VsrDF(j), s);
3472     }
3473 }
3474 
vsxger_zero64(ppc_vsr_t * at,int i,int j)3475 static void vsxger_zero64(ppc_vsr_t *at, int i, int j)
3476 {
3477     if (j >= 2) {
3478         j -= 2;
3479         at[i].VsrDF(j) = float64_zero;
3480     }
3481 }
3482 
vsxger(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask,bool acc,bool neg_mul,bool neg_acc,vsxger_muladd_f mul,vsxger_muladd_f muladd,vsxger_zero zero)3483 static void vsxger(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3484                    ppc_acc_t  *at, uint32_t mask, bool acc, bool neg_mul,
3485                    bool neg_acc, vsxger_muladd_f mul, vsxger_muladd_f muladd,
3486                    vsxger_zero zero)
3487 {
3488     int i, j, xmsk_bit, ymsk_bit, op_flags;
3489     uint8_t xmsk = mask & 0x0F;
3490     uint8_t ymsk = (mask >> 4) & 0x0F;
3491     float_status *excp_ptr = &env->fp_status;
3492     op_flags = (neg_acc ^ neg_mul) ? float_muladd_negate_c : 0;
3493     op_flags |= (neg_mul) ? float_muladd_negate_result : 0;
3494     helper_reset_fpstatus(env);
3495     for (i = 0, xmsk_bit = 1 << 3; i < 4; i++, xmsk_bit >>= 1) {
3496         for (j = 0, ymsk_bit = 1 << 3; j < 4; j++, ymsk_bit >>= 1) {
3497             if ((xmsk_bit & xmsk) && (ymsk_bit & ymsk)) {
3498                 if (acc) {
3499                     muladd(at, a, b, i, j, op_flags, excp_ptr);
3500                 } else {
3501                     mul(at, a, b, i, j, op_flags, excp_ptr);
3502                 }
3503             } else {
3504                 zero(at, i, j);
3505             }
3506         }
3507     }
3508     vsxger_excp(env, GETPC());
3509 }
3510 
3511 QEMU_FLATTEN
helper_XVBF16GER2(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3512 void helper_XVBF16GER2(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3513                        ppc_acc_t *at, uint32_t mask)
3514 {
3515     vsxger16(env, a, b, at, mask, false, false, false, extract_bf16);
3516 }
3517 
3518 QEMU_FLATTEN
helper_XVBF16GER2PP(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3519 void helper_XVBF16GER2PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3520                          ppc_acc_t *at, uint32_t mask)
3521 {
3522     vsxger16(env, a, b, at, mask, true, false, false, extract_bf16);
3523 }
3524 
3525 QEMU_FLATTEN
helper_XVBF16GER2PN(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3526 void helper_XVBF16GER2PN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3527                          ppc_acc_t *at, uint32_t mask)
3528 {
3529     vsxger16(env, a, b, at, mask, true, false, true, extract_bf16);
3530 }
3531 
3532 QEMU_FLATTEN
helper_XVBF16GER2NP(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3533 void helper_XVBF16GER2NP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3534                          ppc_acc_t *at, uint32_t mask)
3535 {
3536     vsxger16(env, a, b, at, mask, true, true, false, extract_bf16);
3537 }
3538 
3539 QEMU_FLATTEN
helper_XVBF16GER2NN(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3540 void helper_XVBF16GER2NN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3541                          ppc_acc_t *at, uint32_t mask)
3542 {
3543     vsxger16(env, a, b, at, mask, true, true, true, extract_bf16);
3544 }
3545 
3546 QEMU_FLATTEN
helper_XVF16GER2(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3547 void helper_XVF16GER2(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3548                      ppc_acc_t *at, uint32_t mask)
3549 {
3550     vsxger16(env, a, b, at, mask, false, false, false, extract_hf16);
3551 }
3552 
3553 QEMU_FLATTEN
helper_XVF16GER2PP(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3554 void helper_XVF16GER2PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3555                         ppc_acc_t *at, uint32_t mask)
3556 {
3557     vsxger16(env, a, b, at, mask, true, false, false, extract_hf16);
3558 }
3559 
3560 QEMU_FLATTEN
helper_XVF16GER2PN(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3561 void helper_XVF16GER2PN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3562                         ppc_acc_t *at, uint32_t mask)
3563 {
3564     vsxger16(env, a, b, at, mask, true, false, true, extract_hf16);
3565 }
3566 
3567 QEMU_FLATTEN
helper_XVF16GER2NP(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3568 void helper_XVF16GER2NP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3569                         ppc_acc_t *at, uint32_t mask)
3570 {
3571     vsxger16(env, a, b, at, mask, true, true, false, extract_hf16);
3572 }
3573 
3574 QEMU_FLATTEN
helper_XVF16GER2NN(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3575 void helper_XVF16GER2NN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3576                         ppc_acc_t *at, uint32_t mask)
3577 {
3578     vsxger16(env, a, b, at, mask, true, true, true, extract_hf16);
3579 }
3580 
3581 QEMU_FLATTEN
helper_XVF32GER(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3582 void helper_XVF32GER(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3583                      ppc_acc_t *at, uint32_t mask)
3584 {
3585     vsxger(env, a, b, at, mask, false, false, false, vsxger_mul32,
3586            vsxger_muladd32, vsxger_zero32);
3587 }
3588 
3589 QEMU_FLATTEN
helper_XVF32GERPP(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3590 void helper_XVF32GERPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3591                        ppc_acc_t *at, uint32_t mask)
3592 {
3593     vsxger(env, a, b, at, mask, true, false, false, vsxger_mul32,
3594            vsxger_muladd32, vsxger_zero32);
3595 }
3596 
3597 QEMU_FLATTEN
helper_XVF32GERPN(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3598 void helper_XVF32GERPN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3599                        ppc_acc_t *at, uint32_t mask)
3600 {
3601     vsxger(env, a, b, at, mask, true, false, true, vsxger_mul32,
3602            vsxger_muladd32, vsxger_zero32);
3603 }
3604 
3605 QEMU_FLATTEN
helper_XVF32GERNP(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3606 void helper_XVF32GERNP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3607                        ppc_acc_t *at, uint32_t mask)
3608 {
3609     vsxger(env, a, b, at, mask, true, true, false, vsxger_mul32,
3610            vsxger_muladd32, vsxger_zero32);
3611 }
3612 
3613 QEMU_FLATTEN
helper_XVF32GERNN(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3614 void helper_XVF32GERNN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3615                        ppc_acc_t *at, uint32_t mask)
3616 {
3617     vsxger(env, a, b, at, mask, true, true, true, vsxger_mul32,
3618            vsxger_muladd32, vsxger_zero32);
3619 }
3620 
3621 QEMU_FLATTEN
helper_XVF64GER(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3622 void helper_XVF64GER(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3623                      ppc_acc_t *at, uint32_t mask)
3624 {
3625     vsxger(env, a, b, at, mask, false, false, false, vsxger_mul64,
3626            vsxger_muladd64, vsxger_zero64);
3627 }
3628 
3629 QEMU_FLATTEN
helper_XVF64GERPP(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3630 void helper_XVF64GERPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3631                        ppc_acc_t *at, uint32_t mask)
3632 {
3633     vsxger(env, a, b, at, mask, true, false, false, vsxger_mul64,
3634            vsxger_muladd64, vsxger_zero64);
3635 }
3636 
3637 QEMU_FLATTEN
helper_XVF64GERPN(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3638 void helper_XVF64GERPN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3639                        ppc_acc_t *at, uint32_t mask)
3640 {
3641     vsxger(env, a, b, at, mask, true, false, true, vsxger_mul64,
3642            vsxger_muladd64, vsxger_zero64);
3643 }
3644 
3645 QEMU_FLATTEN
helper_XVF64GERNP(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3646 void helper_XVF64GERNP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3647                        ppc_acc_t *at, uint32_t mask)
3648 {
3649     vsxger(env, a, b, at, mask, true, true, false, vsxger_mul64,
3650            vsxger_muladd64, vsxger_zero64);
3651 }
3652 
3653 QEMU_FLATTEN
helper_XVF64GERNN(CPUPPCState * env,ppc_vsr_t * a,ppc_vsr_t * b,ppc_acc_t * at,uint32_t mask)3654 void helper_XVF64GERNN(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
3655                        ppc_acc_t *at, uint32_t mask)
3656 {
3657     vsxger(env, a, b, at, mask, true, true, true, vsxger_mul64,
3658            vsxger_muladd64, vsxger_zero64);
3659 }
3660