xref: /qemu/target/ppc/int_helper.c (revision 91e01270)
1 /*
2  *  PowerPC integer and vector emulation helpers for QEMU.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "internal.h"
23 #include "qemu/host-utils.h"
24 #include "qemu/log.h"
25 #include "exec/helper-proto.h"
26 #include "crypto/aes.h"
27 #include "crypto/aes-round.h"
28 #include "fpu/softfloat.h"
29 #include "qapi/error.h"
30 #include "qemu/guest-random.h"
31 #include "tcg/tcg-gvec-desc.h"
32 
33 #include "helper_regs.h"
34 /*****************************************************************************/
35 /* Fixed point operations helpers */
36 
37 static inline void helper_update_ov_legacy(CPUPPCState *env, int ov)
38 {
39     if (unlikely(ov)) {
40         env->so = env->ov = env->ov32 = 1;
41     } else {
42         env->ov = env->ov32 = 0;
43     }
44 }
45 
46 target_ulong helper_divweu(CPUPPCState *env, target_ulong ra, target_ulong rb,
47                            uint32_t oe)
48 {
49     uint64_t rt = 0;
50     int overflow = 0;
51 
52     uint64_t dividend = (uint64_t)ra << 32;
53     uint64_t divisor = (uint32_t)rb;
54 
55     if (unlikely(divisor == 0)) {
56         overflow = 1;
57     } else {
58         rt = dividend / divisor;
59         overflow = rt > UINT32_MAX;
60     }
61 
62     if (unlikely(overflow)) {
63         rt = 0; /* Undefined */
64     }
65 
66     if (oe) {
67         helper_update_ov_legacy(env, overflow);
68     }
69 
70     return (target_ulong)rt;
71 }
72 
73 target_ulong helper_divwe(CPUPPCState *env, target_ulong ra, target_ulong rb,
74                           uint32_t oe)
75 {
76     int64_t rt = 0;
77     int overflow = 0;
78 
79     int64_t dividend = (int64_t)ra << 32;
80     int64_t divisor = (int64_t)((int32_t)rb);
81 
82     if (unlikely((divisor == 0) ||
83                  ((divisor == -1ull) && (dividend == INT64_MIN)))) {
84         overflow = 1;
85     } else {
86         rt = dividend / divisor;
87         overflow = rt != (int32_t)rt;
88     }
89 
90     if (unlikely(overflow)) {
91         rt = 0; /* Undefined */
92     }
93 
94     if (oe) {
95         helper_update_ov_legacy(env, overflow);
96     }
97 
98     return (target_ulong)rt;
99 }
100 
101 #if defined(TARGET_PPC64)
102 
103 uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe)
104 {
105     uint64_t rt = 0;
106     int overflow = 0;
107 
108     if (unlikely(rb == 0 || ra >= rb)) {
109         overflow = 1;
110         rt = 0; /* Undefined */
111     } else {
112         divu128(&rt, &ra, rb);
113     }
114 
115     if (oe) {
116         helper_update_ov_legacy(env, overflow);
117     }
118 
119     return rt;
120 }
121 
122 uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
123 {
124     uint64_t rt = 0;
125     int64_t ra = (int64_t)rau;
126     int64_t rb = (int64_t)rbu;
127     int overflow = 0;
128 
129     if (unlikely(rb == 0 || uabs64(ra) >= uabs64(rb))) {
130         overflow = 1;
131         rt = 0; /* Undefined */
132     } else {
133         divs128(&rt, &ra, rb);
134     }
135 
136     if (oe) {
137         helper_update_ov_legacy(env, overflow);
138     }
139 
140     return rt;
141 }
142 
143 #endif
144 
145 
146 #if defined(TARGET_PPC64)
147 /* if x = 0xab, returns 0xababababababababa */
148 #define pattern(x) (((x) & 0xff) * (~(target_ulong)0 / 0xff))
149 
150 /*
151  * subtract 1 from each byte, and with inverse, check if MSB is set at each
152  * byte.
153  * i.e. ((0x00 - 0x01) & ~(0x00)) & 0x80
154  *      (0xFF & 0xFF) & 0x80 = 0x80 (zero found)
155  */
156 #define haszero(v) (((v) - pattern(0x01)) & ~(v) & pattern(0x80))
157 
158 /* When you XOR the pattern and there is a match, that byte will be zero */
159 #define hasvalue(x, n)  (haszero((x) ^ pattern(n)))
160 
161 uint32_t helper_cmpeqb(target_ulong ra, target_ulong rb)
162 {
163     return hasvalue(rb, ra) ? CRF_GT : 0;
164 }
165 
166 #undef pattern
167 #undef haszero
168 #undef hasvalue
169 
170 /*
171  * Return a random number.
172  */
173 uint64_t helper_darn32(void)
174 {
175     Error *err = NULL;
176     uint32_t ret;
177 
178     if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) {
179         qemu_log_mask(LOG_UNIMP, "darn: Crypto failure: %s",
180                       error_get_pretty(err));
181         error_free(err);
182         return -1;
183     }
184 
185     return ret;
186 }
187 
188 uint64_t helper_darn64(void)
189 {
190     Error *err = NULL;
191     uint64_t ret;
192 
193     if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) {
194         qemu_log_mask(LOG_UNIMP, "darn: Crypto failure: %s",
195                       error_get_pretty(err));
196         error_free(err);
197         return -1;
198     }
199 
200     return ret;
201 }
202 
203 uint64_t helper_bpermd(uint64_t rs, uint64_t rb)
204 {
205     int i;
206     uint64_t ra = 0;
207 
208     for (i = 0; i < 8; i++) {
209         int index = (rs >> (i * 8)) & 0xFF;
210         if (index < 64) {
211             if (rb & PPC_BIT(index)) {
212                 ra |= 1 << i;
213             }
214         }
215     }
216     return ra;
217 }
218 
219 #endif
220 
221 target_ulong helper_cmpb(target_ulong rs, target_ulong rb)
222 {
223     target_ulong mask = 0xff;
224     target_ulong ra = 0;
225     int i;
226 
227     for (i = 0; i < sizeof(target_ulong); i++) {
228         if ((rs & mask) == (rb & mask)) {
229             ra |= mask;
230         }
231         mask <<= 8;
232     }
233     return ra;
234 }
235 
236 /* shift right arithmetic helper */
237 target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
238                          target_ulong shift)
239 {
240     int32_t ret;
241 
242     if (likely(!(shift & 0x20))) {
243         if (likely((uint32_t)shift != 0)) {
244             shift &= 0x1f;
245             ret = (int32_t)value >> shift;
246             if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
247                 env->ca32 = env->ca = 0;
248             } else {
249                 env->ca32 = env->ca = 1;
250             }
251         } else {
252             ret = (int32_t)value;
253             env->ca32 = env->ca = 0;
254         }
255     } else {
256         ret = (int32_t)value >> 31;
257         env->ca32 = env->ca = (ret != 0);
258     }
259     return (target_long)ret;
260 }
261 
262 #if defined(TARGET_PPC64)
263 target_ulong helper_srad(CPUPPCState *env, target_ulong value,
264                          target_ulong shift)
265 {
266     int64_t ret;
267 
268     if (likely(!(shift & 0x40))) {
269         if (likely((uint64_t)shift != 0)) {
270             shift &= 0x3f;
271             ret = (int64_t)value >> shift;
272             if (likely(ret >= 0 || (value & ((1ULL << shift) - 1)) == 0)) {
273                 env->ca32 = env->ca = 0;
274             } else {
275                 env->ca32 = env->ca = 1;
276             }
277         } else {
278             ret = (int64_t)value;
279             env->ca32 = env->ca = 0;
280         }
281     } else {
282         ret = (int64_t)value >> 63;
283         env->ca32 = env->ca = (ret != 0);
284     }
285     return ret;
286 }
287 #endif
288 
289 #if defined(TARGET_PPC64)
290 target_ulong helper_popcntb(target_ulong val)
291 {
292     /* Note that we don't fold past bytes */
293     val = (val & 0x5555555555555555ULL) + ((val >>  1) &
294                                            0x5555555555555555ULL);
295     val = (val & 0x3333333333333333ULL) + ((val >>  2) &
296                                            0x3333333333333333ULL);
297     val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
298                                            0x0f0f0f0f0f0f0f0fULL);
299     return val;
300 }
301 
302 target_ulong helper_popcntw(target_ulong val)
303 {
304     /* Note that we don't fold past words.  */
305     val = (val & 0x5555555555555555ULL) + ((val >>  1) &
306                                            0x5555555555555555ULL);
307     val = (val & 0x3333333333333333ULL) + ((val >>  2) &
308                                            0x3333333333333333ULL);
309     val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
310                                            0x0f0f0f0f0f0f0f0fULL);
311     val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) &
312                                            0x00ff00ff00ff00ffULL);
313     val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
314                                            0x0000ffff0000ffffULL);
315     return val;
316 }
317 #else
318 target_ulong helper_popcntb(target_ulong val)
319 {
320     /* Note that we don't fold past bytes */
321     val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
322     val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
323     val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
324     return val;
325 }
326 #endif
327 
328 uint64_t helper_CFUGED(uint64_t src, uint64_t mask)
329 {
330     /*
331      * Instead of processing the mask bit-by-bit from the most significant to
332      * the least significant bit, as described in PowerISA, we'll handle it in
333      * blocks of 'n' zeros/ones from LSB to MSB. To avoid the decision to use
334      * ctz or cto, we negate the mask at the end of the loop.
335      */
336     target_ulong m, left = 0, right = 0;
337     unsigned int n, i = 64;
338     bool bit = false; /* tracks if we are processing zeros or ones */
339 
340     if (mask == 0 || mask == -1) {
341         return src;
342     }
343 
344     /* Processes the mask in blocks, from LSB to MSB */
345     while (i) {
346         /* Find how many bits we should take */
347         n = ctz64(mask);
348         if (n > i) {
349             n = i;
350         }
351 
352         /*
353          * Extracts 'n' trailing bits of src and put them on the leading 'n'
354          * bits of 'right' or 'left', pushing down the previously extracted
355          * values.
356          */
357         m = (1ll << n) - 1;
358         if (bit) {
359             right = ror64(right | (src & m), n);
360         } else {
361             left = ror64(left | (src & m), n);
362         }
363 
364         /*
365          * Discards the processed bits from 'src' and 'mask'. Note that we are
366          * removing 'n' trailing zeros from 'mask', but the logical shift will
367          * add 'n' leading zeros back, so the population count of 'mask' is kept
368          * the same.
369          */
370         src >>= n;
371         mask >>= n;
372         i -= n;
373         bit = !bit;
374         mask = ~mask;
375     }
376 
377     /*
378      * At the end, right was ror'ed ctpop(mask) times. To put it back in place,
379      * we'll shift it more 64-ctpop(mask) times.
380      */
381     if (bit) {
382         n = ctpop64(mask);
383     } else {
384         n = 64 - ctpop64(mask);
385     }
386 
387     return left | (right >> n);
388 }
389 
390 uint64_t helper_PDEPD(uint64_t src, uint64_t mask)
391 {
392     int i, o;
393     uint64_t result = 0;
394 
395     if (mask == -1) {
396         return src;
397     }
398 
399     for (i = 0; mask != 0; i++) {
400         o = ctz64(mask);
401         mask &= mask - 1;
402         result |= ((src >> i) & 1) << o;
403     }
404 
405     return result;
406 }
407 
408 uint64_t helper_PEXTD(uint64_t src, uint64_t mask)
409 {
410     int i, o;
411     uint64_t result = 0;
412 
413     if (mask == -1) {
414         return src;
415     }
416 
417     for (o = 0; mask != 0; o++) {
418         i = ctz64(mask);
419         mask &= mask - 1;
420         result |= ((src >> i) & 1) << o;
421     }
422 
423     return result;
424 }
425 
426 /*****************************************************************************/
427 /* Altivec extension helpers */
428 #if HOST_BIG_ENDIAN
429 #define VECTOR_FOR_INORDER_I(index, element)                    \
430     for (index = 0; index < ARRAY_SIZE(r->element); index++)
431 #else
432 #define VECTOR_FOR_INORDER_I(index, element)                    \
433     for (index = ARRAY_SIZE(r->element) - 1; index >= 0; index--)
434 #endif
435 
436 /* Saturating arithmetic helpers.  */
437 #define SATCVT(from, to, from_type, to_type, min, max)          \
438     static inline to_type cvt##from##to(from_type x, int *sat)  \
439     {                                                           \
440         to_type r;                                              \
441                                                                 \
442         if (x < (from_type)min) {                               \
443             r = min;                                            \
444             *sat = 1;                                           \
445         } else if (x > (from_type)max) {                        \
446             r = max;                                            \
447             *sat = 1;                                           \
448         } else {                                                \
449             r = x;                                              \
450         }                                                       \
451         return r;                                               \
452     }
453 #define SATCVTU(from, to, from_type, to_type, min, max)         \
454     static inline to_type cvt##from##to(from_type x, int *sat)  \
455     {                                                           \
456         to_type r;                                              \
457                                                                 \
458         if (x > (from_type)max) {                               \
459             r = max;                                            \
460             *sat = 1;                                           \
461         } else {                                                \
462             r = x;                                              \
463         }                                                       \
464         return r;                                               \
465     }
466 SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX)
467 SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX)
468 SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX)
469 
470 SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX)
471 SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX)
472 SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX)
473 SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX)
474 SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX)
475 SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
476 #undef SATCVT
477 #undef SATCVTU
478 
479 void helper_mtvscr(CPUPPCState *env, uint32_t vscr)
480 {
481     ppc_store_vscr(env, vscr);
482 }
483 
484 uint32_t helper_mfvscr(CPUPPCState *env)
485 {
486     return ppc_get_vscr(env);
487 }
488 
489 static inline void set_vscr_sat(CPUPPCState *env)
490 {
491     /* The choice of non-zero value is arbitrary.  */
492     env->vscr_sat.u32[0] = 1;
493 }
494 
495 /* vprtybq */
496 void helper_VPRTYBQ(ppc_avr_t *r, ppc_avr_t *b, uint32_t v)
497 {
498     uint64_t res = b->u64[0] ^ b->u64[1];
499     res ^= res >> 32;
500     res ^= res >> 16;
501     res ^= res >> 8;
502     r->VsrD(1) = res & 1;
503     r->VsrD(0) = 0;
504 }
505 
506 #define VARITHFP(suffix, func)                                          \
507     void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
508                           ppc_avr_t *b)                                 \
509     {                                                                   \
510         int i;                                                          \
511                                                                         \
512         for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
513             r->f32[i] = func(a->f32[i], b->f32[i], &env->vec_status);   \
514         }                                                               \
515     }
516 VARITHFP(addfp, float32_add)
517 VARITHFP(subfp, float32_sub)
518 VARITHFP(minfp, float32_min)
519 VARITHFP(maxfp, float32_max)
520 #undef VARITHFP
521 
522 #define VARITHFPFMA(suffix, type)                                       \
523     void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
524                            ppc_avr_t *b, ppc_avr_t *c)                  \
525     {                                                                   \
526         int i;                                                          \
527         for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
528             r->f32[i] = float32_muladd(a->f32[i], c->f32[i], b->f32[i], \
529                                        type, &env->vec_status);         \
530         }                                                               \
531     }
532 VARITHFPFMA(maddfp, 0);
533 VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
534 #undef VARITHFPFMA
535 
536 #define VARITHSAT_CASE(type, op, cvt, element)                          \
537     {                                                                   \
538         type result = (type)a->element[i] op (type)b->element[i];       \
539         r->element[i] = cvt(result, &sat);                              \
540     }
541 
542 #define VARITHSAT_DO(name, op, optype, cvt, element)                    \
543     void helper_v##name(ppc_avr_t *r, ppc_avr_t *vscr_sat,              \
544                         ppc_avr_t *a, ppc_avr_t *b, uint32_t desc)      \
545     {                                                                   \
546         int sat = 0;                                                    \
547         int i;                                                          \
548                                                                         \
549         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
550             VARITHSAT_CASE(optype, op, cvt, element);                   \
551         }                                                               \
552         if (sat) {                                                      \
553             vscr_sat->u32[0] = 1;                                       \
554         }                                                               \
555     }
556 #define VARITHSAT_SIGNED(suffix, element, optype, cvt)          \
557     VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element)      \
558     VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
559 #define VARITHSAT_UNSIGNED(suffix, element, optype, cvt)        \
560     VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element)      \
561     VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
562 VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
563 VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
564 VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
565 VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
566 VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
567 VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
568 #undef VARITHSAT_CASE
569 #undef VARITHSAT_DO
570 #undef VARITHSAT_SIGNED
571 #undef VARITHSAT_UNSIGNED
572 
573 #define VAVG(name, element, etype)                                          \
574     void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t v)\
575     {                                                                       \
576         int i;                                                              \
577                                                                             \
578         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
579             etype x = (etype)a->element[i] + (etype)b->element[i] + 1;      \
580             r->element[i] = x >> 1;                                         \
581         }                                                                   \
582     }
583 
584 VAVG(VAVGSB, s8, int16_t)
585 VAVG(VAVGUB, u8, uint16_t)
586 VAVG(VAVGSH, s16, int32_t)
587 VAVG(VAVGUH, u16, uint32_t)
588 VAVG(VAVGSW, s32, int64_t)
589 VAVG(VAVGUW, u32, uint64_t)
590 #undef VAVG
591 
592 #define VABSDU(name, element)                                           \
593 void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t v)\
594 {                                                                       \
595     int i;                                                              \
596                                                                         \
597     for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
598         r->element[i] = (a->element[i] > b->element[i]) ?               \
599             (a->element[i] - b->element[i]) :                           \
600             (b->element[i] - a->element[i]);                            \
601     }                                                                   \
602 }
603 
604 /*
605  * VABSDU - Vector absolute difference unsigned
606  *   name    - instruction mnemonic suffix (b: byte, h: halfword, w: word)
607  *   element - element type to access from vector
608  */
609 VABSDU(VABSDUB, u8)
610 VABSDU(VABSDUH, u16)
611 VABSDU(VABSDUW, u32)
612 #undef VABSDU
613 
614 #define VCF(suffix, cvt, element)                                       \
615     void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r,             \
616                             ppc_avr_t *b, uint32_t uim)                 \
617     {                                                                   \
618         int i;                                                          \
619                                                                         \
620         for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
621             float32 t = cvt(b->element[i], &env->vec_status);           \
622             r->f32[i] = float32_scalbn(t, -uim, &env->vec_status);      \
623         }                                                               \
624     }
625 VCF(ux, uint32_to_float32, u32)
626 VCF(sx, int32_to_float32, s32)
627 #undef VCF
628 
629 #define VCMPNEZ(NAME, ELEM) \
630 void helper_##NAME(ppc_vsr_t *t, ppc_vsr_t *a, ppc_vsr_t *b, uint32_t desc) \
631 {                                                                           \
632     for (int i = 0; i < ARRAY_SIZE(t->ELEM); i++) {                         \
633         t->ELEM[i] = ((a->ELEM[i] == 0) || (b->ELEM[i] == 0) ||             \
634                       (a->ELEM[i] != b->ELEM[i])) ? -1 : 0;                 \
635     }                                                                       \
636 }
637 VCMPNEZ(VCMPNEZB, u8)
638 VCMPNEZ(VCMPNEZH, u16)
639 VCMPNEZ(VCMPNEZW, u32)
640 #undef VCMPNEZ
641 
642 #define VCMPFP_DO(suffix, compare, order, record)                       \
643     void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r,            \
644                              ppc_avr_t *a, ppc_avr_t *b)                \
645     {                                                                   \
646         uint32_t ones = (uint32_t)-1;                                   \
647         uint32_t all = ones;                                            \
648         uint32_t none = 0;                                              \
649         int i;                                                          \
650                                                                         \
651         for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
652             uint32_t result;                                            \
653             FloatRelation rel =                                         \
654                 float32_compare_quiet(a->f32[i], b->f32[i],             \
655                                       &env->vec_status);                \
656             if (rel == float_relation_unordered) {                      \
657                 result = 0;                                             \
658             } else if (rel compare order) {                             \
659                 result = ones;                                          \
660             } else {                                                    \
661                 result = 0;                                             \
662             }                                                           \
663             r->u32[i] = result;                                         \
664             all &= result;                                              \
665             none |= result;                                             \
666         }                                                               \
667         if (record) {                                                   \
668             env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
669         }                                                               \
670     }
671 #define VCMPFP(suffix, compare, order)          \
672     VCMPFP_DO(suffix, compare, order, 0)        \
673     VCMPFP_DO(suffix##_dot, compare, order, 1)
674 VCMPFP(eqfp, ==, float_relation_equal)
675 VCMPFP(gefp, !=, float_relation_less)
676 VCMPFP(gtfp, ==, float_relation_greater)
677 #undef VCMPFP_DO
678 #undef VCMPFP
679 
680 static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r,
681                                     ppc_avr_t *a, ppc_avr_t *b, int record)
682 {
683     int i;
684     int all_in = 0;
685 
686     for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
687         FloatRelation le_rel = float32_compare_quiet(a->f32[i], b->f32[i],
688                                                      &env->vec_status);
689         if (le_rel == float_relation_unordered) {
690             r->u32[i] = 0xc0000000;
691             all_in = 1;
692         } else {
693             float32 bneg = float32_chs(b->f32[i]);
694             FloatRelation ge_rel = float32_compare_quiet(a->f32[i], bneg,
695                                                          &env->vec_status);
696             int le = le_rel != float_relation_greater;
697             int ge = ge_rel != float_relation_less;
698 
699             r->u32[i] = ((!le) << 31) | ((!ge) << 30);
700             all_in |= (!le | !ge);
701         }
702     }
703     if (record) {
704         env->crf[6] = (all_in == 0) << 1;
705     }
706 }
707 
708 void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
709 {
710     vcmpbfp_internal(env, r, a, b, 0);
711 }
712 
713 void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
714                         ppc_avr_t *b)
715 {
716     vcmpbfp_internal(env, r, a, b, 1);
717 }
718 
719 #define VCT(suffix, satcvt, element)                                    \
720     void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r,             \
721                             ppc_avr_t *b, uint32_t uim)                 \
722     {                                                                   \
723         int i;                                                          \
724         int sat = 0;                                                    \
725         float_status s = env->vec_status;                               \
726                                                                         \
727         set_float_rounding_mode(float_round_to_zero, &s);               \
728         for (i = 0; i < ARRAY_SIZE(r->f32); i++) {                      \
729             if (float32_is_any_nan(b->f32[i])) {                        \
730                 r->element[i] = 0;                                      \
731             } else {                                                    \
732                 float64 t = float32_to_float64(b->f32[i], &s);          \
733                 int64_t j;                                              \
734                                                                         \
735                 t = float64_scalbn(t, uim, &s);                         \
736                 j = float64_to_int64(t, &s);                            \
737                 r->element[i] = satcvt(j, &sat);                        \
738             }                                                           \
739         }                                                               \
740         if (sat) {                                                      \
741             set_vscr_sat(env);                                          \
742         }                                                               \
743     }
744 VCT(uxs, cvtsduw, u32)
745 VCT(sxs, cvtsdsw, s32)
746 #undef VCT
747 
748 typedef int64_t do_ger(uint32_t, uint32_t, uint32_t);
749 
750 static int64_t ger_rank8(uint32_t a, uint32_t b, uint32_t mask)
751 {
752     int64_t psum = 0;
753     for (int i = 0; i < 8; i++, mask >>= 1) {
754         if (mask & 1) {
755             psum += (int64_t)sextract32(a, 4 * i, 4) * sextract32(b, 4 * i, 4);
756         }
757     }
758     return psum;
759 }
760 
761 static int64_t ger_rank4(uint32_t a, uint32_t b, uint32_t mask)
762 {
763     int64_t psum = 0;
764     for (int i = 0; i < 4; i++, mask >>= 1) {
765         if (mask & 1) {
766             psum += sextract32(a, 8 * i, 8) * (int64_t)extract32(b, 8 * i, 8);
767         }
768     }
769     return psum;
770 }
771 
772 static int64_t ger_rank2(uint32_t a, uint32_t b, uint32_t mask)
773 {
774     int64_t psum = 0;
775     for (int i = 0; i < 2; i++, mask >>= 1) {
776         if (mask & 1) {
777             psum += (int64_t)sextract32(a, 16 * i, 16) *
778                              sextract32(b, 16 * i, 16);
779         }
780     }
781     return psum;
782 }
783 
784 static void xviger(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b, ppc_acc_t  *at,
785                    uint32_t mask, bool sat, bool acc, do_ger ger)
786 {
787     uint8_t pmsk = FIELD_EX32(mask, GER_MSK, PMSK),
788             xmsk = FIELD_EX32(mask, GER_MSK, XMSK),
789             ymsk = FIELD_EX32(mask, GER_MSK, YMSK);
790     uint8_t xmsk_bit, ymsk_bit;
791     int64_t psum;
792     int i, j;
793     for (i = 0, xmsk_bit = 1 << 3; i < 4; i++, xmsk_bit >>= 1) {
794         for (j = 0, ymsk_bit = 1 << 3; j < 4; j++, ymsk_bit >>= 1) {
795             if ((xmsk_bit & xmsk) && (ymsk_bit & ymsk)) {
796                 psum = ger(a->VsrW(i), b->VsrW(j), pmsk);
797                 if (acc) {
798                     psum += at[i].VsrSW(j);
799                 }
800                 if (sat && psum > INT32_MAX) {
801                     set_vscr_sat(env);
802                     at[i].VsrSW(j) = INT32_MAX;
803                 } else if (sat && psum < INT32_MIN) {
804                     set_vscr_sat(env);
805                     at[i].VsrSW(j) = INT32_MIN;
806                 } else {
807                     at[i].VsrSW(j) = (int32_t) psum;
808                 }
809             } else {
810                 at[i].VsrSW(j) = 0;
811             }
812         }
813     }
814 }
815 
816 QEMU_FLATTEN
817 void helper_XVI4GER8(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
818                      ppc_acc_t *at, uint32_t mask)
819 {
820     xviger(env, a, b, at, mask, false, false, ger_rank8);
821 }
822 
823 QEMU_FLATTEN
824 void helper_XVI4GER8PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
825                        ppc_acc_t *at, uint32_t mask)
826 {
827     xviger(env, a, b, at, mask, false, true, ger_rank8);
828 }
829 
830 QEMU_FLATTEN
831 void helper_XVI8GER4(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
832                      ppc_acc_t *at, uint32_t mask)
833 {
834     xviger(env, a, b, at, mask, false, false, ger_rank4);
835 }
836 
837 QEMU_FLATTEN
838 void helper_XVI8GER4PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
839                        ppc_acc_t *at, uint32_t mask)
840 {
841     xviger(env, a, b, at, mask, false, true, ger_rank4);
842 }
843 
844 QEMU_FLATTEN
845 void helper_XVI8GER4SPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
846                         ppc_acc_t *at, uint32_t mask)
847 {
848     xviger(env, a, b, at, mask, true, true, ger_rank4);
849 }
850 
851 QEMU_FLATTEN
852 void helper_XVI16GER2(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
853                       ppc_acc_t *at, uint32_t mask)
854 {
855     xviger(env, a, b, at, mask, false, false, ger_rank2);
856 }
857 
858 QEMU_FLATTEN
859 void helper_XVI16GER2S(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
860                        ppc_acc_t *at, uint32_t mask)
861 {
862     xviger(env, a, b, at, mask, true, false, ger_rank2);
863 }
864 
865 QEMU_FLATTEN
866 void helper_XVI16GER2PP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
867                         ppc_acc_t *at, uint32_t mask)
868 {
869     xviger(env, a, b, at, mask, false, true, ger_rank2);
870 }
871 
872 QEMU_FLATTEN
873 void helper_XVI16GER2SPP(CPUPPCState *env, ppc_vsr_t *a, ppc_vsr_t *b,
874                          ppc_acc_t *at, uint32_t mask)
875 {
876     xviger(env, a, b, at, mask, true, true, ger_rank2);
877 }
878 
879 target_ulong helper_vclzlsbb(ppc_avr_t *r)
880 {
881     target_ulong count = 0;
882     int i;
883     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
884         if (r->VsrB(i) & 0x01) {
885             break;
886         }
887         count++;
888     }
889     return count;
890 }
891 
892 target_ulong helper_vctzlsbb(ppc_avr_t *r)
893 {
894     target_ulong count = 0;
895     int i;
896     for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) {
897         if (r->VsrB(i) & 0x01) {
898             break;
899         }
900         count++;
901     }
902     return count;
903 }
904 
905 void helper_VMHADDSHS(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
906                       ppc_avr_t *b, ppc_avr_t *c)
907 {
908     int sat = 0;
909     int i;
910 
911     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
912         int32_t prod = a->s16[i] * b->s16[i];
913         int32_t t = (int32_t)c->s16[i] + (prod >> 15);
914 
915         r->s16[i] = cvtswsh(t, &sat);
916     }
917 
918     if (sat) {
919         set_vscr_sat(env);
920     }
921 }
922 
923 void helper_VMHRADDSHS(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
924                        ppc_avr_t *b, ppc_avr_t *c)
925 {
926     int sat = 0;
927     int i;
928 
929     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
930         int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
931         int32_t t = (int32_t)c->s16[i] + (prod >> 15);
932         r->s16[i] = cvtswsh(t, &sat);
933     }
934 
935     if (sat) {
936         set_vscr_sat(env);
937     }
938 }
939 
940 void helper_VMLADDUHM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c,
941                       uint32_t v)
942 {
943     int i;
944 
945     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
946         int32_t prod = a->s16[i] * b->s16[i];
947         r->s16[i] = (int16_t) (prod + c->s16[i]);
948     }
949 }
950 
951 #define VMRG_DO(name, element, access, ofs)                                  \
952     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)            \
953     {                                                                        \
954         ppc_avr_t result;                                                    \
955         int i, half = ARRAY_SIZE(r->element) / 2;                            \
956                                                                              \
957         for (i = 0; i < half; i++) {                                         \
958             result.access(i * 2 + 0) = a->access(i + ofs);                   \
959             result.access(i * 2 + 1) = b->access(i + ofs);                   \
960         }                                                                    \
961         *r = result;                                                         \
962     }
963 
964 #define VMRG(suffix, element, access)          \
965     VMRG_DO(mrgl##suffix, element, access, half)   \
966     VMRG_DO(mrgh##suffix, element, access, 0)
967 VMRG(b, u8, VsrB)
968 VMRG(h, u16, VsrH)
969 VMRG(w, u32, VsrW)
970 #undef VMRG_DO
971 #undef VMRG
972 
973 void helper_VMSUMMBM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
974 {
975     int32_t prod[16];
976     int i;
977 
978     for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
979         prod[i] = (int32_t)a->s8[i] * b->u8[i];
980     }
981 
982     VECTOR_FOR_INORDER_I(i, s32) {
983         r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
984             prod[4 * i + 2] + prod[4 * i + 3];
985     }
986 }
987 
988 void helper_VMSUMSHM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
989 {
990     int32_t prod[8];
991     int i;
992 
993     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
994         prod[i] = a->s16[i] * b->s16[i];
995     }
996 
997     VECTOR_FOR_INORDER_I(i, s32) {
998         r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
999     }
1000 }
1001 
1002 void helper_VMSUMSHS(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
1003                      ppc_avr_t *b, ppc_avr_t *c)
1004 {
1005     int32_t prod[8];
1006     int i;
1007     int sat = 0;
1008 
1009     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
1010         prod[i] = (int32_t)a->s16[i] * b->s16[i];
1011     }
1012 
1013     VECTOR_FOR_INORDER_I(i, s32) {
1014         int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
1015 
1016         r->u32[i] = cvtsdsw(t, &sat);
1017     }
1018 
1019     if (sat) {
1020         set_vscr_sat(env);
1021     }
1022 }
1023 
1024 void helper_VMSUMUBM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1025 {
1026     uint16_t prod[16];
1027     int i;
1028 
1029     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1030         prod[i] = a->u8[i] * b->u8[i];
1031     }
1032 
1033     VECTOR_FOR_INORDER_I(i, u32) {
1034         r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
1035             prod[4 * i + 2] + prod[4 * i + 3];
1036     }
1037 }
1038 
1039 void helper_VMSUMUHM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1040 {
1041     uint32_t prod[8];
1042     int i;
1043 
1044     for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
1045         prod[i] = a->u16[i] * b->u16[i];
1046     }
1047 
1048     VECTOR_FOR_INORDER_I(i, u32) {
1049         r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
1050     }
1051 }
1052 
1053 void helper_VMSUMUHS(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
1054                      ppc_avr_t *b, ppc_avr_t *c)
1055 {
1056     uint32_t prod[8];
1057     int i;
1058     int sat = 0;
1059 
1060     for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
1061         prod[i] = a->u16[i] * b->u16[i];
1062     }
1063 
1064     VECTOR_FOR_INORDER_I(i, s32) {
1065         uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
1066 
1067         r->u32[i] = cvtuduw(t, &sat);
1068     }
1069 
1070     if (sat) {
1071         set_vscr_sat(env);
1072     }
1073 }
1074 
1075 #define VMUL_DO_EVN(name, mul_element, mul_access, prod_access, cast)   \
1076     void helper_V##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
1077     {                                                                   \
1078         int i;                                                          \
1079                                                                         \
1080         for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) {           \
1081             r->prod_access(i >> 1) = (cast)a->mul_access(i) *           \
1082                                      (cast)b->mul_access(i);            \
1083         }                                                               \
1084     }
1085 
1086 #define VMUL_DO_ODD(name, mul_element, mul_access, prod_access, cast)   \
1087     void helper_V##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
1088     {                                                                   \
1089         int i;                                                          \
1090                                                                         \
1091         for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) {           \
1092             r->prod_access(i >> 1) = (cast)a->mul_access(i + 1) *       \
1093                                      (cast)b->mul_access(i + 1);        \
1094         }                                                               \
1095     }
1096 
1097 #define VMUL(suffix, mul_element, mul_access, prod_access, cast)       \
1098     VMUL_DO_EVN(MULE##suffix, mul_element, mul_access, prod_access, cast)  \
1099     VMUL_DO_ODD(MULO##suffix, mul_element, mul_access, prod_access, cast)
1100 VMUL(SB, s8, VsrSB, VsrSH, int16_t)
1101 VMUL(SH, s16, VsrSH, VsrSW, int32_t)
1102 VMUL(SW, s32, VsrSW, VsrSD, int64_t)
1103 VMUL(UB, u8, VsrB, VsrH, uint16_t)
1104 VMUL(UH, u16, VsrH, VsrW, uint32_t)
1105 VMUL(UW, u32, VsrW, VsrD, uint64_t)
1106 #undef VMUL_DO_EVN
1107 #undef VMUL_DO_ODD
1108 #undef VMUL
1109 
1110 void helper_XXPERMX(ppc_vsr_t *t, ppc_vsr_t *s0, ppc_vsr_t *s1, ppc_vsr_t *pcv,
1111                     target_ulong uim)
1112 {
1113     int i, idx;
1114     ppc_vsr_t tmp = { .u64 = {0, 0} };
1115 
1116     for (i = 0; i < ARRAY_SIZE(t->u8); i++) {
1117         if ((pcv->VsrB(i) >> 5) == uim) {
1118             idx = pcv->VsrB(i) & 0x1f;
1119             if (idx < ARRAY_SIZE(t->u8)) {
1120                 tmp.VsrB(i) = s0->VsrB(idx);
1121             } else {
1122                 tmp.VsrB(i) = s1->VsrB(idx - ARRAY_SIZE(t->u8));
1123             }
1124         }
1125     }
1126 
1127     *t = tmp;
1128 }
1129 
1130 void helper_VDIVSQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
1131 {
1132     Int128 neg1 = int128_makes64(-1);
1133     Int128 int128_min = int128_make128(0, INT64_MIN);
1134     if (likely(int128_nz(b->s128) &&
1135               (int128_ne(a->s128, int128_min) || int128_ne(b->s128, neg1)))) {
1136         t->s128 = int128_divs(a->s128, b->s128);
1137     } else {
1138         t->s128 = a->s128; /* Undefined behavior */
1139     }
1140 }
1141 
1142 void helper_VDIVUQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
1143 {
1144     if (int128_nz(b->s128)) {
1145         t->s128 = int128_divu(a->s128, b->s128);
1146     } else {
1147         t->s128 = a->s128; /* Undefined behavior */
1148     }
1149 }
1150 
1151 void helper_VDIVESD(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
1152 {
1153     int i;
1154     int64_t high;
1155     uint64_t low;
1156     for (i = 0; i < 2; i++) {
1157         high = a->s64[i];
1158         low = 0;
1159         if (unlikely((high == INT64_MIN && b->s64[i] == -1) || !b->s64[i])) {
1160             t->s64[i] = a->s64[i]; /* Undefined behavior */
1161         } else {
1162             divs128(&low, &high, b->s64[i]);
1163             t->s64[i] = low;
1164         }
1165     }
1166 }
1167 
1168 void helper_VDIVEUD(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
1169 {
1170     int i;
1171     uint64_t high, low;
1172     for (i = 0; i < 2; i++) {
1173         high = a->u64[i];
1174         low = 0;
1175         if (unlikely(!b->u64[i])) {
1176             t->u64[i] = a->u64[i]; /* Undefined behavior */
1177         } else {
1178             divu128(&low, &high, b->u64[i]);
1179             t->u64[i] = low;
1180         }
1181     }
1182 }
1183 
1184 void helper_VDIVESQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
1185 {
1186     Int128 high, low;
1187     Int128 int128_min = int128_make128(0, INT64_MIN);
1188     Int128 neg1 = int128_makes64(-1);
1189 
1190     high = a->s128;
1191     low = int128_zero();
1192     if (unlikely(!int128_nz(b->s128) ||
1193                  (int128_eq(b->s128, neg1) && int128_eq(high, int128_min)))) {
1194         t->s128 = a->s128; /* Undefined behavior */
1195     } else {
1196         divs256(&low, &high, b->s128);
1197         t->s128 = low;
1198     }
1199 }
1200 
1201 void helper_VDIVEUQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
1202 {
1203     Int128 high, low;
1204 
1205     high = a->s128;
1206     low = int128_zero();
1207     if (unlikely(!int128_nz(b->s128))) {
1208         t->s128 = a->s128; /* Undefined behavior */
1209     } else {
1210         divu256(&low, &high, b->s128);
1211         t->s128 = low;
1212     }
1213 }
1214 
1215 void helper_VMODSQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
1216 {
1217     Int128 neg1 = int128_makes64(-1);
1218     Int128 int128_min = int128_make128(0, INT64_MIN);
1219     if (likely(int128_nz(b->s128) &&
1220               (int128_ne(a->s128, int128_min) || int128_ne(b->s128, neg1)))) {
1221         t->s128 = int128_rems(a->s128, b->s128);
1222     } else {
1223         t->s128 = int128_zero(); /* Undefined behavior */
1224     }
1225 }
1226 
1227 void helper_VMODUQ(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b)
1228 {
1229     if (likely(int128_nz(b->s128))) {
1230         t->s128 = int128_remu(a->s128, b->s128);
1231     } else {
1232         t->s128 = int128_zero(); /* Undefined behavior */
1233     }
1234 }
1235 
1236 void helper_VPERM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1237 {
1238     ppc_avr_t result;
1239     int i;
1240 
1241     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1242         int s = c->VsrB(i) & 0x1f;
1243         int index = s & 0xf;
1244 
1245         if (s & 0x10) {
1246             result.VsrB(i) = b->VsrB(index);
1247         } else {
1248             result.VsrB(i) = a->VsrB(index);
1249         }
1250     }
1251     *r = result;
1252 }
1253 
1254 void helper_VPERMR(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1255 {
1256     ppc_avr_t result;
1257     int i;
1258 
1259     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1260         int s = c->VsrB(i) & 0x1f;
1261         int index = 15 - (s & 0xf);
1262 
1263         if (s & 0x10) {
1264             result.VsrB(i) = a->VsrB(index);
1265         } else {
1266             result.VsrB(i) = b->VsrB(index);
1267         }
1268     }
1269     *r = result;
1270 }
1271 
1272 #define XXGENPCV_BE_EXP(NAME, SZ) \
1273 void glue(helper_, glue(NAME, _be_exp))(ppc_vsr_t *t, ppc_vsr_t *b) \
1274 {                                                                   \
1275     ppc_vsr_t tmp;                                                  \
1276                                                                     \
1277     /* Initialize tmp with the result of an all-zeros mask */       \
1278     tmp.VsrD(0) = 0x1011121314151617;                               \
1279     tmp.VsrD(1) = 0x18191A1B1C1D1E1F;                               \
1280                                                                     \
1281     /* Iterate over the most significant byte of each element */    \
1282     for (int i = 0, j = 0; i < ARRAY_SIZE(b->u8); i += SZ) {        \
1283         if (b->VsrB(i) & 0x80) {                                    \
1284             /* Update each byte of the element */                   \
1285             for (int k = 0; k < SZ; k++) {                          \
1286                 tmp.VsrB(i + k) = j + k;                            \
1287             }                                                       \
1288             j += SZ;                                                \
1289         }                                                           \
1290     }                                                               \
1291                                                                     \
1292     *t = tmp;                                                       \
1293 }
1294 
1295 #define XXGENPCV_BE_COMP(NAME, SZ) \
1296 void glue(helper_, glue(NAME, _be_comp))(ppc_vsr_t *t, ppc_vsr_t *b)\
1297 {                                                                   \
1298     ppc_vsr_t tmp = { .u64 = { 0, 0 } };                            \
1299                                                                     \
1300     /* Iterate over the most significant byte of each element */    \
1301     for (int i = 0, j = 0; i < ARRAY_SIZE(b->u8); i += SZ) {        \
1302         if (b->VsrB(i) & 0x80) {                                    \
1303             /* Update each byte of the element */                   \
1304             for (int k = 0; k < SZ; k++) {                          \
1305                 tmp.VsrB(j + k) = i + k;                            \
1306             }                                                       \
1307             j += SZ;                                                \
1308         }                                                           \
1309     }                                                               \
1310                                                                     \
1311     *t = tmp;                                                       \
1312 }
1313 
1314 #define XXGENPCV_LE_EXP(NAME, SZ) \
1315 void glue(helper_, glue(NAME, _le_exp))(ppc_vsr_t *t, ppc_vsr_t *b) \
1316 {                                                                   \
1317     ppc_vsr_t tmp;                                                  \
1318                                                                     \
1319     /* Initialize tmp with the result of an all-zeros mask */       \
1320     tmp.VsrD(0) = 0x1F1E1D1C1B1A1918;                               \
1321     tmp.VsrD(1) = 0x1716151413121110;                               \
1322                                                                     \
1323     /* Iterate over the most significant byte of each element */    \
1324     for (int i = 0, j = 0; i < ARRAY_SIZE(b->u8); i += SZ) {        \
1325         /* Reverse indexing of "i" */                               \
1326         const int idx = ARRAY_SIZE(b->u8) - i - SZ;                 \
1327         if (b->VsrB(idx) & 0x80) {                                  \
1328             /* Update each byte of the element */                   \
1329             for (int k = 0, rk = SZ - 1; k < SZ; k++, rk--) {       \
1330                 tmp.VsrB(idx + rk) = j + k;                         \
1331             }                                                       \
1332             j += SZ;                                                \
1333         }                                                           \
1334     }                                                               \
1335                                                                     \
1336     *t = tmp;                                                       \
1337 }
1338 
1339 #define XXGENPCV_LE_COMP(NAME, SZ) \
1340 void glue(helper_, glue(NAME, _le_comp))(ppc_vsr_t *t, ppc_vsr_t *b)\
1341 {                                                                   \
1342     ppc_vsr_t tmp = { .u64 = { 0, 0 } };                            \
1343                                                                     \
1344     /* Iterate over the most significant byte of each element */    \
1345     for (int i = 0, j = 0; i < ARRAY_SIZE(b->u8); i += SZ) {        \
1346         if (b->VsrB(ARRAY_SIZE(b->u8) - i - SZ) & 0x80) {           \
1347             /* Update each byte of the element */                   \
1348             for (int k = 0, rk = SZ - 1; k < SZ; k++, rk--) {       \
1349                 /* Reverse indexing of "j" */                       \
1350                 const int idx = ARRAY_SIZE(b->u8) - j - SZ;         \
1351                 tmp.VsrB(idx + rk) = i + k;                         \
1352             }                                                       \
1353             j += SZ;                                                \
1354         }                                                           \
1355     }                                                               \
1356                                                                     \
1357     *t = tmp;                                                       \
1358 }
1359 
1360 #define XXGENPCV(NAME, SZ) \
1361     XXGENPCV_BE_EXP(NAME, SZ)  \
1362     XXGENPCV_BE_COMP(NAME, SZ) \
1363     XXGENPCV_LE_EXP(NAME, SZ)  \
1364     XXGENPCV_LE_COMP(NAME, SZ) \
1365 
1366 XXGENPCV(XXGENPCVBM, 1)
1367 XXGENPCV(XXGENPCVHM, 2)
1368 XXGENPCV(XXGENPCVWM, 4)
1369 XXGENPCV(XXGENPCVDM, 8)
1370 
1371 #undef XXGENPCV_BE_EXP
1372 #undef XXGENPCV_BE_COMP
1373 #undef XXGENPCV_LE_EXP
1374 #undef XXGENPCV_LE_COMP
1375 #undef XXGENPCV
1376 
1377 #if HOST_BIG_ENDIAN
1378 #define VBPERMQ_INDEX(avr, i) ((avr)->u8[(i)])
1379 #define VBPERMD_INDEX(i) (i)
1380 #define VBPERMQ_DW(index) (((index) & 0x40) != 0)
1381 #else
1382 #define VBPERMQ_INDEX(avr, i) ((avr)->u8[15 - (i)])
1383 #define VBPERMD_INDEX(i) (1 - i)
1384 #define VBPERMQ_DW(index) (((index) & 0x40) == 0)
1385 #endif
1386 #define EXTRACT_BIT(avr, i, index) \
1387         (extract64((avr)->VsrD(i), 63 - index, 1))
1388 
1389 void helper_vbpermd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1390 {
1391     int i, j;
1392     ppc_avr_t result = { .u64 = { 0, 0 } };
1393     VECTOR_FOR_INORDER_I(i, u64) {
1394         for (j = 0; j < 8; j++) {
1395             int index = VBPERMQ_INDEX(b, (i * 8) + j);
1396             if (index < 64 && EXTRACT_BIT(a, i, index)) {
1397                 result.u64[VBPERMD_INDEX(i)] |= (0x80 >> j);
1398             }
1399         }
1400     }
1401     *r = result;
1402 }
1403 
1404 void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1405 {
1406     int i;
1407     uint64_t perm = 0;
1408 
1409     VECTOR_FOR_INORDER_I(i, u8) {
1410         int index = VBPERMQ_INDEX(b, i);
1411 
1412         if (index < 128) {
1413             uint64_t mask = (1ull << (63 - (index & 0x3F)));
1414             if (a->u64[VBPERMQ_DW(index)] & mask) {
1415                 perm |= (0x8000 >> i);
1416             }
1417         }
1418     }
1419 
1420     r->VsrD(0) = perm;
1421     r->VsrD(1) = 0;
1422 }
1423 
1424 #undef VBPERMQ_INDEX
1425 #undef VBPERMQ_DW
1426 
1427 #define PMSUM(name, srcfld, trgfld, trgtyp)                   \
1428 void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
1429 {                                                             \
1430     int i, j;                                                 \
1431     trgtyp prod[sizeof(ppc_avr_t) / sizeof(a->srcfld[0])];    \
1432                                                               \
1433     VECTOR_FOR_INORDER_I(i, srcfld) {                         \
1434         prod[i] = 0;                                          \
1435         for (j = 0; j < sizeof(a->srcfld[0]) * 8; j++) {      \
1436             if (a->srcfld[i] & (1ull << j)) {                 \
1437                 prod[i] ^= ((trgtyp)b->srcfld[i] << j);       \
1438             }                                                 \
1439         }                                                     \
1440     }                                                         \
1441                                                               \
1442     VECTOR_FOR_INORDER_I(i, trgfld) {                         \
1443         r->trgfld[i] = prod[2 * i] ^ prod[2 * i + 1];         \
1444     }                                                         \
1445 }
1446 
1447 PMSUM(vpmsumb, u8, u16, uint16_t)
1448 PMSUM(vpmsumh, u16, u32, uint32_t)
1449 PMSUM(vpmsumw, u32, u64, uint64_t)
1450 
1451 void helper_VPMSUMD(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1452 {
1453     int i, j;
1454     Int128 tmp, prod[2] = {int128_zero(), int128_zero()};
1455 
1456     for (j = 0; j < 64; j++) {
1457         for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1458             if (a->VsrD(i) & (1ull << j)) {
1459                 tmp = int128_make64(b->VsrD(i));
1460                 tmp = int128_lshift(tmp, j);
1461                 prod[i] = int128_xor(prod[i], tmp);
1462             }
1463         }
1464     }
1465 
1466     r->s128 = int128_xor(prod[0], prod[1]);
1467 }
1468 
1469 #if HOST_BIG_ENDIAN
1470 #define PKBIG 1
1471 #else
1472 #define PKBIG 0
1473 #endif
1474 void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1475 {
1476     int i, j;
1477     ppc_avr_t result;
1478 #if HOST_BIG_ENDIAN
1479     const ppc_avr_t *x[2] = { a, b };
1480 #else
1481     const ppc_avr_t *x[2] = { b, a };
1482 #endif
1483 
1484     VECTOR_FOR_INORDER_I(i, u64) {
1485         VECTOR_FOR_INORDER_I(j, u32) {
1486             uint32_t e = x[i]->u32[j];
1487 
1488             result.u16[4 * i + j] = (((e >> 9) & 0xfc00) |
1489                                      ((e >> 6) & 0x3e0) |
1490                                      ((e >> 3) & 0x1f));
1491         }
1492     }
1493     *r = result;
1494 }
1495 
1496 #define VPK(suffix, from, to, cvt, dosat)                               \
1497     void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r,             \
1498                             ppc_avr_t *a, ppc_avr_t *b)                 \
1499     {                                                                   \
1500         int i;                                                          \
1501         int sat = 0;                                                    \
1502         ppc_avr_t result;                                               \
1503         ppc_avr_t *a0 = PKBIG ? a : b;                                  \
1504         ppc_avr_t *a1 = PKBIG ? b : a;                                  \
1505                                                                         \
1506         VECTOR_FOR_INORDER_I(i, from) {                                 \
1507             result.to[i] = cvt(a0->from[i], &sat);                      \
1508             result.to[i + ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);\
1509         }                                                               \
1510         *r = result;                                                    \
1511         if (dosat && sat) {                                             \
1512             set_vscr_sat(env);                                          \
1513         }                                                               \
1514     }
1515 #define I(x, y) (x)
1516 VPK(shss, s16, s8, cvtshsb, 1)
1517 VPK(shus, s16, u8, cvtshub, 1)
1518 VPK(swss, s32, s16, cvtswsh, 1)
1519 VPK(swus, s32, u16, cvtswuh, 1)
1520 VPK(sdss, s64, s32, cvtsdsw, 1)
1521 VPK(sdus, s64, u32, cvtsduw, 1)
1522 VPK(uhus, u16, u8, cvtuhub, 1)
1523 VPK(uwus, u32, u16, cvtuwuh, 1)
1524 VPK(udus, u64, u32, cvtuduw, 1)
1525 VPK(uhum, u16, u8, I, 0)
1526 VPK(uwum, u32, u16, I, 0)
1527 VPK(udum, u64, u32, I, 0)
1528 #undef I
1529 #undef VPK
1530 #undef PKBIG
1531 
1532 void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1533 {
1534     int i;
1535 
1536     for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
1537         r->f32[i] = float32_div(float32_one, b->f32[i], &env->vec_status);
1538     }
1539 }
1540 
1541 #define VRFI(suffix, rounding)                                  \
1542     void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r,    \
1543                              ppc_avr_t *b)                      \
1544     {                                                           \
1545         int i;                                                  \
1546         float_status s = env->vec_status;                       \
1547                                                                 \
1548         set_float_rounding_mode(rounding, &s);                  \
1549         for (i = 0; i < ARRAY_SIZE(r->f32); i++) {              \
1550             r->f32[i] = float32_round_to_int (b->f32[i], &s);   \
1551         }                                                       \
1552     }
1553 VRFI(n, float_round_nearest_even)
1554 VRFI(m, float_round_down)
1555 VRFI(p, float_round_up)
1556 VRFI(z, float_round_to_zero)
1557 #undef VRFI
1558 
1559 void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1560 {
1561     int i;
1562 
1563     for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
1564         float32 t = float32_sqrt(b->f32[i], &env->vec_status);
1565 
1566         r->f32[i] = float32_div(float32_one, t, &env->vec_status);
1567     }
1568 }
1569 
1570 #define VRLMI(name, size, element, insert)                                  \
1571 void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t desc) \
1572 {                                                                           \
1573     int i;                                                                  \
1574     for (i = 0; i < ARRAY_SIZE(r->element); i++) {                          \
1575         uint##size##_t src1 = a->element[i];                                \
1576         uint##size##_t src2 = b->element[i];                                \
1577         uint##size##_t src3 = r->element[i];                                \
1578         uint##size##_t begin, end, shift, mask, rot_val;                    \
1579                                                                             \
1580         shift = extract##size(src2, 0, 6);                                  \
1581         end   = extract##size(src2, 8, 6);                                  \
1582         begin = extract##size(src2, 16, 6);                                 \
1583         rot_val = rol##size(src1, shift);                                   \
1584         mask = mask_u##size(begin, end);                                    \
1585         if (insert) {                                                       \
1586             r->element[i] = (rot_val & mask) | (src3 & ~mask);              \
1587         } else {                                                            \
1588             r->element[i] = (rot_val & mask);                               \
1589         }                                                                   \
1590     }                                                                       \
1591 }
1592 
1593 VRLMI(VRLDMI, 64, u64, 1);
1594 VRLMI(VRLWMI, 32, u32, 1);
1595 VRLMI(VRLDNM, 64, u64, 0);
1596 VRLMI(VRLWNM, 32, u32, 0);
1597 
1598 void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1599 {
1600     int i;
1601 
1602     for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
1603         r->f32[i] = float32_exp2(b->f32[i], &env->vec_status);
1604     }
1605 }
1606 
1607 void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1608 {
1609     int i;
1610 
1611     for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
1612         r->f32[i] = float32_log2(b->f32[i], &env->vec_status);
1613     }
1614 }
1615 
1616 #define VEXTU_X_DO(name, size, left)                            \
1617 target_ulong glue(helper_, name)(target_ulong a, ppc_avr_t *b)  \
1618 {                                                               \
1619     int index = (a & 0xf) * 8;                                  \
1620     if (left) {                                                 \
1621         index = 128 - index - size;                             \
1622     }                                                           \
1623     return int128_getlo(int128_rshift(b->s128, index)) &        \
1624         MAKE_64BIT_MASK(0, size);                               \
1625 }
1626 VEXTU_X_DO(vextublx,  8, 1)
1627 VEXTU_X_DO(vextuhlx, 16, 1)
1628 VEXTU_X_DO(vextuwlx, 32, 1)
1629 VEXTU_X_DO(vextubrx,  8, 0)
1630 VEXTU_X_DO(vextuhrx, 16, 0)
1631 VEXTU_X_DO(vextuwrx, 32, 0)
1632 #undef VEXTU_X_DO
1633 
1634 void helper_vslv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1635 {
1636     int i;
1637     unsigned int shift, bytes, size;
1638 
1639     size = ARRAY_SIZE(r->u8);
1640     for (i = 0; i < size; i++) {
1641         shift = b->VsrB(i) & 0x7;             /* extract shift value */
1642         bytes = (a->VsrB(i) << 8) +           /* extract adjacent bytes */
1643             (((i + 1) < size) ? a->VsrB(i + 1) : 0);
1644         r->VsrB(i) = (bytes << shift) >> 8;   /* shift and store result */
1645     }
1646 }
1647 
1648 void helper_vsrv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1649 {
1650     int i;
1651     unsigned int shift, bytes;
1652 
1653     /*
1654      * Use reverse order, as destination and source register can be
1655      * same. Its being modified in place saving temporary, reverse
1656      * order will guarantee that computed result is not fed back.
1657      */
1658     for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) {
1659         shift = b->VsrB(i) & 0x7;               /* extract shift value */
1660         bytes = ((i ? a->VsrB(i - 1) : 0) << 8) + a->VsrB(i);
1661                                                 /* extract adjacent bytes */
1662         r->VsrB(i) = (bytes >> shift) & 0xFF;   /* shift and store result */
1663     }
1664 }
1665 
1666 void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
1667 {
1668     int sh = shift & 0xf;
1669     int i;
1670     ppc_avr_t result;
1671 
1672     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1673         int index = sh + i;
1674         if (index > 0xf) {
1675             result.VsrB(i) = b->VsrB(index - 0x10);
1676         } else {
1677             result.VsrB(i) = a->VsrB(index);
1678         }
1679     }
1680     *r = result;
1681 }
1682 
1683 void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1684 {
1685     int sh = (b->VsrB(0xf) >> 3) & 0xf;
1686 
1687 #if HOST_BIG_ENDIAN
1688     memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1689     memset(&r->u8[16 - sh], 0, sh);
1690 #else
1691     memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1692     memset(&r->u8[0], 0, sh);
1693 #endif
1694 }
1695 
1696 #if HOST_BIG_ENDIAN
1697 #define ELEM_ADDR(VEC, IDX, SIZE) (&(VEC)->u8[IDX])
1698 #else
1699 #define ELEM_ADDR(VEC, IDX, SIZE) (&(VEC)->u8[15 - (IDX)] - (SIZE) + 1)
1700 #endif
1701 
1702 #define VINSX(SUFFIX, TYPE) \
1703 void glue(glue(helper_VINS, SUFFIX), LX)(CPUPPCState *env, ppc_avr_t *t,       \
1704                                          uint64_t val, target_ulong index)     \
1705 {                                                                              \
1706     const int maxidx = ARRAY_SIZE(t->u8) - sizeof(TYPE);                       \
1707     target_long idx = index;                                                   \
1708                                                                                \
1709     if (idx < 0 || idx > maxidx) {                                             \
1710         idx =  idx < 0 ? sizeof(TYPE) - idx : idx;                             \
1711         qemu_log_mask(LOG_GUEST_ERROR,                                         \
1712             "Invalid index for Vector Insert Element after 0x" TARGET_FMT_lx   \
1713             ", RA = " TARGET_FMT_ld " > %d\n", env->nip, idx, maxidx);         \
1714     } else {                                                                   \
1715         TYPE src = val;                                                        \
1716         memcpy(ELEM_ADDR(t, idx, sizeof(TYPE)), &src, sizeof(TYPE));           \
1717     }                                                                          \
1718 }
1719 VINSX(B, uint8_t)
1720 VINSX(H, uint16_t)
1721 VINSX(W, uint32_t)
1722 VINSX(D, uint64_t)
1723 #undef ELEM_ADDR
1724 #undef VINSX
1725 #if HOST_BIG_ENDIAN
1726 #define VEXTDVLX(NAME, SIZE) \
1727 void helper_##NAME(CPUPPCState *env, ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, \
1728                    target_ulong index)                                         \
1729 {                                                                              \
1730     const target_long idx = index;                                             \
1731     ppc_avr_t tmp[2] = { *a, *b };                                             \
1732     memset(t, 0, sizeof(*t));                                                  \
1733     if (idx >= 0 && idx + SIZE <= sizeof(tmp)) {                               \
1734         memcpy(&t->u8[ARRAY_SIZE(t->u8) / 2 - SIZE], (void *)tmp + idx, SIZE); \
1735     } else {                                                                   \
1736         qemu_log_mask(LOG_GUEST_ERROR, "Invalid index for " #NAME " after 0x"  \
1737                       TARGET_FMT_lx ", RC = " TARGET_FMT_ld " > %d\n",         \
1738                       env->nip, idx < 0 ? SIZE - idx : idx, 32 - SIZE);        \
1739     }                                                                          \
1740 }
1741 #else
1742 #define VEXTDVLX(NAME, SIZE) \
1743 void helper_##NAME(CPUPPCState *env, ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, \
1744                    target_ulong index)                                         \
1745 {                                                                              \
1746     const target_long idx = index;                                             \
1747     ppc_avr_t tmp[2] = { *b, *a };                                             \
1748     memset(t, 0, sizeof(*t));                                                  \
1749     if (idx >= 0 && idx + SIZE <= sizeof(tmp)) {                               \
1750         memcpy(&t->u8[ARRAY_SIZE(t->u8) / 2],                                  \
1751                (void *)tmp + sizeof(tmp) - SIZE - idx, SIZE);                  \
1752     } else {                                                                   \
1753         qemu_log_mask(LOG_GUEST_ERROR, "Invalid index for " #NAME " after 0x"  \
1754                       TARGET_FMT_lx ", RC = " TARGET_FMT_ld " > %d\n",         \
1755                       env->nip, idx < 0 ? SIZE - idx : idx, 32 - SIZE);        \
1756     }                                                                          \
1757 }
1758 #endif
1759 VEXTDVLX(VEXTDUBVLX, 1)
1760 VEXTDVLX(VEXTDUHVLX, 2)
1761 VEXTDVLX(VEXTDUWVLX, 4)
1762 VEXTDVLX(VEXTDDVLX, 8)
1763 #undef VEXTDVLX
1764 #if HOST_BIG_ENDIAN
1765 #define VEXTRACT(suffix, element)                                            \
1766     void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
1767     {                                                                        \
1768         uint32_t es = sizeof(r->element[0]);                                 \
1769         memmove(&r->u8[8 - es], &b->u8[index], es);                          \
1770         memset(&r->u8[8], 0, 8);                                             \
1771         memset(&r->u8[0], 0, 8 - es);                                        \
1772     }
1773 #else
1774 #define VEXTRACT(suffix, element)                                            \
1775     void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
1776     {                                                                        \
1777         uint32_t es = sizeof(r->element[0]);                                 \
1778         uint32_t s = (16 - index) - es;                                      \
1779         memmove(&r->u8[8], &b->u8[s], es);                                   \
1780         memset(&r->u8[0], 0, 8);                                             \
1781         memset(&r->u8[8 + es], 0, 8 - es);                                   \
1782     }
1783 #endif
1784 VEXTRACT(ub, u8)
1785 VEXTRACT(uh, u16)
1786 VEXTRACT(uw, u32)
1787 VEXTRACT(d, u64)
1788 #undef VEXTRACT
1789 
1790 #define VSTRI(NAME, ELEM, NUM_ELEMS, LEFT) \
1791 uint32_t helper_##NAME(ppc_avr_t *t, ppc_avr_t *b) \
1792 {                                                   \
1793     int i, idx, crf = 0;                            \
1794                                                     \
1795     for (i = 0; i < NUM_ELEMS; i++) {               \
1796         idx = LEFT ? i : NUM_ELEMS - i - 1;         \
1797         if (b->Vsr##ELEM(idx)) {                    \
1798             t->Vsr##ELEM(idx) = b->Vsr##ELEM(idx);  \
1799         } else {                                    \
1800             crf = 0b0010;                           \
1801             break;                                  \
1802         }                                           \
1803     }                                               \
1804                                                     \
1805     for (; i < NUM_ELEMS; i++) {                    \
1806         idx = LEFT ? i : NUM_ELEMS - i - 1;         \
1807         t->Vsr##ELEM(idx) = 0;                      \
1808     }                                               \
1809                                                     \
1810     return crf;                                     \
1811 }
1812 VSTRI(VSTRIBL, B, 16, true)
1813 VSTRI(VSTRIBR, B, 16, false)
1814 VSTRI(VSTRIHL, H, 8, true)
1815 VSTRI(VSTRIHR, H, 8, false)
1816 #undef VSTRI
1817 
1818 void helper_XXEXTRACTUW(ppc_vsr_t *xt, ppc_vsr_t *xb, uint32_t index)
1819 {
1820     ppc_vsr_t t = { };
1821     size_t es = sizeof(uint32_t);
1822     uint32_t ext_index;
1823     int i;
1824 
1825     ext_index = index;
1826     for (i = 0; i < es; i++, ext_index++) {
1827         t.VsrB(8 - es + i) = xb->VsrB(ext_index % 16);
1828     }
1829 
1830     *xt = t;
1831 }
1832 
1833 void helper_XXINSERTW(ppc_vsr_t *xt, ppc_vsr_t *xb, uint32_t index)
1834 {
1835     ppc_vsr_t t = *xt;
1836     size_t es = sizeof(uint32_t);
1837     int ins_index, i = 0;
1838 
1839     ins_index = index;
1840     for (i = 0; i < es && ins_index < 16; i++, ins_index++) {
1841         t.VsrB(ins_index) = xb->VsrB(8 - es + i);
1842     }
1843 
1844     *xt = t;
1845 }
1846 
1847 void helper_XXEVAL(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c,
1848                    uint32_t desc)
1849 {
1850     /*
1851      * Instead of processing imm bit-by-bit, we'll skip the computation of
1852      * conjunctions whose corresponding bit is unset.
1853      */
1854     int bit, imm = simd_data(desc);
1855     Int128 conj, disj = int128_zero();
1856 
1857     /* Iterate over set bits from the least to the most significant bit */
1858     while (imm) {
1859         /*
1860          * Get the next bit to be processed with ctz64. Invert the result of
1861          * ctz64 to match the indexing used by PowerISA.
1862          */
1863         bit = 7 - ctzl(imm);
1864         if (bit & 0x4) {
1865             conj = a->s128;
1866         } else {
1867             conj = int128_not(a->s128);
1868         }
1869         if (bit & 0x2) {
1870             conj = int128_and(conj, b->s128);
1871         } else {
1872             conj = int128_and(conj, int128_not(b->s128));
1873         }
1874         if (bit & 0x1) {
1875             conj = int128_and(conj, c->s128);
1876         } else {
1877             conj = int128_and(conj, int128_not(c->s128));
1878         }
1879         disj = int128_or(disj, conj);
1880 
1881         /* Unset the least significant bit that is set */
1882         imm &= imm - 1;
1883     }
1884 
1885     t->s128 = disj;
1886 }
1887 
1888 #define XXBLEND(name, sz) \
1889 void glue(helper_XXBLENDV, name)(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b,  \
1890                                  ppc_avr_t *c, uint32_t desc)               \
1891 {                                                                           \
1892     for (int i = 0; i < ARRAY_SIZE(t->glue(u, sz)); i++) {                  \
1893         t->glue(u, sz)[i] = (c->glue(s, sz)[i] >> (sz - 1)) ?               \
1894             b->glue(u, sz)[i] : a->glue(u, sz)[i];                          \
1895     }                                                                       \
1896 }
1897 XXBLEND(B, 8)
1898 XXBLEND(H, 16)
1899 XXBLEND(W, 32)
1900 XXBLEND(D, 64)
1901 #undef XXBLEND
1902 
1903 void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1904 {
1905     int sh = (b->VsrB(0xf) >> 3) & 0xf;
1906 
1907 #if HOST_BIG_ENDIAN
1908     memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1909     memset(&r->u8[0], 0, sh);
1910 #else
1911     memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1912     memset(&r->u8[16 - sh], 0, sh);
1913 #endif
1914 }
1915 
1916 void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1917 {
1918     int64_t t;
1919     int i, upper;
1920     ppc_avr_t result;
1921     int sat = 0;
1922 
1923     upper = ARRAY_SIZE(r->s32) - 1;
1924     t = (int64_t)b->VsrSW(upper);
1925     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1926         t += a->VsrSW(i);
1927         result.VsrSW(i) = 0;
1928     }
1929     result.VsrSW(upper) = cvtsdsw(t, &sat);
1930     *r = result;
1931 
1932     if (sat) {
1933         set_vscr_sat(env);
1934     }
1935 }
1936 
1937 void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1938 {
1939     int i, j, upper;
1940     ppc_avr_t result;
1941     int sat = 0;
1942 
1943     upper = 1;
1944     for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1945         int64_t t = (int64_t)b->VsrSW(upper + i * 2);
1946 
1947         result.VsrD(i) = 0;
1948         for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
1949             t += a->VsrSW(2 * i + j);
1950         }
1951         result.VsrSW(upper + i * 2) = cvtsdsw(t, &sat);
1952     }
1953 
1954     *r = result;
1955     if (sat) {
1956         set_vscr_sat(env);
1957     }
1958 }
1959 
1960 void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1961 {
1962     int i, j;
1963     int sat = 0;
1964 
1965     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1966         int64_t t = (int64_t)b->s32[i];
1967 
1968         for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
1969             t += a->s8[4 * i + j];
1970         }
1971         r->s32[i] = cvtsdsw(t, &sat);
1972     }
1973 
1974     if (sat) {
1975         set_vscr_sat(env);
1976     }
1977 }
1978 
1979 void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1980 {
1981     int sat = 0;
1982     int i;
1983 
1984     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1985         int64_t t = (int64_t)b->s32[i];
1986 
1987         t += a->s16[2 * i] + a->s16[2 * i + 1];
1988         r->s32[i] = cvtsdsw(t, &sat);
1989     }
1990 
1991     if (sat) {
1992         set_vscr_sat(env);
1993     }
1994 }
1995 
1996 void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1997 {
1998     int i, j;
1999     int sat = 0;
2000 
2001     for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2002         uint64_t t = (uint64_t)b->u32[i];
2003 
2004         for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
2005             t += a->u8[4 * i + j];
2006         }
2007         r->u32[i] = cvtuduw(t, &sat);
2008     }
2009 
2010     if (sat) {
2011         set_vscr_sat(env);
2012     }
2013 }
2014 
2015 #if HOST_BIG_ENDIAN
2016 #define UPKHI 1
2017 #define UPKLO 0
2018 #else
2019 #define UPKHI 0
2020 #define UPKLO 1
2021 #endif
2022 #define VUPKPX(suffix, hi)                                              \
2023     void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
2024     {                                                                   \
2025         int i;                                                          \
2026         ppc_avr_t result;                                               \
2027                                                                         \
2028         for (i = 0; i < ARRAY_SIZE(r->u32); i++) {                      \
2029             uint16_t e = b->u16[hi ? i : i + 4];                        \
2030             uint8_t a = (e >> 15) ? 0xff : 0;                           \
2031             uint8_t r = (e >> 10) & 0x1f;                               \
2032             uint8_t g = (e >> 5) & 0x1f;                                \
2033             uint8_t b = e & 0x1f;                                       \
2034                                                                         \
2035             result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
2036         }                                                               \
2037         *r = result;                                                    \
2038     }
2039 VUPKPX(lpx, UPKLO)
2040 VUPKPX(hpx, UPKHI)
2041 #undef VUPKPX
2042 
2043 #define VUPK(suffix, unpacked, packee, hi)                              \
2044     void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
2045     {                                                                   \
2046         int i;                                                          \
2047         ppc_avr_t result;                                               \
2048                                                                         \
2049         if (hi) {                                                       \
2050             for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
2051                 result.unpacked[i] = b->packee[i];                      \
2052             }                                                           \
2053         } else {                                                        \
2054             for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
2055                  i++) {                                                 \
2056                 result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
2057             }                                                           \
2058         }                                                               \
2059         *r = result;                                                    \
2060     }
2061 VUPK(hsb, s16, s8, UPKHI)
2062 VUPK(hsh, s32, s16, UPKHI)
2063 VUPK(hsw, s64, s32, UPKHI)
2064 VUPK(lsb, s16, s8, UPKLO)
2065 VUPK(lsh, s32, s16, UPKLO)
2066 VUPK(lsw, s64, s32, UPKLO)
2067 #undef VUPK
2068 #undef UPKHI
2069 #undef UPKLO
2070 
2071 #define VGENERIC_DO(name, element)                                      \
2072     void helper_v##name(ppc_avr_t *r, ppc_avr_t *b)                     \
2073     {                                                                   \
2074         int i;                                                          \
2075                                                                         \
2076         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2077             r->element[i] = name(b->element[i]);                        \
2078         }                                                               \
2079     }
2080 
2081 #define clzb(v) ((v) ? clz32((uint32_t)(v) << 24) : 8)
2082 #define clzh(v) ((v) ? clz32((uint32_t)(v) << 16) : 16)
2083 
2084 VGENERIC_DO(clzb, u8)
2085 VGENERIC_DO(clzh, u16)
2086 
2087 #undef clzb
2088 #undef clzh
2089 
2090 #define ctzb(v) ((v) ? ctz32(v) : 8)
2091 #define ctzh(v) ((v) ? ctz32(v) : 16)
2092 #define ctzw(v) ctz32((v))
2093 #define ctzd(v) ctz64((v))
2094 
2095 VGENERIC_DO(ctzb, u8)
2096 VGENERIC_DO(ctzh, u16)
2097 VGENERIC_DO(ctzw, u32)
2098 VGENERIC_DO(ctzd, u64)
2099 
2100 #undef ctzb
2101 #undef ctzh
2102 #undef ctzw
2103 #undef ctzd
2104 
2105 #define popcntb(v) ctpop8(v)
2106 #define popcnth(v) ctpop16(v)
2107 #define popcntw(v) ctpop32(v)
2108 #define popcntd(v) ctpop64(v)
2109 
2110 VGENERIC_DO(popcntb, u8)
2111 VGENERIC_DO(popcnth, u16)
2112 VGENERIC_DO(popcntw, u32)
2113 VGENERIC_DO(popcntd, u64)
2114 
2115 #undef popcntb
2116 #undef popcnth
2117 #undef popcntw
2118 #undef popcntd
2119 
2120 #undef VGENERIC_DO
2121 
2122 void helper_VADDUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2123 {
2124     r->s128 = int128_add(a->s128, b->s128);
2125 }
2126 
2127 void helper_VADDEUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2128 {
2129     r->s128 = int128_add(int128_add(a->s128, b->s128),
2130                          int128_make64(int128_getlo(c->s128) & 1));
2131 }
2132 
2133 void helper_VADDCUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2134 {
2135     r->VsrD(1) = int128_ult(int128_not(a->s128), b->s128);
2136     r->VsrD(0) = 0;
2137 }
2138 
2139 void helper_VADDECUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2140 {
2141     bool carry_out = int128_ult(int128_not(a->s128), b->s128),
2142          carry_in = int128_getlo(c->s128) & 1;
2143 
2144     if (!carry_out && carry_in) {
2145         carry_out = (int128_nz(a->s128) || int128_nz(b->s128)) &&
2146                     int128_eq(int128_add(a->s128, b->s128), int128_makes64(-1));
2147     }
2148 
2149     r->VsrD(0) = 0;
2150     r->VsrD(1) = carry_out;
2151 }
2152 
2153 void helper_VSUBUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2154 {
2155     r->s128 = int128_sub(a->s128, b->s128);
2156 }
2157 
2158 void helper_VSUBEUQM(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2159 {
2160     r->s128 = int128_add(int128_add(a->s128, int128_not(b->s128)),
2161                          int128_make64(int128_getlo(c->s128) & 1));
2162 }
2163 
2164 void helper_VSUBCUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2165 {
2166     Int128 tmp = int128_not(b->s128);
2167 
2168     r->VsrD(1) = int128_ult(int128_not(a->s128), tmp) ||
2169                  int128_eq(int128_add(a->s128, tmp), int128_makes64(-1));
2170     r->VsrD(0) = 0;
2171 }
2172 
2173 void helper_VSUBECUQ(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2174 {
2175     Int128 tmp = int128_not(b->s128);
2176     bool carry_out = int128_ult(int128_not(a->s128), tmp),
2177          carry_in = int128_getlo(c->s128) & 1;
2178 
2179     r->VsrD(1) = carry_out || (carry_in && int128_eq(int128_add(a->s128, tmp),
2180                                                      int128_makes64(-1)));
2181     r->VsrD(0) = 0;
2182 }
2183 
2184 #define BCD_PLUS_PREF_1 0xC
2185 #define BCD_PLUS_PREF_2 0xF
2186 #define BCD_PLUS_ALT_1  0xA
2187 #define BCD_NEG_PREF    0xD
2188 #define BCD_NEG_ALT     0xB
2189 #define BCD_PLUS_ALT_2  0xE
2190 #define NATIONAL_PLUS   0x2B
2191 #define NATIONAL_NEG    0x2D
2192 
2193 #define BCD_DIG_BYTE(n) (15 - ((n) / 2))
2194 
2195 static int bcd_get_sgn(ppc_avr_t *bcd)
2196 {
2197     switch (bcd->VsrB(BCD_DIG_BYTE(0)) & 0xF) {
2198     case BCD_PLUS_PREF_1:
2199     case BCD_PLUS_PREF_2:
2200     case BCD_PLUS_ALT_1:
2201     case BCD_PLUS_ALT_2:
2202     {
2203         return 1;
2204     }
2205 
2206     case BCD_NEG_PREF:
2207     case BCD_NEG_ALT:
2208     {
2209         return -1;
2210     }
2211 
2212     default:
2213     {
2214         return 0;
2215     }
2216     }
2217 }
2218 
2219 static int bcd_preferred_sgn(int sgn, int ps)
2220 {
2221     if (sgn >= 0) {
2222         return (ps == 0) ? BCD_PLUS_PREF_1 : BCD_PLUS_PREF_2;
2223     } else {
2224         return BCD_NEG_PREF;
2225     }
2226 }
2227 
2228 static uint8_t bcd_get_digit(ppc_avr_t *bcd, int n, int *invalid)
2229 {
2230     uint8_t result;
2231     if (n & 1) {
2232         result = bcd->VsrB(BCD_DIG_BYTE(n)) >> 4;
2233     } else {
2234        result = bcd->VsrB(BCD_DIG_BYTE(n)) & 0xF;
2235     }
2236 
2237     if (unlikely(result > 9)) {
2238         *invalid = true;
2239     }
2240     return result;
2241 }
2242 
2243 static void bcd_put_digit(ppc_avr_t *bcd, uint8_t digit, int n)
2244 {
2245     if (n & 1) {
2246         bcd->VsrB(BCD_DIG_BYTE(n)) &= 0x0F;
2247         bcd->VsrB(BCD_DIG_BYTE(n)) |= (digit << 4);
2248     } else {
2249         bcd->VsrB(BCD_DIG_BYTE(n)) &= 0xF0;
2250         bcd->VsrB(BCD_DIG_BYTE(n)) |= digit;
2251     }
2252 }
2253 
2254 static bool bcd_is_valid(ppc_avr_t *bcd)
2255 {
2256     int i;
2257     int invalid = 0;
2258 
2259     if (bcd_get_sgn(bcd) == 0) {
2260         return false;
2261     }
2262 
2263     for (i = 1; i < 32; i++) {
2264         bcd_get_digit(bcd, i, &invalid);
2265         if (unlikely(invalid)) {
2266             return false;
2267         }
2268     }
2269     return true;
2270 }
2271 
2272 static int bcd_cmp_zero(ppc_avr_t *bcd)
2273 {
2274     if (bcd->VsrD(0) == 0 && (bcd->VsrD(1) >> 4) == 0) {
2275         return CRF_EQ;
2276     } else {
2277         return (bcd_get_sgn(bcd) == 1) ? CRF_GT : CRF_LT;
2278     }
2279 }
2280 
2281 static uint16_t get_national_digit(ppc_avr_t *reg, int n)
2282 {
2283     return reg->VsrH(7 - n);
2284 }
2285 
2286 static void set_national_digit(ppc_avr_t *reg, uint8_t val, int n)
2287 {
2288     reg->VsrH(7 - n) = val;
2289 }
2290 
2291 static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b)
2292 {
2293     int i;
2294     int invalid = 0;
2295     for (i = 31; i > 0; i--) {
2296         uint8_t dig_a = bcd_get_digit(a, i, &invalid);
2297         uint8_t dig_b = bcd_get_digit(b, i, &invalid);
2298         if (unlikely(invalid)) {
2299             return 0; /* doesn't matter */
2300         } else if (dig_a > dig_b) {
2301             return 1;
2302         } else if (dig_a < dig_b) {
2303             return -1;
2304         }
2305     }
2306 
2307     return 0;
2308 }
2309 
2310 static int bcd_add_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
2311                        int *overflow)
2312 {
2313     int carry = 0;
2314     int i;
2315     int is_zero = 1;
2316 
2317     for (i = 1; i <= 31; i++) {
2318         uint8_t digit = bcd_get_digit(a, i, invalid) +
2319                         bcd_get_digit(b, i, invalid) + carry;
2320         is_zero &= (digit == 0);
2321         if (digit > 9) {
2322             carry = 1;
2323             digit -= 10;
2324         } else {
2325             carry = 0;
2326         }
2327 
2328         bcd_put_digit(t, digit, i);
2329     }
2330 
2331     *overflow = carry;
2332     return is_zero;
2333 }
2334 
2335 static void bcd_sub_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
2336                        int *overflow)
2337 {
2338     int carry = 0;
2339     int i;
2340 
2341     for (i = 1; i <= 31; i++) {
2342         uint8_t digit = bcd_get_digit(a, i, invalid) -
2343                         bcd_get_digit(b, i, invalid) + carry;
2344         if (digit & 0x80) {
2345             carry = -1;
2346             digit += 10;
2347         } else {
2348             carry = 0;
2349         }
2350 
2351         bcd_put_digit(t, digit, i);
2352     }
2353 
2354     *overflow = carry;
2355 }
2356 
2357 uint32_t helper_bcdadd(ppc_avr_t *r,  ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2358 {
2359 
2360     int sgna = bcd_get_sgn(a);
2361     int sgnb = bcd_get_sgn(b);
2362     int invalid = (sgna == 0) || (sgnb == 0);
2363     int overflow = 0;
2364     int zero = 0;
2365     uint32_t cr = 0;
2366     ppc_avr_t result = { .u64 = { 0, 0 } };
2367 
2368     if (!invalid) {
2369         if (sgna == sgnb) {
2370             result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgna, ps);
2371             zero = bcd_add_mag(&result, a, b, &invalid, &overflow);
2372             cr = (sgna > 0) ? CRF_GT : CRF_LT;
2373         } else {
2374             int magnitude = bcd_cmp_mag(a, b);
2375             if (magnitude > 0) {
2376                 result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgna, ps);
2377                 bcd_sub_mag(&result, a, b, &invalid, &overflow);
2378                 cr = (sgna > 0) ? CRF_GT : CRF_LT;
2379             } else if (magnitude < 0) {
2380                 result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(sgnb, ps);
2381                 bcd_sub_mag(&result, b, a, &invalid, &overflow);
2382                 cr = (sgnb > 0) ? CRF_GT : CRF_LT;
2383             } else {
2384                 result.VsrB(BCD_DIG_BYTE(0)) = bcd_preferred_sgn(0, ps);
2385                 cr = CRF_EQ;
2386             }
2387         }
2388     }
2389 
2390     if (unlikely(invalid)) {
2391         result.VsrD(0) = result.VsrD(1) = -1;
2392         cr = CRF_SO;
2393     } else if (overflow) {
2394         cr |= CRF_SO;
2395     } else if (zero) {
2396         cr |= CRF_EQ;
2397     }
2398 
2399     *r = result;
2400 
2401     return cr;
2402 }
2403 
2404 uint32_t helper_bcdsub(ppc_avr_t *r,  ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2405 {
2406     ppc_avr_t bcopy = *b;
2407     int sgnb = bcd_get_sgn(b);
2408     if (sgnb < 0) {
2409         bcd_put_digit(&bcopy, BCD_PLUS_PREF_1, 0);
2410     } else if (sgnb > 0) {
2411         bcd_put_digit(&bcopy, BCD_NEG_PREF, 0);
2412     }
2413     /* else invalid ... defer to bcdadd code for proper handling */
2414 
2415     return helper_bcdadd(r, a, &bcopy, ps);
2416 }
2417 
2418 uint32_t helper_bcdcfn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2419 {
2420     int i;
2421     int cr = 0;
2422     uint16_t national = 0;
2423     uint16_t sgnb = get_national_digit(b, 0);
2424     ppc_avr_t ret = { .u64 = { 0, 0 } };
2425     int invalid = (sgnb != NATIONAL_PLUS && sgnb != NATIONAL_NEG);
2426 
2427     for (i = 1; i < 8; i++) {
2428         national = get_national_digit(b, i);
2429         if (unlikely(national < 0x30 || national > 0x39)) {
2430             invalid = 1;
2431             break;
2432         }
2433 
2434         bcd_put_digit(&ret, national & 0xf, i);
2435     }
2436 
2437     if (sgnb == NATIONAL_PLUS) {
2438         bcd_put_digit(&ret, (ps == 0) ? BCD_PLUS_PREF_1 : BCD_PLUS_PREF_2, 0);
2439     } else {
2440         bcd_put_digit(&ret, BCD_NEG_PREF, 0);
2441     }
2442 
2443     cr = bcd_cmp_zero(&ret);
2444 
2445     if (unlikely(invalid)) {
2446         cr = CRF_SO;
2447     }
2448 
2449     *r = ret;
2450 
2451     return cr;
2452 }
2453 
2454 uint32_t helper_bcdctn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2455 {
2456     int i;
2457     int cr = 0;
2458     int sgnb = bcd_get_sgn(b);
2459     int invalid = (sgnb == 0);
2460     ppc_avr_t ret = { .u64 = { 0, 0 } };
2461 
2462     int ox_flag = (b->VsrD(0) != 0) || ((b->VsrD(1) >> 32) != 0);
2463 
2464     for (i = 1; i < 8; i++) {
2465         set_national_digit(&ret, 0x30 + bcd_get_digit(b, i, &invalid), i);
2466 
2467         if (unlikely(invalid)) {
2468             break;
2469         }
2470     }
2471     set_national_digit(&ret, (sgnb == -1) ? NATIONAL_NEG : NATIONAL_PLUS, 0);
2472 
2473     cr = bcd_cmp_zero(b);
2474 
2475     if (ox_flag) {
2476         cr |= CRF_SO;
2477     }
2478 
2479     if (unlikely(invalid)) {
2480         cr = CRF_SO;
2481     }
2482 
2483     *r = ret;
2484 
2485     return cr;
2486 }
2487 
2488 uint32_t helper_bcdcfz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2489 {
2490     int i;
2491     int cr = 0;
2492     int invalid = 0;
2493     int zone_digit = 0;
2494     int zone_lead = ps ? 0xF : 0x3;
2495     int digit = 0;
2496     ppc_avr_t ret = { .u64 = { 0, 0 } };
2497     int sgnb = b->VsrB(BCD_DIG_BYTE(0)) >> 4;
2498 
2499     if (unlikely((sgnb < 0xA) && ps)) {
2500         invalid = 1;
2501     }
2502 
2503     for (i = 0; i < 16; i++) {
2504         zone_digit = i ? b->VsrB(BCD_DIG_BYTE(i * 2)) >> 4 : zone_lead;
2505         digit = b->VsrB(BCD_DIG_BYTE(i * 2)) & 0xF;
2506         if (unlikely(zone_digit != zone_lead || digit > 0x9)) {
2507             invalid = 1;
2508             break;
2509         }
2510 
2511         bcd_put_digit(&ret, digit, i + 1);
2512     }
2513 
2514     if ((ps && (sgnb == 0xB || sgnb == 0xD)) ||
2515             (!ps && (sgnb & 0x4))) {
2516         bcd_put_digit(&ret, BCD_NEG_PREF, 0);
2517     } else {
2518         bcd_put_digit(&ret, BCD_PLUS_PREF_1, 0);
2519     }
2520 
2521     cr = bcd_cmp_zero(&ret);
2522 
2523     if (unlikely(invalid)) {
2524         cr = CRF_SO;
2525     }
2526 
2527     *r = ret;
2528 
2529     return cr;
2530 }
2531 
2532 uint32_t helper_bcdctz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2533 {
2534     int i;
2535     int cr = 0;
2536     uint8_t digit = 0;
2537     int sgnb = bcd_get_sgn(b);
2538     int zone_lead = (ps) ? 0xF0 : 0x30;
2539     int invalid = (sgnb == 0);
2540     ppc_avr_t ret = { .u64 = { 0, 0 } };
2541 
2542     int ox_flag = ((b->VsrD(0) >> 4) != 0);
2543 
2544     for (i = 0; i < 16; i++) {
2545         digit = bcd_get_digit(b, i + 1, &invalid);
2546 
2547         if (unlikely(invalid)) {
2548             break;
2549         }
2550 
2551         ret.VsrB(BCD_DIG_BYTE(i * 2)) = zone_lead + digit;
2552     }
2553 
2554     if (ps) {
2555         bcd_put_digit(&ret, (sgnb == 1) ? 0xC : 0xD, 1);
2556     } else {
2557         bcd_put_digit(&ret, (sgnb == 1) ? 0x3 : 0x7, 1);
2558     }
2559 
2560     cr = bcd_cmp_zero(b);
2561 
2562     if (ox_flag) {
2563         cr |= CRF_SO;
2564     }
2565 
2566     if (unlikely(invalid)) {
2567         cr = CRF_SO;
2568     }
2569 
2570     *r = ret;
2571 
2572     return cr;
2573 }
2574 
2575 /**
2576  * Compare 2 128-bit unsigned integers, passed in as unsigned 64-bit pairs
2577  *
2578  * Returns:
2579  * > 0 if ahi|alo > bhi|blo,
2580  * 0 if ahi|alo == bhi|blo,
2581  * < 0 if ahi|alo < bhi|blo
2582  */
2583 static inline int ucmp128(uint64_t alo, uint64_t ahi,
2584                           uint64_t blo, uint64_t bhi)
2585 {
2586     return (ahi == bhi) ?
2587         (alo > blo ? 1 : (alo == blo ? 0 : -1)) :
2588         (ahi > bhi ? 1 : -1);
2589 }
2590 
2591 uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2592 {
2593     int i;
2594     int cr;
2595     uint64_t lo_value;
2596     uint64_t hi_value;
2597     uint64_t rem;
2598     ppc_avr_t ret = { .u64 = { 0, 0 } };
2599 
2600     if (b->VsrSD(0) < 0) {
2601         lo_value = -b->VsrSD(1);
2602         hi_value = ~b->VsrD(0) + !lo_value;
2603         bcd_put_digit(&ret, 0xD, 0);
2604 
2605         cr = CRF_LT;
2606     } else {
2607         lo_value = b->VsrD(1);
2608         hi_value = b->VsrD(0);
2609         bcd_put_digit(&ret, bcd_preferred_sgn(0, ps), 0);
2610 
2611         if (hi_value == 0 && lo_value == 0) {
2612             cr = CRF_EQ;
2613         } else {
2614             cr = CRF_GT;
2615         }
2616     }
2617 
2618     /*
2619      * Check src limits: abs(src) <= 10^31 - 1
2620      *
2621      * 10^31 - 1 = 0x0000007e37be2022 c0914b267fffffff
2622      */
2623     if (ucmp128(lo_value, hi_value,
2624                 0xc0914b267fffffffULL, 0x7e37be2022ULL) > 0) {
2625         cr |= CRF_SO;
2626 
2627         /*
2628          * According to the ISA, if src wouldn't fit in the destination
2629          * register, the result is undefined.
2630          * In that case, we leave r unchanged.
2631          */
2632     } else {
2633         rem = divu128(&lo_value, &hi_value, 1000000000000000ULL);
2634 
2635         for (i = 1; i < 16; rem /= 10, i++) {
2636             bcd_put_digit(&ret, rem % 10, i);
2637         }
2638 
2639         for (; i < 32; lo_value /= 10, i++) {
2640             bcd_put_digit(&ret, lo_value % 10, i);
2641         }
2642 
2643         *r = ret;
2644     }
2645 
2646     return cr;
2647 }
2648 
2649 uint32_t helper_bcdctsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2650 {
2651     uint8_t i;
2652     int cr;
2653     uint64_t carry;
2654     uint64_t unused;
2655     uint64_t lo_value;
2656     uint64_t hi_value = 0;
2657     int sgnb = bcd_get_sgn(b);
2658     int invalid = (sgnb == 0);
2659 
2660     lo_value = bcd_get_digit(b, 31, &invalid);
2661     for (i = 30; i > 0; i--) {
2662         mulu64(&lo_value, &carry, lo_value, 10ULL);
2663         mulu64(&hi_value, &unused, hi_value, 10ULL);
2664         lo_value += bcd_get_digit(b, i, &invalid);
2665         hi_value += carry;
2666 
2667         if (unlikely(invalid)) {
2668             break;
2669         }
2670     }
2671 
2672     if (sgnb == -1) {
2673         r->VsrSD(1) = -lo_value;
2674         r->VsrSD(0) = ~hi_value + !r->VsrSD(1);
2675     } else {
2676         r->VsrSD(1) = lo_value;
2677         r->VsrSD(0) = hi_value;
2678     }
2679 
2680     cr = bcd_cmp_zero(b);
2681 
2682     if (unlikely(invalid)) {
2683         cr = CRF_SO;
2684     }
2685 
2686     return cr;
2687 }
2688 
2689 uint32_t helper_bcdcpsgn(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2690 {
2691     int i;
2692     int invalid = 0;
2693 
2694     if (bcd_get_sgn(a) == 0 || bcd_get_sgn(b) == 0) {
2695         return CRF_SO;
2696     }
2697 
2698     *r = *a;
2699     bcd_put_digit(r, b->VsrB(BCD_DIG_BYTE(0)) & 0xF, 0);
2700 
2701     for (i = 1; i < 32; i++) {
2702         bcd_get_digit(a, i, &invalid);
2703         bcd_get_digit(b, i, &invalid);
2704         if (unlikely(invalid)) {
2705             return CRF_SO;
2706         }
2707     }
2708 
2709     return bcd_cmp_zero(r);
2710 }
2711 
2712 uint32_t helper_bcdsetsgn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
2713 {
2714     int sgnb = bcd_get_sgn(b);
2715 
2716     *r = *b;
2717     bcd_put_digit(r, bcd_preferred_sgn(sgnb, ps), 0);
2718 
2719     if (bcd_is_valid(b) == false) {
2720         return CRF_SO;
2721     }
2722 
2723     return bcd_cmp_zero(r);
2724 }
2725 
2726 uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2727 {
2728     int cr;
2729     int i = a->VsrSB(7);
2730     bool ox_flag = false;
2731     int sgnb = bcd_get_sgn(b);
2732     ppc_avr_t ret = *b;
2733     ret.VsrD(1) &= ~0xf;
2734 
2735     if (bcd_is_valid(b) == false) {
2736         return CRF_SO;
2737     }
2738 
2739     if (unlikely(i > 31)) {
2740         i = 31;
2741     } else if (unlikely(i < -31)) {
2742         i = -31;
2743     }
2744 
2745     if (i > 0) {
2746         ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
2747     } else {
2748         urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
2749     }
2750     bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
2751 
2752     *r = ret;
2753 
2754     cr = bcd_cmp_zero(r);
2755     if (ox_flag) {
2756         cr |= CRF_SO;
2757     }
2758 
2759     return cr;
2760 }
2761 
2762 uint32_t helper_bcdus(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2763 {
2764     int cr;
2765     int i;
2766     int invalid = 0;
2767     bool ox_flag = false;
2768     ppc_avr_t ret = *b;
2769 
2770     for (i = 0; i < 32; i++) {
2771         bcd_get_digit(b, i, &invalid);
2772 
2773         if (unlikely(invalid)) {
2774             return CRF_SO;
2775         }
2776     }
2777 
2778     i = a->VsrSB(7);
2779     if (i >= 32) {
2780         ox_flag = true;
2781         ret.VsrD(1) = ret.VsrD(0) = 0;
2782     } else if (i <= -32) {
2783         ret.VsrD(1) = ret.VsrD(0) = 0;
2784     } else if (i > 0) {
2785         ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
2786     } else {
2787         urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
2788     }
2789     *r = ret;
2790 
2791     cr = bcd_cmp_zero(r);
2792     if (ox_flag) {
2793         cr |= CRF_SO;
2794     }
2795 
2796     return cr;
2797 }
2798 
2799 uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2800 {
2801     int cr;
2802     int unused = 0;
2803     int invalid = 0;
2804     bool ox_flag = false;
2805     int sgnb = bcd_get_sgn(b);
2806     ppc_avr_t ret = *b;
2807     ret.VsrD(1) &= ~0xf;
2808 
2809     int i = a->VsrSB(7);
2810     ppc_avr_t bcd_one;
2811 
2812     bcd_one.VsrD(0) = 0;
2813     bcd_one.VsrD(1) = 0x10;
2814 
2815     if (bcd_is_valid(b) == false) {
2816         return CRF_SO;
2817     }
2818 
2819     if (unlikely(i > 31)) {
2820         i = 31;
2821     } else if (unlikely(i < -31)) {
2822         i = -31;
2823     }
2824 
2825     if (i > 0) {
2826         ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
2827     } else {
2828         urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
2829 
2830         if (bcd_get_digit(&ret, 0, &invalid) >= 5) {
2831             bcd_add_mag(&ret, &ret, &bcd_one, &invalid, &unused);
2832         }
2833     }
2834     bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
2835 
2836     cr = bcd_cmp_zero(&ret);
2837     if (ox_flag) {
2838         cr |= CRF_SO;
2839     }
2840     *r = ret;
2841 
2842     return cr;
2843 }
2844 
2845 uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2846 {
2847     uint64_t mask;
2848     uint32_t ox_flag = 0;
2849     int i = a->VsrSH(3) + 1;
2850     ppc_avr_t ret = *b;
2851 
2852     if (bcd_is_valid(b) == false) {
2853         return CRF_SO;
2854     }
2855 
2856     if (i > 16 && i < 32) {
2857         mask = (uint64_t)-1 >> (128 - i * 4);
2858         if (ret.VsrD(0) & ~mask) {
2859             ox_flag = CRF_SO;
2860         }
2861 
2862         ret.VsrD(0) &= mask;
2863     } else if (i >= 0 && i <= 16) {
2864         mask = (uint64_t)-1 >> (64 - i * 4);
2865         if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) {
2866             ox_flag = CRF_SO;
2867         }
2868 
2869         ret.VsrD(1) &= mask;
2870         ret.VsrD(0) = 0;
2871     }
2872     bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0);
2873     *r = ret;
2874 
2875     return bcd_cmp_zero(&ret) | ox_flag;
2876 }
2877 
2878 uint32_t helper_bcdutrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
2879 {
2880     int i;
2881     uint64_t mask;
2882     uint32_t ox_flag = 0;
2883     int invalid = 0;
2884     ppc_avr_t ret = *b;
2885 
2886     for (i = 0; i < 32; i++) {
2887         bcd_get_digit(b, i, &invalid);
2888 
2889         if (unlikely(invalid)) {
2890             return CRF_SO;
2891         }
2892     }
2893 
2894     i = a->VsrSH(3);
2895     if (i > 16 && i < 33) {
2896         mask = (uint64_t)-1 >> (128 - i * 4);
2897         if (ret.VsrD(0) & ~mask) {
2898             ox_flag = CRF_SO;
2899         }
2900 
2901         ret.VsrD(0) &= mask;
2902     } else if (i > 0 && i <= 16) {
2903         mask = (uint64_t)-1 >> (64 - i * 4);
2904         if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) {
2905             ox_flag = CRF_SO;
2906         }
2907 
2908         ret.VsrD(1) &= mask;
2909         ret.VsrD(0) = 0;
2910     } else if (i == 0) {
2911         if (ret.VsrD(0) || ret.VsrD(1)) {
2912             ox_flag = CRF_SO;
2913         }
2914         ret.VsrD(0) = ret.VsrD(1) = 0;
2915     }
2916 
2917     *r = ret;
2918     if (r->VsrD(0) == 0 && r->VsrD(1) == 0) {
2919         return ox_flag | CRF_EQ;
2920     }
2921 
2922     return ox_flag | CRF_GT;
2923 }
2924 
2925 void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
2926 {
2927     int i;
2928     VECTOR_FOR_INORDER_I(i, u8) {
2929         r->u8[i] = AES_sbox[a->u8[i]];
2930     }
2931 }
2932 
2933 void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2934 {
2935     AESState *ad = (AESState *)r;
2936     AESState *st = (AESState *)a;
2937     AESState *rk = (AESState *)b;
2938 
2939     aesenc_SB_SR_MC_AK(ad, st, rk, true);
2940 }
2941 
2942 void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2943 {
2944     aesenc_SB_SR_AK((AESState *)r, (AESState *)a, (AESState *)b, true);
2945 }
2946 
2947 void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2948 {
2949     AESState *ad = (AESState *)r;
2950     AESState *st = (AESState *)a;
2951     AESState *rk = (AESState *)b;
2952 
2953     aesdec_ISB_ISR_AK_IMC(ad, st, rk, true);
2954 }
2955 
2956 void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2957 {
2958     aesdec_ISB_ISR_AK((AESState *)r, (AESState *)a, (AESState *)b, true);
2959 }
2960 
2961 void helper_vshasigmaw(ppc_avr_t *r,  ppc_avr_t *a, uint32_t st_six)
2962 {
2963     int st = (st_six & 0x10) != 0;
2964     int six = st_six & 0xF;
2965     int i;
2966 
2967     for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2968         if (st == 0) {
2969             if ((six & (0x8 >> i)) == 0) {
2970                 r->VsrW(i) = ror32(a->VsrW(i), 7) ^
2971                              ror32(a->VsrW(i), 18) ^
2972                              (a->VsrW(i) >> 3);
2973             } else { /* six.bit[i] == 1 */
2974                 r->VsrW(i) = ror32(a->VsrW(i), 17) ^
2975                              ror32(a->VsrW(i), 19) ^
2976                              (a->VsrW(i) >> 10);
2977             }
2978         } else { /* st == 1 */
2979             if ((six & (0x8 >> i)) == 0) {
2980                 r->VsrW(i) = ror32(a->VsrW(i), 2) ^
2981                              ror32(a->VsrW(i), 13) ^
2982                              ror32(a->VsrW(i), 22);
2983             } else { /* six.bit[i] == 1 */
2984                 r->VsrW(i) = ror32(a->VsrW(i), 6) ^
2985                              ror32(a->VsrW(i), 11) ^
2986                              ror32(a->VsrW(i), 25);
2987             }
2988         }
2989     }
2990 }
2991 
2992 void helper_vshasigmad(ppc_avr_t *r,  ppc_avr_t *a, uint32_t st_six)
2993 {
2994     int st = (st_six & 0x10) != 0;
2995     int six = st_six & 0xF;
2996     int i;
2997 
2998     for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
2999         if (st == 0) {
3000             if ((six & (0x8 >> (2 * i))) == 0) {
3001                 r->VsrD(i) = ror64(a->VsrD(i), 1) ^
3002                              ror64(a->VsrD(i), 8) ^
3003                              (a->VsrD(i) >> 7);
3004             } else { /* six.bit[2*i] == 1 */
3005                 r->VsrD(i) = ror64(a->VsrD(i), 19) ^
3006                              ror64(a->VsrD(i), 61) ^
3007                              (a->VsrD(i) >> 6);
3008             }
3009         } else { /* st == 1 */
3010             if ((six & (0x8 >> (2 * i))) == 0) {
3011                 r->VsrD(i) = ror64(a->VsrD(i), 28) ^
3012                              ror64(a->VsrD(i), 34) ^
3013                              ror64(a->VsrD(i), 39);
3014             } else { /* six.bit[2*i] == 1 */
3015                 r->VsrD(i) = ror64(a->VsrD(i), 14) ^
3016                              ror64(a->VsrD(i), 18) ^
3017                              ror64(a->VsrD(i), 41);
3018             }
3019         }
3020     }
3021 }
3022 
3023 void helper_vpermxor(ppc_avr_t *r,  ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
3024 {
3025     ppc_avr_t result;
3026     int i;
3027 
3028     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
3029         int indexA = c->VsrB(i) >> 4;
3030         int indexB = c->VsrB(i) & 0xF;
3031 
3032         result.VsrB(i) = a->VsrB(indexA) ^ b->VsrB(indexB);
3033     }
3034     *r = result;
3035 }
3036 
3037 #undef VECTOR_FOR_INORDER_I
3038 
3039 /*****************************************************************************/
3040 /* SPE extension helpers */
3041 /* Use a table to make this quicker */
3042 static const uint8_t hbrev[16] = {
3043     0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
3044     0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
3045 };
3046 
3047 static inline uint8_t byte_reverse(uint8_t val)
3048 {
3049     return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
3050 }
3051 
3052 static inline uint32_t word_reverse(uint32_t val)
3053 {
3054     return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
3055         (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
3056 }
3057 
3058 #define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
3059 target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
3060 {
3061     uint32_t a, b, d, mask;
3062 
3063     mask = UINT32_MAX >> (32 - MASKBITS);
3064     a = arg1 & mask;
3065     b = arg2 & mask;
3066     d = word_reverse(1 + word_reverse(a | ~b));
3067     return (arg1 & ~mask) | (d & b);
3068 }
3069 
3070 uint32_t helper_cntlsw32(uint32_t val)
3071 {
3072     if (val & 0x80000000) {
3073         return clz32(~val);
3074     } else {
3075         return clz32(val);
3076     }
3077 }
3078 
3079 uint32_t helper_cntlzw32(uint32_t val)
3080 {
3081     return clz32(val);
3082 }
3083 
3084 /* 440 specific */
3085 target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high,
3086                           target_ulong low, uint32_t update_Rc)
3087 {
3088     target_ulong mask;
3089     int i;
3090 
3091     i = 1;
3092     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
3093         if ((high & mask) == 0) {
3094             if (update_Rc) {
3095                 env->crf[0] = 0x4;
3096             }
3097             goto done;
3098         }
3099         i++;
3100     }
3101     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
3102         if ((low & mask) == 0) {
3103             if (update_Rc) {
3104                 env->crf[0] = 0x8;
3105             }
3106             goto done;
3107         }
3108         i++;
3109     }
3110     i = 8;
3111     if (update_Rc) {
3112         env->crf[0] = 0x2;
3113     }
3114  done:
3115     env->xer = (env->xer & ~0x7F) | i;
3116     if (update_Rc) {
3117         env->crf[0] |= xer_so;
3118     }
3119     return i;
3120 }
3121