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