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