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