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