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