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