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