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