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