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