]> Git Repo - qemu.git/blame - target-ppc/int_helper.c
target-ppc: Altivec 2.07: Vector Gather Bits by Bytes
[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 */
19#include "cpu.h"
1de7afc9 20#include "qemu/host-utils.h"
64654ded
BS
21#include "helper.h"
22
23#include "helper_regs.h"
24/*****************************************************************************/
25/* Fixed point operations helpers */
26#if defined(TARGET_PPC64)
27
d15f74fb 28uint64_t helper_mulldo(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
64654ded
BS
29{
30 int64_t th;
31 uint64_t tl;
32
33 muls64(&tl, (uint64_t *)&th, arg1, arg2);
34 /* If th != 0 && th != -1, then we had an overflow */
35 if (likely((uint64_t)(th + 1) <= 1)) {
da91a00f 36 env->ov = 0;
64654ded 37 } else {
da91a00f 38 env->so = env->ov = 1;
64654ded
BS
39 }
40 return (int64_t)tl;
41}
42#endif
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) {
65 if (unlikely(overflow)) {
66 env->so = env->ov = 1;
67 } else {
68 env->ov = 0;
69 }
70 }
71
72 return (target_ulong)rt;
73}
74
a98eb9e9
TM
75target_ulong helper_divwe(CPUPPCState *env, target_ulong ra, target_ulong rb,
76 uint32_t oe)
77{
78 int64_t rt = 0;
79 int overflow = 0;
80
81 int64_t dividend = (int64_t)ra << 32;
82 int64_t divisor = (int64_t)((int32_t)rb);
83
84 if (unlikely((divisor == 0) ||
85 ((divisor == -1ull) && (dividend == INT64_MIN)))) {
86 overflow = 1;
87 } else {
88 rt = dividend / divisor;
89 overflow = rt != (int32_t)rt;
90 }
91
92 if (unlikely(overflow)) {
93 rt = 0; /* Undefined */
94 }
95
96 if (oe) {
97 if (unlikely(overflow)) {
98 env->so = env->ov = 1;
99 } else {
100 env->ov = 0;
101 }
102 }
103
104 return (target_ulong)rt;
105}
106
98d1eb27
TM
107#if defined(TARGET_PPC64)
108
109uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe)
110{
111 uint64_t rt = 0;
112 int overflow = 0;
113
114 overflow = divu128(&rt, &ra, rb);
115
116 if (unlikely(overflow)) {
117 rt = 0; /* Undefined */
118 }
119
120 if (oe) {
121 if (unlikely(overflow)) {
122 env->so = env->ov = 1;
123 } else {
124 env->ov = 0;
125 }
126 }
127
128 return rt;
129}
130
e44259b6
TM
131uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
132{
133 int64_t rt = 0;
134 int64_t ra = (int64_t)rau;
135 int64_t rb = (int64_t)rbu;
136 int overflow = divs128(&rt, &ra, rb);
137
138 if (unlikely(overflow)) {
139 rt = 0; /* Undefined */
140 }
141
142 if (oe) {
143
144 if (unlikely(overflow)) {
145 env->so = env->ov = 1;
146 } else {
147 env->ov = 0;
148 }
149 }
150
151 return rt;
152}
153
98d1eb27
TM
154#endif
155
156
64654ded
BS
157target_ulong helper_cntlzw(target_ulong t)
158{
159 return clz32(t);
160}
161
162#if defined(TARGET_PPC64)
163target_ulong helper_cntlzd(target_ulong t)
164{
165 return clz64(t);
166}
167#endif
168
86ba37ed
TM
169#if defined(TARGET_PPC64)
170
171uint64_t helper_bpermd(uint64_t rs, uint64_t rb)
172{
173 int i;
174 uint64_t ra = 0;
175
176 for (i = 0; i < 8; i++) {
177 int index = (rs >> (i*8)) & 0xFF;
178 if (index < 64) {
179 if (rb & (1ull << (63-index))) {
180 ra |= 1 << i;
181 }
182 }
183 }
184 return ra;
185}
186
187#endif
188
fcfda20f
AJ
189target_ulong helper_cmpb(target_ulong rs, target_ulong rb)
190{
191 target_ulong mask = 0xff;
192 target_ulong ra = 0;
193 int i;
194
195 for (i = 0; i < sizeof(target_ulong); i++) {
196 if ((rs & mask) == (rb & mask)) {
197 ra |= mask;
198 }
199 mask <<= 8;
200 }
201 return ra;
202}
203
64654ded 204/* shift right arithmetic helper */
d15f74fb
BS
205target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
206 target_ulong shift)
64654ded
BS
207{
208 int32_t ret;
209
210 if (likely(!(shift & 0x20))) {
211 if (likely((uint32_t)shift != 0)) {
212 shift &= 0x1f;
213 ret = (int32_t)value >> shift;
214 if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
da91a00f 215 env->ca = 0;
64654ded 216 } else {
da91a00f 217 env->ca = 1;
64654ded
BS
218 }
219 } else {
220 ret = (int32_t)value;
da91a00f 221 env->ca = 0;
64654ded
BS
222 }
223 } else {
224 ret = (int32_t)value >> 31;
da91a00f 225 env->ca = (ret != 0);
64654ded
BS
226 }
227 return (target_long)ret;
228}
229
230#if defined(TARGET_PPC64)
d15f74fb
BS
231target_ulong helper_srad(CPUPPCState *env, target_ulong value,
232 target_ulong shift)
64654ded
BS
233{
234 int64_t ret;
235
236 if (likely(!(shift & 0x40))) {
237 if (likely((uint64_t)shift != 0)) {
238 shift &= 0x3f;
239 ret = (int64_t)value >> shift;
240 if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
da91a00f 241 env->ca = 0;
64654ded 242 } else {
da91a00f 243 env->ca = 1;
64654ded
BS
244 }
245 } else {
246 ret = (int64_t)value;
da91a00f 247 env->ca = 0;
64654ded
BS
248 }
249 } else {
250 ret = (int64_t)value >> 63;
da91a00f 251 env->ca = (ret != 0);
64654ded
BS
252 }
253 return ret;
254}
255#endif
256
257#if defined(TARGET_PPC64)
258target_ulong helper_popcntb(target_ulong val)
259{
260 val = (val & 0x5555555555555555ULL) + ((val >> 1) &
261 0x5555555555555555ULL);
262 val = (val & 0x3333333333333333ULL) + ((val >> 2) &
263 0x3333333333333333ULL);
264 val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) &
265 0x0f0f0f0f0f0f0f0fULL);
266 return val;
267}
268
269target_ulong helper_popcntw(target_ulong val)
270{
271 val = (val & 0x5555555555555555ULL) + ((val >> 1) &
272 0x5555555555555555ULL);
273 val = (val & 0x3333333333333333ULL) + ((val >> 2) &
274 0x3333333333333333ULL);
275 val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) &
276 0x0f0f0f0f0f0f0f0fULL);
277 val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) &
278 0x00ff00ff00ff00ffULL);
279 val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
280 0x0000ffff0000ffffULL);
281 return val;
282}
283
284target_ulong helper_popcntd(target_ulong val)
285{
286 return ctpop64(val);
287}
288#else
289target_ulong helper_popcntb(target_ulong val)
290{
291 val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
292 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
293 val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
294 return val;
295}
296
297target_ulong helper_popcntw(target_ulong val)
298{
299 val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
300 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
301 val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
302 val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff);
303 val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
304 return val;
305}
306#endif
307
308/*****************************************************************************/
309/* PowerPC 601 specific instructions (POWER bridge) */
d15f74fb 310target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
64654ded
BS
311{
312 uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
313
314 if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
315 (int32_t)arg2 == 0) {
316 env->spr[SPR_MQ] = 0;
317 return INT32_MIN;
318 } else {
319 env->spr[SPR_MQ] = tmp % arg2;
320 return tmp / (int32_t)arg2;
321 }
322}
323
d15f74fb
BS
324target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
325 target_ulong arg2)
64654ded
BS
326{
327 uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
328
329 if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
330 (int32_t)arg2 == 0) {
da91a00f 331 env->so = env->ov = 1;
64654ded
BS
332 env->spr[SPR_MQ] = 0;
333 return INT32_MIN;
334 } else {
335 env->spr[SPR_MQ] = tmp % arg2;
336 tmp /= (int32_t)arg2;
337 if ((int32_t)tmp != tmp) {
da91a00f 338 env->so = env->ov = 1;
64654ded 339 } else {
da91a00f 340 env->ov = 0;
64654ded
BS
341 }
342 return tmp;
343 }
344}
345
d15f74fb
BS
346target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
347 target_ulong arg2)
64654ded
BS
348{
349 if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
350 (int32_t)arg2 == 0) {
351 env->spr[SPR_MQ] = 0;
352 return INT32_MIN;
353 } else {
354 env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
355 return (int32_t)arg1 / (int32_t)arg2;
356 }
357}
358
d15f74fb
BS
359target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
360 target_ulong arg2)
64654ded
BS
361{
362 if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
363 (int32_t)arg2 == 0) {
da91a00f 364 env->so = env->ov = 1;
64654ded
BS
365 env->spr[SPR_MQ] = 0;
366 return INT32_MIN;
367 } else {
da91a00f 368 env->ov = 0;
64654ded
BS
369 env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
370 return (int32_t)arg1 / (int32_t)arg2;
371 }
372}
373
374/*****************************************************************************/
375/* 602 specific instructions */
376/* mfrom is the most crazy instruction ever seen, imho ! */
377/* Real implementation uses a ROM table. Do the same */
378/* Extremely decomposed:
379 * -arg / 256
380 * return 256 * log10(10 + 1.0) + 0.5
381 */
382#if !defined(CONFIG_USER_ONLY)
383target_ulong helper_602_mfrom(target_ulong arg)
384{
385 if (likely(arg < 602)) {
386#include "mfrom_table.c"
387 return mfrom_ROM_table[arg];
388 } else {
389 return 0;
390 }
391}
392#endif
393
394/*****************************************************************************/
395/* Altivec extension helpers */
396#if defined(HOST_WORDS_BIGENDIAN)
397#define HI_IDX 0
398#define LO_IDX 1
399#else
400#define HI_IDX 1
401#define LO_IDX 0
402#endif
403
404#if defined(HOST_WORDS_BIGENDIAN)
405#define VECTOR_FOR_INORDER_I(index, element) \
406 for (index = 0; index < ARRAY_SIZE(r->element); index++)
407#else
408#define VECTOR_FOR_INORDER_I(index, element) \
409 for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
410#endif
411
64654ded
BS
412/* Saturating arithmetic helpers. */
413#define SATCVT(from, to, from_type, to_type, min, max) \
414 static inline to_type cvt##from##to(from_type x, int *sat) \
415 { \
416 to_type r; \
417 \
418 if (x < (from_type)min) { \
419 r = min; \
420 *sat = 1; \
421 } else if (x > (from_type)max) { \
422 r = max; \
423 *sat = 1; \
424 } else { \
425 r = x; \
426 } \
427 return r; \
428 }
429#define SATCVTU(from, to, from_type, to_type, min, max) \
430 static inline to_type cvt##from##to(from_type x, int *sat) \
431 { \
432 to_type r; \
433 \
434 if (x > (from_type)max) { \
435 r = max; \
436 *sat = 1; \
437 } else { \
438 r = x; \
439 } \
440 return r; \
441 }
442SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX)
443SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX)
444SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX)
445
446SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX)
447SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX)
448SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX)
449SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX)
450SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX)
451SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
452#undef SATCVT
453#undef SATCVTU
454
455void helper_lvsl(ppc_avr_t *r, target_ulong sh)
456{
457 int i, j = (sh & 0xf);
458
459 VECTOR_FOR_INORDER_I(i, u8) {
460 r->u8[i] = j++;
461 }
462}
463
464void helper_lvsr(ppc_avr_t *r, target_ulong sh)
465{
466 int i, j = 0x10 - (sh & 0xf);
467
468 VECTOR_FOR_INORDER_I(i, u8) {
469 r->u8[i] = j++;
470 }
471}
472
d15f74fb 473void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
64654ded
BS
474{
475#if defined(HOST_WORDS_BIGENDIAN)
476 env->vscr = r->u32[3];
477#else
478 env->vscr = r->u32[0];
479#endif
480 set_flush_to_zero(vscr_nj, &env->vec_status);
481}
482
483void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
484{
485 int i;
486
487 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
488 r->u32[i] = ~a->u32[i] < b->u32[i];
489 }
490}
491
492#define VARITH_DO(name, op, element) \
493 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
494 { \
495 int i; \
496 \
497 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
498 r->element[i] = a->element[i] op b->element[i]; \
499 } \
500 }
501#define VARITH(suffix, element) \
502 VARITH_DO(add##suffix, +, element) \
503 VARITH_DO(sub##suffix, -, element)
504VARITH(ubm, u8)
505VARITH(uhm, u16)
506VARITH(uwm, u32)
56eabc75 507VARITH(udm, u64)
953f0f58 508VARITH_DO(muluwm, *, u32)
64654ded
BS
509#undef VARITH_DO
510#undef VARITH
511
512#define VARITHFP(suffix, func) \
d15f74fb
BS
513 void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
514 ppc_avr_t *b) \
64654ded
BS
515 { \
516 int i; \
517 \
518 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
ef9bd150 519 r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
64654ded
BS
520 } \
521 }
522VARITHFP(addfp, float32_add)
523VARITHFP(subfp, float32_sub)
db1babb8
AJ
524VARITHFP(minfp, float32_min)
525VARITHFP(maxfp, float32_max)
64654ded
BS
526#undef VARITHFP
527
2f93c23f
AJ
528#define VARITHFPFMA(suffix, type) \
529 void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
530 ppc_avr_t *b, ppc_avr_t *c) \
531 { \
532 int i; \
533 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
534 r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i], \
535 type, &env->vec_status); \
536 } \
537 }
538VARITHFPFMA(maddfp, 0);
539VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
540#undef VARITHFPFMA
541
64654ded
BS
542#define VARITHSAT_CASE(type, op, cvt, element) \
543 { \
544 type result = (type)a->element[i] op (type)b->element[i]; \
545 r->element[i] = cvt(result, &sat); \
546 }
547
548#define VARITHSAT_DO(name, op, optype, cvt, element) \
d15f74fb
BS
549 void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
550 ppc_avr_t *b) \
64654ded
BS
551 { \
552 int sat = 0; \
553 int i; \
554 \
555 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
556 switch (sizeof(r->element[0])) { \
557 case 1: \
558 VARITHSAT_CASE(optype, op, cvt, element); \
559 break; \
560 case 2: \
561 VARITHSAT_CASE(optype, op, cvt, element); \
562 break; \
563 case 4: \
564 VARITHSAT_CASE(optype, op, cvt, element); \
565 break; \
566 } \
567 } \
568 if (sat) { \
569 env->vscr |= (1 << VSCR_SAT); \
570 } \
571 }
572#define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
573 VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element) \
574 VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
575#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt) \
576 VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element) \
577 VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
578VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
579VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
580VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
581VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
582VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
583VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
584#undef VARITHSAT_CASE
585#undef VARITHSAT_DO
586#undef VARITHSAT_SIGNED
587#undef VARITHSAT_UNSIGNED
588
589#define VAVG_DO(name, element, etype) \
590 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
591 { \
592 int i; \
593 \
594 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
595 etype x = (etype)a->element[i] + (etype)b->element[i] + 1; \
596 r->element[i] = x >> 1; \
597 } \
598 }
599
600#define VAVG(type, signed_element, signed_type, unsigned_element, \
601 unsigned_type) \
602 VAVG_DO(avgs##type, signed_element, signed_type) \
603 VAVG_DO(avgu##type, unsigned_element, unsigned_type)
604VAVG(b, s8, int16_t, u8, uint16_t)
605VAVG(h, s16, int32_t, u16, uint32_t)
606VAVG(w, s32, int64_t, u32, uint64_t)
607#undef VAVG_DO
608#undef VAVG
609
610#define VCF(suffix, cvt, element) \
d15f74fb
BS
611 void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r, \
612 ppc_avr_t *b, uint32_t uim) \
64654ded
BS
613 { \
614 int i; \
615 \
616 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
617 float32 t = cvt(b->element[i], &env->vec_status); \
618 r->f[i] = float32_scalbn(t, -uim, &env->vec_status); \
619 } \
620 }
621VCF(ux, uint32_to_float32, u32)
622VCF(sx, int32_to_float32, s32)
623#undef VCF
624
625#define VCMP_DO(suffix, compare, element, record) \
d15f74fb
BS
626 void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
627 ppc_avr_t *a, ppc_avr_t *b) \
64654ded 628 { \
6f3dab41
TM
629 uint64_t ones = (uint64_t)-1; \
630 uint64_t all = ones; \
631 uint64_t none = 0; \
64654ded
BS
632 int i; \
633 \
634 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
6f3dab41 635 uint64_t result = (a->element[i] compare b->element[i] ? \
64654ded
BS
636 ones : 0x0); \
637 switch (sizeof(a->element[0])) { \
6f3dab41
TM
638 case 8: \
639 r->u64[i] = result; \
640 break; \
64654ded
BS
641 case 4: \
642 r->u32[i] = result; \
643 break; \
644 case 2: \
645 r->u16[i] = result; \
646 break; \
647 case 1: \
648 r->u8[i] = result; \
649 break; \
650 } \
651 all &= result; \
652 none |= result; \
653 } \
654 if (record) { \
655 env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
656 } \
657 }
658#define VCMP(suffix, compare, element) \
659 VCMP_DO(suffix, compare, element, 0) \
660 VCMP_DO(suffix##_dot, compare, element, 1)
661VCMP(equb, ==, u8)
662VCMP(equh, ==, u16)
663VCMP(equw, ==, u32)
6f3dab41 664VCMP(equd, ==, u64)
64654ded
BS
665VCMP(gtub, >, u8)
666VCMP(gtuh, >, u16)
667VCMP(gtuw, >, u32)
6f3dab41 668VCMP(gtud, >, u64)
64654ded
BS
669VCMP(gtsb, >, s8)
670VCMP(gtsh, >, s16)
671VCMP(gtsw, >, s32)
6f3dab41 672VCMP(gtsd, >, s64)
64654ded
BS
673#undef VCMP_DO
674#undef VCMP
675
676#define VCMPFP_DO(suffix, compare, order, record) \
d15f74fb
BS
677 void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
678 ppc_avr_t *a, ppc_avr_t *b) \
64654ded
BS
679 { \
680 uint32_t ones = (uint32_t)-1; \
681 uint32_t all = ones; \
682 uint32_t none = 0; \
683 int i; \
684 \
685 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
686 uint32_t result; \
687 int rel = float32_compare_quiet(a->f[i], b->f[i], \
688 &env->vec_status); \
689 if (rel == float_relation_unordered) { \
690 result = 0; \
691 } else if (rel compare order) { \
692 result = ones; \
693 } else { \
694 result = 0; \
695 } \
696 r->u32[i] = result; \
697 all &= result; \
698 none |= result; \
699 } \
700 if (record) { \
701 env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
702 } \
703 }
704#define VCMPFP(suffix, compare, order) \
705 VCMPFP_DO(suffix, compare, order, 0) \
706 VCMPFP_DO(suffix##_dot, compare, order, 1)
707VCMPFP(eqfp, ==, float_relation_equal)
708VCMPFP(gefp, !=, float_relation_less)
709VCMPFP(gtfp, ==, float_relation_greater)
710#undef VCMPFP_DO
711#undef VCMPFP
712
d15f74fb
BS
713static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r,
714 ppc_avr_t *a, ppc_avr_t *b, int record)
64654ded
BS
715{
716 int i;
717 int all_in = 0;
718
719 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
720 int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
721 if (le_rel == float_relation_unordered) {
722 r->u32[i] = 0xc0000000;
723 /* ALL_IN does not need to be updated here. */
724 } else {
725 float32 bneg = float32_chs(b->f[i]);
726 int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
727 int le = le_rel != float_relation_greater;
728 int ge = ge_rel != float_relation_less;
729
730 r->u32[i] = ((!le) << 31) | ((!ge) << 30);
731 all_in |= (!le | !ge);
732 }
733 }
734 if (record) {
735 env->crf[6] = (all_in == 0) << 1;
736 }
737}
738
d15f74fb 739void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded 740{
d15f74fb 741 vcmpbfp_internal(env, r, a, b, 0);
64654ded
BS
742}
743
d15f74fb
BS
744void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
745 ppc_avr_t *b)
64654ded 746{
d15f74fb 747 vcmpbfp_internal(env, r, a, b, 1);
64654ded
BS
748}
749
750#define VCT(suffix, satcvt, element) \
d15f74fb
BS
751 void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r, \
752 ppc_avr_t *b, uint32_t uim) \
64654ded
BS
753 { \
754 int i; \
755 int sat = 0; \
756 float_status s = env->vec_status; \
757 \
758 set_float_rounding_mode(float_round_to_zero, &s); \
759 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
760 if (float32_is_any_nan(b->f[i])) { \
761 r->element[i] = 0; \
762 } else { \
763 float64 t = float32_to_float64(b->f[i], &s); \
764 int64_t j; \
765 \
766 t = float64_scalbn(t, uim, &s); \
767 j = float64_to_int64(t, &s); \
768 r->element[i] = satcvt(j, &sat); \
769 } \
770 } \
771 if (sat) { \
772 env->vscr |= (1 << VSCR_SAT); \
773 } \
774 }
775VCT(uxs, cvtsduw, u32)
776VCT(sxs, cvtsdsw, s32)
777#undef VCT
778
d15f74fb
BS
779void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
780 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
781{
782 int sat = 0;
783 int i;
784
785 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
786 int32_t prod = a->s16[i] * b->s16[i];
787 int32_t t = (int32_t)c->s16[i] + (prod >> 15);
788
789 r->s16[i] = cvtswsh(t, &sat);
790 }
791
792 if (sat) {
793 env->vscr |= (1 << VSCR_SAT);
794 }
795}
796
d15f74fb
BS
797void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
798 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
799{
800 int sat = 0;
801 int i;
802
803 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
804 int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
805 int32_t t = (int32_t)c->s16[i] + (prod >> 15);
806 r->s16[i] = cvtswsh(t, &sat);
807 }
808
809 if (sat) {
810 env->vscr |= (1 << VSCR_SAT);
811 }
812}
813
814#define VMINMAX_DO(name, compare, element) \
815 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
816 { \
817 int i; \
818 \
819 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
820 if (a->element[i] compare b->element[i]) { \
821 r->element[i] = b->element[i]; \
822 } else { \
823 r->element[i] = a->element[i]; \
824 } \
825 } \
826 }
827#define VMINMAX(suffix, element) \
828 VMINMAX_DO(min##suffix, >, element) \
829 VMINMAX_DO(max##suffix, <, element)
830VMINMAX(sb, s8)
831VMINMAX(sh, s16)
832VMINMAX(sw, s32)
8203e31b 833VMINMAX(sd, s64)
64654ded
BS
834VMINMAX(ub, u8)
835VMINMAX(uh, u16)
836VMINMAX(uw, u32)
8203e31b 837VMINMAX(ud, u64)
64654ded
BS
838#undef VMINMAX_DO
839#undef VMINMAX
840
64654ded
BS
841void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
842{
843 int i;
844
845 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
846 int32_t prod = a->s16[i] * b->s16[i];
847 r->s16[i] = (int16_t) (prod + c->s16[i]);
848 }
849}
850
851#define VMRG_DO(name, element, highp) \
852 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
853 { \
854 ppc_avr_t result; \
855 int i; \
856 size_t n_elems = ARRAY_SIZE(r->element); \
857 \
858 for (i = 0; i < n_elems / 2; i++) { \
859 if (highp) { \
860 result.element[i*2+HI_IDX] = a->element[i]; \
861 result.element[i*2+LO_IDX] = b->element[i]; \
862 } else { \
863 result.element[n_elems - i * 2 - (1 + HI_IDX)] = \
864 b->element[n_elems - i - 1]; \
865 result.element[n_elems - i * 2 - (1 + LO_IDX)] = \
866 a->element[n_elems - i - 1]; \
867 } \
868 } \
869 *r = result; \
870 }
871#if defined(HOST_WORDS_BIGENDIAN)
872#define MRGHI 0
873#define MRGLO 1
874#else
875#define MRGHI 1
876#define MRGLO 0
877#endif
878#define VMRG(suffix, element) \
879 VMRG_DO(mrgl##suffix, element, MRGHI) \
880 VMRG_DO(mrgh##suffix, element, MRGLO)
881VMRG(b, u8)
882VMRG(h, u16)
883VMRG(w, u32)
884#undef VMRG_DO
885#undef VMRG
886#undef MRGHI
887#undef MRGLO
888
d15f74fb
BS
889void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
890 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
891{
892 int32_t prod[16];
893 int i;
894
895 for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
896 prod[i] = (int32_t)a->s8[i] * b->u8[i];
897 }
898
899 VECTOR_FOR_INORDER_I(i, s32) {
900 r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
901 prod[4 * i + 2] + prod[4 * i + 3];
902 }
903}
904
d15f74fb
BS
905void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
906 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
907{
908 int32_t prod[8];
909 int i;
910
911 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
912 prod[i] = a->s16[i] * b->s16[i];
913 }
914
915 VECTOR_FOR_INORDER_I(i, s32) {
916 r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
917 }
918}
919
d15f74fb
BS
920void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
921 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
922{
923 int32_t prod[8];
924 int i;
925 int sat = 0;
926
927 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
928 prod[i] = (int32_t)a->s16[i] * b->s16[i];
929 }
930
931 VECTOR_FOR_INORDER_I(i, s32) {
932 int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
933
934 r->u32[i] = cvtsdsw(t, &sat);
935 }
936
937 if (sat) {
938 env->vscr |= (1 << VSCR_SAT);
939 }
940}
941
d15f74fb
BS
942void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
943 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
944{
945 uint16_t prod[16];
946 int i;
947
948 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
949 prod[i] = a->u8[i] * b->u8[i];
950 }
951
952 VECTOR_FOR_INORDER_I(i, u32) {
953 r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
954 prod[4 * i + 2] + prod[4 * i + 3];
955 }
956}
957
d15f74fb
BS
958void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
959 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
960{
961 uint32_t prod[8];
962 int i;
963
964 for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
965 prod[i] = a->u16[i] * b->u16[i];
966 }
967
968 VECTOR_FOR_INORDER_I(i, u32) {
969 r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
970 }
971}
972
d15f74fb
BS
973void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
974 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
975{
976 uint32_t prod[8];
977 int i;
978 int sat = 0;
979
980 for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
981 prod[i] = a->u16[i] * b->u16[i];
982 }
983
984 VECTOR_FOR_INORDER_I(i, s32) {
985 uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
986
987 r->u32[i] = cvtuduw(t, &sat);
988 }
989
990 if (sat) {
991 env->vscr |= (1 << VSCR_SAT);
992 }
993}
994
aa9e930c 995#define VMUL_DO(name, mul_element, prod_element, cast, evenp) \
64654ded
BS
996 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
997 { \
998 int i; \
999 \
1000 VECTOR_FOR_INORDER_I(i, prod_element) { \
1001 if (evenp) { \
aa9e930c
TM
1002 r->prod_element[i] = \
1003 (cast)a->mul_element[i * 2 + HI_IDX] * \
1004 (cast)b->mul_element[i * 2 + HI_IDX]; \
64654ded 1005 } else { \
aa9e930c
TM
1006 r->prod_element[i] = \
1007 (cast)a->mul_element[i * 2 + LO_IDX] * \
1008 (cast)b->mul_element[i * 2 + LO_IDX]; \
64654ded
BS
1009 } \
1010 } \
1011 }
aa9e930c
TM
1012#define VMUL(suffix, mul_element, prod_element, cast) \
1013 VMUL_DO(mule##suffix, mul_element, prod_element, cast, 1) \
1014 VMUL_DO(mulo##suffix, mul_element, prod_element, cast, 0)
1015VMUL(sb, s8, s16, int16_t)
1016VMUL(sh, s16, s32, int32_t)
63be0936 1017VMUL(sw, s32, s64, int64_t)
aa9e930c
TM
1018VMUL(ub, u8, u16, uint16_t)
1019VMUL(uh, u16, u32, uint32_t)
63be0936 1020VMUL(uw, u32, u64, uint64_t)
64654ded
BS
1021#undef VMUL_DO
1022#undef VMUL
1023
d15f74fb
BS
1024void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1025 ppc_avr_t *c)
64654ded
BS
1026{
1027 ppc_avr_t result;
1028 int i;
1029
1030 VECTOR_FOR_INORDER_I(i, u8) {
1031 int s = c->u8[i] & 0x1f;
1032#if defined(HOST_WORDS_BIGENDIAN)
1033 int index = s & 0xf;
1034#else
1035 int index = 15 - (s & 0xf);
1036#endif
1037
1038 if (s & 0x10) {
1039 result.u8[i] = b->u8[index];
1040 } else {
1041 result.u8[i] = a->u8[index];
1042 }
1043 }
1044 *r = result;
1045}
1046
4d82038e
TM
1047#if defined(HOST_WORDS_BIGENDIAN)
1048#define VBPERMQ_INDEX(avr, i) ((avr)->u8[(i)])
1049#define VBPERMQ_DW(index) (((index) & 0x40) != 0)
1050#else
1051#define VBPERMQ_INDEX(avr, i) ((avr)->u8[15-(i)])
1052#define VBPERMQ_DW(index) (((index) & 0x40) == 0)
1053#endif
1054
1055void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1056{
1057 int i;
1058 uint64_t perm = 0;
1059
1060 VECTOR_FOR_INORDER_I(i, u8) {
1061 int index = VBPERMQ_INDEX(b, i);
1062
1063 if (index < 128) {
1064 uint64_t mask = (1ull << (63-(index & 0x3F)));
1065 if (a->u64[VBPERMQ_DW(index)] & mask) {
1066 perm |= (0x8000 >> i);
1067 }
1068 }
1069 }
1070
1071 r->u64[HI_IDX] = perm;
1072 r->u64[LO_IDX] = 0;
1073}
1074
1075#undef VBPERMQ_INDEX
1076#undef VBPERMQ_DW
1077
f1064f61
TM
1078uint64_t VGBBD_MASKS[256] = {
1079 0x0000000000000000ull, /* 00 */
1080 0x0000000000000080ull, /* 01 */
1081 0x0000000000008000ull, /* 02 */
1082 0x0000000000008080ull, /* 03 */
1083 0x0000000000800000ull, /* 04 */
1084 0x0000000000800080ull, /* 05 */
1085 0x0000000000808000ull, /* 06 */
1086 0x0000000000808080ull, /* 07 */
1087 0x0000000080000000ull, /* 08 */
1088 0x0000000080000080ull, /* 09 */
1089 0x0000000080008000ull, /* 0A */
1090 0x0000000080008080ull, /* 0B */
1091 0x0000000080800000ull, /* 0C */
1092 0x0000000080800080ull, /* 0D */
1093 0x0000000080808000ull, /* 0E */
1094 0x0000000080808080ull, /* 0F */
1095 0x0000008000000000ull, /* 10 */
1096 0x0000008000000080ull, /* 11 */
1097 0x0000008000008000ull, /* 12 */
1098 0x0000008000008080ull, /* 13 */
1099 0x0000008000800000ull, /* 14 */
1100 0x0000008000800080ull, /* 15 */
1101 0x0000008000808000ull, /* 16 */
1102 0x0000008000808080ull, /* 17 */
1103 0x0000008080000000ull, /* 18 */
1104 0x0000008080000080ull, /* 19 */
1105 0x0000008080008000ull, /* 1A */
1106 0x0000008080008080ull, /* 1B */
1107 0x0000008080800000ull, /* 1C */
1108 0x0000008080800080ull, /* 1D */
1109 0x0000008080808000ull, /* 1E */
1110 0x0000008080808080ull, /* 1F */
1111 0x0000800000000000ull, /* 20 */
1112 0x0000800000000080ull, /* 21 */
1113 0x0000800000008000ull, /* 22 */
1114 0x0000800000008080ull, /* 23 */
1115 0x0000800000800000ull, /* 24 */
1116 0x0000800000800080ull, /* 25 */
1117 0x0000800000808000ull, /* 26 */
1118 0x0000800000808080ull, /* 27 */
1119 0x0000800080000000ull, /* 28 */
1120 0x0000800080000080ull, /* 29 */
1121 0x0000800080008000ull, /* 2A */
1122 0x0000800080008080ull, /* 2B */
1123 0x0000800080800000ull, /* 2C */
1124 0x0000800080800080ull, /* 2D */
1125 0x0000800080808000ull, /* 2E */
1126 0x0000800080808080ull, /* 2F */
1127 0x0000808000000000ull, /* 30 */
1128 0x0000808000000080ull, /* 31 */
1129 0x0000808000008000ull, /* 32 */
1130 0x0000808000008080ull, /* 33 */
1131 0x0000808000800000ull, /* 34 */
1132 0x0000808000800080ull, /* 35 */
1133 0x0000808000808000ull, /* 36 */
1134 0x0000808000808080ull, /* 37 */
1135 0x0000808080000000ull, /* 38 */
1136 0x0000808080000080ull, /* 39 */
1137 0x0000808080008000ull, /* 3A */
1138 0x0000808080008080ull, /* 3B */
1139 0x0000808080800000ull, /* 3C */
1140 0x0000808080800080ull, /* 3D */
1141 0x0000808080808000ull, /* 3E */
1142 0x0000808080808080ull, /* 3F */
1143 0x0080000000000000ull, /* 40 */
1144 0x0080000000000080ull, /* 41 */
1145 0x0080000000008000ull, /* 42 */
1146 0x0080000000008080ull, /* 43 */
1147 0x0080000000800000ull, /* 44 */
1148 0x0080000000800080ull, /* 45 */
1149 0x0080000000808000ull, /* 46 */
1150 0x0080000000808080ull, /* 47 */
1151 0x0080000080000000ull, /* 48 */
1152 0x0080000080000080ull, /* 49 */
1153 0x0080000080008000ull, /* 4A */
1154 0x0080000080008080ull, /* 4B */
1155 0x0080000080800000ull, /* 4C */
1156 0x0080000080800080ull, /* 4D */
1157 0x0080000080808000ull, /* 4E */
1158 0x0080000080808080ull, /* 4F */
1159 0x0080008000000000ull, /* 50 */
1160 0x0080008000000080ull, /* 51 */
1161 0x0080008000008000ull, /* 52 */
1162 0x0080008000008080ull, /* 53 */
1163 0x0080008000800000ull, /* 54 */
1164 0x0080008000800080ull, /* 55 */
1165 0x0080008000808000ull, /* 56 */
1166 0x0080008000808080ull, /* 57 */
1167 0x0080008080000000ull, /* 58 */
1168 0x0080008080000080ull, /* 59 */
1169 0x0080008080008000ull, /* 5A */
1170 0x0080008080008080ull, /* 5B */
1171 0x0080008080800000ull, /* 5C */
1172 0x0080008080800080ull, /* 5D */
1173 0x0080008080808000ull, /* 5E */
1174 0x0080008080808080ull, /* 5F */
1175 0x0080800000000000ull, /* 60 */
1176 0x0080800000000080ull, /* 61 */
1177 0x0080800000008000ull, /* 62 */
1178 0x0080800000008080ull, /* 63 */
1179 0x0080800000800000ull, /* 64 */
1180 0x0080800000800080ull, /* 65 */
1181 0x0080800000808000ull, /* 66 */
1182 0x0080800000808080ull, /* 67 */
1183 0x0080800080000000ull, /* 68 */
1184 0x0080800080000080ull, /* 69 */
1185 0x0080800080008000ull, /* 6A */
1186 0x0080800080008080ull, /* 6B */
1187 0x0080800080800000ull, /* 6C */
1188 0x0080800080800080ull, /* 6D */
1189 0x0080800080808000ull, /* 6E */
1190 0x0080800080808080ull, /* 6F */
1191 0x0080808000000000ull, /* 70 */
1192 0x0080808000000080ull, /* 71 */
1193 0x0080808000008000ull, /* 72 */
1194 0x0080808000008080ull, /* 73 */
1195 0x0080808000800000ull, /* 74 */
1196 0x0080808000800080ull, /* 75 */
1197 0x0080808000808000ull, /* 76 */
1198 0x0080808000808080ull, /* 77 */
1199 0x0080808080000000ull, /* 78 */
1200 0x0080808080000080ull, /* 79 */
1201 0x0080808080008000ull, /* 7A */
1202 0x0080808080008080ull, /* 7B */
1203 0x0080808080800000ull, /* 7C */
1204 0x0080808080800080ull, /* 7D */
1205 0x0080808080808000ull, /* 7E */
1206 0x0080808080808080ull, /* 7F */
1207 0x8000000000000000ull, /* 80 */
1208 0x8000000000000080ull, /* 81 */
1209 0x8000000000008000ull, /* 82 */
1210 0x8000000000008080ull, /* 83 */
1211 0x8000000000800000ull, /* 84 */
1212 0x8000000000800080ull, /* 85 */
1213 0x8000000000808000ull, /* 86 */
1214 0x8000000000808080ull, /* 87 */
1215 0x8000000080000000ull, /* 88 */
1216 0x8000000080000080ull, /* 89 */
1217 0x8000000080008000ull, /* 8A */
1218 0x8000000080008080ull, /* 8B */
1219 0x8000000080800000ull, /* 8C */
1220 0x8000000080800080ull, /* 8D */
1221 0x8000000080808000ull, /* 8E */
1222 0x8000000080808080ull, /* 8F */
1223 0x8000008000000000ull, /* 90 */
1224 0x8000008000000080ull, /* 91 */
1225 0x8000008000008000ull, /* 92 */
1226 0x8000008000008080ull, /* 93 */
1227 0x8000008000800000ull, /* 94 */
1228 0x8000008000800080ull, /* 95 */
1229 0x8000008000808000ull, /* 96 */
1230 0x8000008000808080ull, /* 97 */
1231 0x8000008080000000ull, /* 98 */
1232 0x8000008080000080ull, /* 99 */
1233 0x8000008080008000ull, /* 9A */
1234 0x8000008080008080ull, /* 9B */
1235 0x8000008080800000ull, /* 9C */
1236 0x8000008080800080ull, /* 9D */
1237 0x8000008080808000ull, /* 9E */
1238 0x8000008080808080ull, /* 9F */
1239 0x8000800000000000ull, /* A0 */
1240 0x8000800000000080ull, /* A1 */
1241 0x8000800000008000ull, /* A2 */
1242 0x8000800000008080ull, /* A3 */
1243 0x8000800000800000ull, /* A4 */
1244 0x8000800000800080ull, /* A5 */
1245 0x8000800000808000ull, /* A6 */
1246 0x8000800000808080ull, /* A7 */
1247 0x8000800080000000ull, /* A8 */
1248 0x8000800080000080ull, /* A9 */
1249 0x8000800080008000ull, /* AA */
1250 0x8000800080008080ull, /* AB */
1251 0x8000800080800000ull, /* AC */
1252 0x8000800080800080ull, /* AD */
1253 0x8000800080808000ull, /* AE */
1254 0x8000800080808080ull, /* AF */
1255 0x8000808000000000ull, /* B0 */
1256 0x8000808000000080ull, /* B1 */
1257 0x8000808000008000ull, /* B2 */
1258 0x8000808000008080ull, /* B3 */
1259 0x8000808000800000ull, /* B4 */
1260 0x8000808000800080ull, /* B5 */
1261 0x8000808000808000ull, /* B6 */
1262 0x8000808000808080ull, /* B7 */
1263 0x8000808080000000ull, /* B8 */
1264 0x8000808080000080ull, /* B9 */
1265 0x8000808080008000ull, /* BA */
1266 0x8000808080008080ull, /* BB */
1267 0x8000808080800000ull, /* BC */
1268 0x8000808080800080ull, /* BD */
1269 0x8000808080808000ull, /* BE */
1270 0x8000808080808080ull, /* BF */
1271 0x8080000000000000ull, /* C0 */
1272 0x8080000000000080ull, /* C1 */
1273 0x8080000000008000ull, /* C2 */
1274 0x8080000000008080ull, /* C3 */
1275 0x8080000000800000ull, /* C4 */
1276 0x8080000000800080ull, /* C5 */
1277 0x8080000000808000ull, /* C6 */
1278 0x8080000000808080ull, /* C7 */
1279 0x8080000080000000ull, /* C8 */
1280 0x8080000080000080ull, /* C9 */
1281 0x8080000080008000ull, /* CA */
1282 0x8080000080008080ull, /* CB */
1283 0x8080000080800000ull, /* CC */
1284 0x8080000080800080ull, /* CD */
1285 0x8080000080808000ull, /* CE */
1286 0x8080000080808080ull, /* CF */
1287 0x8080008000000000ull, /* D0 */
1288 0x8080008000000080ull, /* D1 */
1289 0x8080008000008000ull, /* D2 */
1290 0x8080008000008080ull, /* D3 */
1291 0x8080008000800000ull, /* D4 */
1292 0x8080008000800080ull, /* D5 */
1293 0x8080008000808000ull, /* D6 */
1294 0x8080008000808080ull, /* D7 */
1295 0x8080008080000000ull, /* D8 */
1296 0x8080008080000080ull, /* D9 */
1297 0x8080008080008000ull, /* DA */
1298 0x8080008080008080ull, /* DB */
1299 0x8080008080800000ull, /* DC */
1300 0x8080008080800080ull, /* DD */
1301 0x8080008080808000ull, /* DE */
1302 0x8080008080808080ull, /* DF */
1303 0x8080800000000000ull, /* E0 */
1304 0x8080800000000080ull, /* E1 */
1305 0x8080800000008000ull, /* E2 */
1306 0x8080800000008080ull, /* E3 */
1307 0x8080800000800000ull, /* E4 */
1308 0x8080800000800080ull, /* E5 */
1309 0x8080800000808000ull, /* E6 */
1310 0x8080800000808080ull, /* E7 */
1311 0x8080800080000000ull, /* E8 */
1312 0x8080800080000080ull, /* E9 */
1313 0x8080800080008000ull, /* EA */
1314 0x8080800080008080ull, /* EB */
1315 0x8080800080800000ull, /* EC */
1316 0x8080800080800080ull, /* ED */
1317 0x8080800080808000ull, /* EE */
1318 0x8080800080808080ull, /* EF */
1319 0x8080808000000000ull, /* F0 */
1320 0x8080808000000080ull, /* F1 */
1321 0x8080808000008000ull, /* F2 */
1322 0x8080808000008080ull, /* F3 */
1323 0x8080808000800000ull, /* F4 */
1324 0x8080808000800080ull, /* F5 */
1325 0x8080808000808000ull, /* F6 */
1326 0x8080808000808080ull, /* F7 */
1327 0x8080808080000000ull, /* F8 */
1328 0x8080808080000080ull, /* F9 */
1329 0x8080808080008000ull, /* FA */
1330 0x8080808080008080ull, /* FB */
1331 0x8080808080800000ull, /* FC */
1332 0x8080808080800080ull, /* FD */
1333 0x8080808080808000ull, /* FE */
1334 0x8080808080808080ull, /* FF */
1335};
1336
1337void helper_vgbbd(ppc_avr_t *r, ppc_avr_t *b)
1338{
1339 int i;
1340 uint64_t t[2] = { 0, 0 };
1341
1342 VECTOR_FOR_INORDER_I(i, u8) {
1343#if defined(HOST_WORDS_BIGENDIAN)
1344 t[i>>3] |= VGBBD_MASKS[b->u8[i]] >> (i & 7);
1345#else
1346 t[i>>3] |= VGBBD_MASKS[b->u8[i]] >> (7-(i & 7));
1347#endif
1348 }
1349
1350 r->u64[0] = t[0];
1351 r->u64[1] = t[1];
1352}
1353
64654ded
BS
1354#if defined(HOST_WORDS_BIGENDIAN)
1355#define PKBIG 1
1356#else
1357#define PKBIG 0
1358#endif
1359void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1360{
1361 int i, j;
1362 ppc_avr_t result;
1363#if defined(HOST_WORDS_BIGENDIAN)
1364 const ppc_avr_t *x[2] = { a, b };
1365#else
1366 const ppc_avr_t *x[2] = { b, a };
1367#endif
1368
1369 VECTOR_FOR_INORDER_I(i, u64) {
1370 VECTOR_FOR_INORDER_I(j, u32) {
1371 uint32_t e = x[i]->u32[j];
1372
1373 result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
1374 ((e >> 6) & 0x3e0) |
1375 ((e >> 3) & 0x1f));
1376 }
1377 }
1378 *r = result;
1379}
1380
1381#define VPK(suffix, from, to, cvt, dosat) \
d15f74fb
BS
1382 void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r, \
1383 ppc_avr_t *a, ppc_avr_t *b) \
64654ded
BS
1384 { \
1385 int i; \
1386 int sat = 0; \
1387 ppc_avr_t result; \
1388 ppc_avr_t *a0 = PKBIG ? a : b; \
1389 ppc_avr_t *a1 = PKBIG ? b : a; \
1390 \
1391 VECTOR_FOR_INORDER_I(i, from) { \
1392 result.to[i] = cvt(a0->from[i], &sat); \
1393 result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat); \
1394 } \
1395 *r = result; \
1396 if (dosat && sat) { \
1397 env->vscr |= (1 << VSCR_SAT); \
1398 } \
1399 }
1400#define I(x, y) (x)
1401VPK(shss, s16, s8, cvtshsb, 1)
1402VPK(shus, s16, u8, cvtshub, 1)
1403VPK(swss, s32, s16, cvtswsh, 1)
1404VPK(swus, s32, u16, cvtswuh, 1)
024215b2
TM
1405VPK(sdss, s64, s32, cvtsdsw, 1)
1406VPK(sdus, s64, u32, cvtsduw, 1)
64654ded
BS
1407VPK(uhus, u16, u8, cvtuhub, 1)
1408VPK(uwus, u32, u16, cvtuwuh, 1)
024215b2 1409VPK(udus, u64, u32, cvtuduw, 1)
64654ded
BS
1410VPK(uhum, u16, u8, I, 0)
1411VPK(uwum, u32, u16, I, 0)
024215b2 1412VPK(udum, u64, u32, I, 0)
64654ded
BS
1413#undef I
1414#undef VPK
1415#undef PKBIG
1416
d15f74fb 1417void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
64654ded
BS
1418{
1419 int i;
1420
1421 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
ef9bd150 1422 r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
64654ded
BS
1423 }
1424}
1425
1426#define VRFI(suffix, rounding) \
d15f74fb
BS
1427 void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r, \
1428 ppc_avr_t *b) \
64654ded
BS
1429 { \
1430 int i; \
1431 float_status s = env->vec_status; \
1432 \
1433 set_float_rounding_mode(rounding, &s); \
1434 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
ef9bd150 1435 r->f[i] = float32_round_to_int (b->f[i], &s); \
64654ded
BS
1436 } \
1437 }
1438VRFI(n, float_round_nearest_even)
1439VRFI(m, float_round_down)
1440VRFI(p, float_round_up)
1441VRFI(z, float_round_to_zero)
1442#undef VRFI
1443
818692ff 1444#define VROTATE(suffix, element, mask) \
64654ded
BS
1445 void helper_vrl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1446 { \
1447 int i; \
1448 \
1449 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
64654ded
BS
1450 unsigned int shift = b->element[i] & mask; \
1451 r->element[i] = (a->element[i] << shift) | \
1452 (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
1453 } \
1454 }
818692ff
TM
1455VROTATE(b, u8, 0x7)
1456VROTATE(h, u16, 0xF)
1457VROTATE(w, u32, 0x1F)
2fdf78e6 1458VROTATE(d, u64, 0x3F)
64654ded
BS
1459#undef VROTATE
1460
d15f74fb 1461void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
64654ded
BS
1462{
1463 int i;
1464
1465 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
ef9bd150 1466 float32 t = float32_sqrt(b->f[i], &env->vec_status);
64654ded 1467
ef9bd150 1468 r->f[i] = float32_div(float32_one, t, &env->vec_status);
64654ded
BS
1469 }
1470}
1471
d15f74fb
BS
1472void helper_vsel(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1473 ppc_avr_t *c)
64654ded
BS
1474{
1475 r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
1476 r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
1477}
1478
d15f74fb 1479void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
64654ded
BS
1480{
1481 int i;
1482
1483 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
ef9bd150 1484 r->f[i] = float32_exp2(b->f[i], &env->vec_status);
64654ded
BS
1485 }
1486}
1487
d15f74fb 1488void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
64654ded
BS
1489{
1490 int i;
1491
1492 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
ef9bd150 1493 r->f[i] = float32_log2(b->f[i], &env->vec_status);
64654ded
BS
1494 }
1495}
1496
1497#if defined(HOST_WORDS_BIGENDIAN)
1498#define LEFT 0
1499#define RIGHT 1
1500#else
1501#define LEFT 1
1502#define RIGHT 0
1503#endif
1504/* The specification says that the results are undefined if all of the
1505 * shift counts are not identical. We check to make sure that they are
1506 * to conform to what real hardware appears to do. */
1507#define VSHIFT(suffix, leftp) \
1508 void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1509 { \
1510 int shift = b->u8[LO_IDX*15] & 0x7; \
1511 int doit = 1; \
1512 int i; \
1513 \
1514 for (i = 0; i < ARRAY_SIZE(r->u8); i++) { \
1515 doit = doit && ((b->u8[i] & 0x7) == shift); \
1516 } \
1517 if (doit) { \
1518 if (shift == 0) { \
1519 *r = *a; \
1520 } else if (leftp) { \
1521 uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \
1522 \
1523 r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \
1524 r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \
1525 } else { \
1526 uint64_t carry = a->u64[HI_IDX] << (64 - shift); \
1527 \
1528 r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \
1529 r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \
1530 } \
1531 } \
1532 }
1533VSHIFT(l, LEFT)
1534VSHIFT(r, RIGHT)
1535#undef VSHIFT
1536#undef LEFT
1537#undef RIGHT
1538
818692ff 1539#define VSL(suffix, element, mask) \
64654ded
BS
1540 void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1541 { \
1542 int i; \
1543 \
1544 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
64654ded
BS
1545 unsigned int shift = b->element[i] & mask; \
1546 \
1547 r->element[i] = a->element[i] << shift; \
1548 } \
1549 }
818692ff
TM
1550VSL(b, u8, 0x7)
1551VSL(h, u16, 0x0F)
1552VSL(w, u32, 0x1F)
2fdf78e6 1553VSL(d, u64, 0x3F)
64654ded
BS
1554#undef VSL
1555
1556void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
1557{
1558 int sh = shift & 0xf;
1559 int i;
1560 ppc_avr_t result;
1561
1562#if defined(HOST_WORDS_BIGENDIAN)
1563 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1564 int index = sh + i;
1565 if (index > 0xf) {
1566 result.u8[i] = b->u8[index - 0x10];
1567 } else {
1568 result.u8[i] = a->u8[index];
1569 }
1570 }
1571#else
1572 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1573 int index = (16 - sh) + i;
1574 if (index > 0xf) {
1575 result.u8[i] = a->u8[index - 0x10];
1576 } else {
1577 result.u8[i] = b->u8[index];
1578 }
1579 }
1580#endif
1581 *r = result;
1582}
1583
1584void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1585{
1586 int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
1587
1588#if defined(HOST_WORDS_BIGENDIAN)
1589 memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1590 memset(&r->u8[16-sh], 0, sh);
1591#else
1592 memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1593 memset(&r->u8[0], 0, sh);
1594#endif
1595}
1596
1597/* Experimental testing shows that hardware masks the immediate. */
1598#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
1599#if defined(HOST_WORDS_BIGENDIAN)
1600#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
1601#else
1602#define SPLAT_ELEMENT(element) \
1603 (ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element))
1604#endif
1605#define VSPLT(suffix, element) \
1606 void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
1607 { \
1608 uint32_t s = b->element[SPLAT_ELEMENT(element)]; \
1609 int i; \
1610 \
1611 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1612 r->element[i] = s; \
1613 } \
1614 }
1615VSPLT(b, u8)
1616VSPLT(h, u16)
1617VSPLT(w, u32)
1618#undef VSPLT
1619#undef SPLAT_ELEMENT
1620#undef _SPLAT_MASKED
1621
1622#define VSPLTI(suffix, element, splat_type) \
1623 void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
1624 { \
1625 splat_type x = (int8_t)(splat << 3) >> 3; \
1626 int i; \
1627 \
1628 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1629 r->element[i] = x; \
1630 } \
1631 }
1632VSPLTI(b, s8, int8_t)
1633VSPLTI(h, s16, int16_t)
1634VSPLTI(w, s32, int32_t)
1635#undef VSPLTI
1636
818692ff 1637#define VSR(suffix, element, mask) \
64654ded
BS
1638 void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1639 { \
1640 int i; \
1641 \
1642 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
64654ded 1643 unsigned int shift = b->element[i] & mask; \
64654ded
BS
1644 r->element[i] = a->element[i] >> shift; \
1645 } \
1646 }
818692ff
TM
1647VSR(ab, s8, 0x7)
1648VSR(ah, s16, 0xF)
1649VSR(aw, s32, 0x1F)
2fdf78e6 1650VSR(ad, s64, 0x3F)
818692ff
TM
1651VSR(b, u8, 0x7)
1652VSR(h, u16, 0xF)
1653VSR(w, u32, 0x1F)
2fdf78e6 1654VSR(d, u64, 0x3F)
64654ded
BS
1655#undef VSR
1656
1657void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1658{
1659 int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf;
1660
1661#if defined(HOST_WORDS_BIGENDIAN)
1662 memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1663 memset(&r->u8[0], 0, sh);
1664#else
1665 memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1666 memset(&r->u8[16 - sh], 0, sh);
1667#endif
1668}
1669
1670void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1671{
1672 int i;
1673
1674 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1675 r->u32[i] = a->u32[i] >= b->u32[i];
1676 }
1677}
1678
d15f74fb 1679void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1680{
1681 int64_t t;
1682 int i, upper;
1683 ppc_avr_t result;
1684 int sat = 0;
1685
1686#if defined(HOST_WORDS_BIGENDIAN)
1687 upper = ARRAY_SIZE(r->s32)-1;
1688#else
1689 upper = 0;
1690#endif
1691 t = (int64_t)b->s32[upper];
1692 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1693 t += a->s32[i];
1694 result.s32[i] = 0;
1695 }
1696 result.s32[upper] = cvtsdsw(t, &sat);
1697 *r = result;
1698
1699 if (sat) {
1700 env->vscr |= (1 << VSCR_SAT);
1701 }
1702}
1703
d15f74fb 1704void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1705{
1706 int i, j, upper;
1707 ppc_avr_t result;
1708 int sat = 0;
1709
1710#if defined(HOST_WORDS_BIGENDIAN)
1711 upper = 1;
1712#else
1713 upper = 0;
1714#endif
1715 for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1716 int64_t t = (int64_t)b->s32[upper + i * 2];
1717
1718 result.u64[i] = 0;
1719 for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
1720 t += a->s32[2 * i + j];
1721 }
1722 result.s32[upper + i * 2] = cvtsdsw(t, &sat);
1723 }
1724
1725 *r = result;
1726 if (sat) {
1727 env->vscr |= (1 << VSCR_SAT);
1728 }
1729}
1730
d15f74fb 1731void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1732{
1733 int i, j;
1734 int sat = 0;
1735
1736 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1737 int64_t t = (int64_t)b->s32[i];
1738
1739 for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
1740 t += a->s8[4 * i + j];
1741 }
1742 r->s32[i] = cvtsdsw(t, &sat);
1743 }
1744
1745 if (sat) {
1746 env->vscr |= (1 << VSCR_SAT);
1747 }
1748}
1749
d15f74fb 1750void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1751{
1752 int sat = 0;
1753 int i;
1754
1755 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1756 int64_t t = (int64_t)b->s32[i];
1757
1758 t += a->s16[2 * i] + a->s16[2 * i + 1];
1759 r->s32[i] = cvtsdsw(t, &sat);
1760 }
1761
1762 if (sat) {
1763 env->vscr |= (1 << VSCR_SAT);
1764 }
1765}
1766
d15f74fb 1767void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1768{
1769 int i, j;
1770 int sat = 0;
1771
1772 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1773 uint64_t t = (uint64_t)b->u32[i];
1774
1775 for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
1776 t += a->u8[4 * i + j];
1777 }
1778 r->u32[i] = cvtuduw(t, &sat);
1779 }
1780
1781 if (sat) {
1782 env->vscr |= (1 << VSCR_SAT);
1783 }
1784}
1785
1786#if defined(HOST_WORDS_BIGENDIAN)
1787#define UPKHI 1
1788#define UPKLO 0
1789#else
1790#define UPKHI 0
1791#define UPKLO 1
1792#endif
1793#define VUPKPX(suffix, hi) \
1794 void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \
1795 { \
1796 int i; \
1797 ppc_avr_t result; \
1798 \
1799 for (i = 0; i < ARRAY_SIZE(r->u32); i++) { \
1800 uint16_t e = b->u16[hi ? i : i+4]; \
1801 uint8_t a = (e >> 15) ? 0xff : 0; \
1802 uint8_t r = (e >> 10) & 0x1f; \
1803 uint8_t g = (e >> 5) & 0x1f; \
1804 uint8_t b = e & 0x1f; \
1805 \
1806 result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b; \
1807 } \
1808 *r = result; \
1809 }
1810VUPKPX(lpx, UPKLO)
1811VUPKPX(hpx, UPKHI)
1812#undef VUPKPX
1813
1814#define VUPK(suffix, unpacked, packee, hi) \
1815 void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \
1816 { \
1817 int i; \
1818 ppc_avr_t result; \
1819 \
1820 if (hi) { \
1821 for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) { \
1822 result.unpacked[i] = b->packee[i]; \
1823 } \
1824 } else { \
1825 for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
1826 i++) { \
1827 result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
1828 } \
1829 } \
1830 *r = result; \
1831 }
1832VUPK(hsb, s16, s8, UPKHI)
1833VUPK(hsh, s32, s16, UPKHI)
4430e076 1834VUPK(hsw, s64, s32, UPKHI)
64654ded
BS
1835VUPK(lsb, s16, s8, UPKLO)
1836VUPK(lsh, s32, s16, UPKLO)
4430e076 1837VUPK(lsw, s64, s32, UPKLO)
64654ded
BS
1838#undef VUPK
1839#undef UPKHI
1840#undef UPKLO
1841
f293f04a
TM
1842#define VGENERIC_DO(name, element) \
1843 void helper_v##name(ppc_avr_t *r, ppc_avr_t *b) \
1844 { \
1845 int i; \
1846 \
1847 VECTOR_FOR_INORDER_I(i, element) { \
1848 r->element[i] = name(b->element[i]); \
1849 } \
1850 }
1851
1852#define clzb(v) ((v) ? clz32((uint32_t)(v) << 24) : 8)
1853#define clzh(v) ((v) ? clz32((uint32_t)(v) << 16) : 16)
1854#define clzw(v) clz32((v))
1855#define clzd(v) clz64((v))
1856
1857VGENERIC_DO(clzb, u8)
1858VGENERIC_DO(clzh, u16)
1859VGENERIC_DO(clzw, u32)
1860VGENERIC_DO(clzd, u64)
1861
1862#undef clzb
1863#undef clzh
1864#undef clzw
1865#undef clzd
1866
e13500b3
TM
1867#define popcntb(v) ctpop8(v)
1868#define popcnth(v) ctpop16(v)
1869#define popcntw(v) ctpop32(v)
1870#define popcntd(v) ctpop64(v)
1871
1872VGENERIC_DO(popcntb, u8)
1873VGENERIC_DO(popcnth, u16)
1874VGENERIC_DO(popcntw, u32)
1875VGENERIC_DO(popcntd, u64)
1876
1877#undef popcntb
1878#undef popcnth
1879#undef popcntw
1880#undef popcntd
f293f04a
TM
1881
1882#undef VGENERIC_DO
1883
b41da4eb
TM
1884#if defined(HOST_WORDS_BIGENDIAN)
1885#define QW_ONE { .u64 = { 0, 1 } }
1886#else
1887#define QW_ONE { .u64 = { 1, 0 } }
1888#endif
1889
1890#ifndef CONFIG_INT128
1891
1892static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a)
1893{
1894 t->u64[0] = ~a.u64[0];
1895 t->u64[1] = ~a.u64[1];
1896}
1897
1898static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b)
1899{
1900 if (a.u64[HI_IDX] < b.u64[HI_IDX]) {
1901 return -1;
1902 } else if (a.u64[HI_IDX] > b.u64[HI_IDX]) {
1903 return 1;
1904 } else if (a.u64[LO_IDX] < b.u64[LO_IDX]) {
1905 return -1;
1906 } else if (a.u64[LO_IDX] > b.u64[LO_IDX]) {
1907 return 1;
1908 } else {
1909 return 0;
1910 }
1911}
1912
1913static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b)
1914{
1915 t->u64[LO_IDX] = a.u64[LO_IDX] + b.u64[LO_IDX];
1916 t->u64[HI_IDX] = a.u64[HI_IDX] + b.u64[HI_IDX] +
1917 (~a.u64[LO_IDX] < b.u64[LO_IDX]);
1918}
1919
1920static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b)
1921{
1922 ppc_avr_t not_a;
1923 t->u64[LO_IDX] = a.u64[LO_IDX] + b.u64[LO_IDX];
1924 t->u64[HI_IDX] = a.u64[HI_IDX] + b.u64[HI_IDX] +
1925 (~a.u64[LO_IDX] < b.u64[LO_IDX]);
1926 avr_qw_not(&not_a, a);
1927 return avr_qw_cmpu(not_a, b) < 0;
1928}
1929
1930#endif
1931
1932void helper_vadduqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1933{
1934#ifdef CONFIG_INT128
1935 r->u128 = a->u128 + b->u128;
1936#else
1937 avr_qw_add(r, *a, *b);
1938#endif
1939}
1940
1941void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1942{
1943#ifdef CONFIG_INT128
1944 r->u128 = a->u128 + b->u128 + (c->u128 & 1);
1945#else
1946
1947 if (c->u64[LO_IDX] & 1) {
1948 ppc_avr_t tmp;
1949
1950 tmp.u64[HI_IDX] = 0;
1951 tmp.u64[LO_IDX] = c->u64[LO_IDX] & 1;
1952 avr_qw_add(&tmp, *a, tmp);
1953 avr_qw_add(r, tmp, *b);
1954 } else {
1955 avr_qw_add(r, *a, *b);
1956 }
1957#endif
1958}
1959
1960void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1961{
1962#ifdef CONFIG_INT128
1963 r->u128 = (~a->u128 < b->u128);
1964#else
1965 ppc_avr_t not_a;
1966
1967 avr_qw_not(&not_a, *a);
1968
1969 r->u64[HI_IDX] = 0;
1970 r->u64[LO_IDX] = (avr_qw_cmpu(not_a, *b) < 0);
1971#endif
1972}
1973
1974void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
1975{
1976#ifdef CONFIG_INT128
1977 int carry_out = (~a->u128 < b->u128);
1978 if (!carry_out && (c->u128 & 1)) {
1979 carry_out = ((a->u128 + b->u128 + 1) == 0) &&
1980 ((a->u128 != 0) || (b->u128 != 0));
1981 }
1982 r->u128 = carry_out;
1983#else
1984
1985 int carry_in = c->u64[LO_IDX] & 1;
1986 int carry_out = 0;
1987 ppc_avr_t tmp;
1988
1989 carry_out = avr_qw_addc(&tmp, *a, *b);
1990
1991 if (!carry_out && carry_in) {
1992 ppc_avr_t one = QW_ONE;
1993 carry_out = avr_qw_addc(&tmp, tmp, one);
1994 }
1995 r->u64[HI_IDX] = 0;
1996 r->u64[LO_IDX] = carry_out;
1997#endif
1998}
1999
2000void helper_vsubuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2001{
2002#ifdef CONFIG_INT128
2003 r->u128 = a->u128 - b->u128;
2004#else
2005 ppc_avr_t tmp;
2006 ppc_avr_t one = QW_ONE;
2007
2008 avr_qw_not(&tmp, *b);
2009 avr_qw_add(&tmp, *a, tmp);
2010 avr_qw_add(r, tmp, one);
2011#endif
2012}
2013
2014void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2015{
2016#ifdef CONFIG_INT128
2017 r->u128 = a->u128 + ~b->u128 + (c->u128 & 1);
2018#else
2019 ppc_avr_t tmp, sum;
2020
2021 avr_qw_not(&tmp, *b);
2022 avr_qw_add(&sum, *a, tmp);
2023
2024 tmp.u64[HI_IDX] = 0;
2025 tmp.u64[LO_IDX] = c->u64[LO_IDX] & 1;
2026 avr_qw_add(r, sum, tmp);
2027#endif
2028}
2029
2030void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2031{
2032#ifdef CONFIG_INT128
2033 r->u128 = (~a->u128 < ~b->u128) ||
2034 (a->u128 + ~b->u128 == (__uint128_t)-1);
2035#else
2036 int carry = (avr_qw_cmpu(*a, *b) > 0);
2037 if (!carry) {
2038 ppc_avr_t tmp;
2039 avr_qw_not(&tmp, *b);
2040 avr_qw_add(&tmp, *a, tmp);
2041 carry = ((tmp.s64[HI_IDX] == -1ull) && (tmp.s64[LO_IDX] == -1ull));
2042 }
2043 r->u64[HI_IDX] = 0;
2044 r->u64[LO_IDX] = carry;
2045#endif
2046}
2047
2048void helper_vsubecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2049{
2050#ifdef CONFIG_INT128
2051 r->u128 =
2052 (~a->u128 < ~b->u128) ||
2053 ((c->u128 & 1) && (a->u128 + ~b->u128 == (__uint128_t)-1));
2054#else
2055 int carry_in = c->u64[LO_IDX] & 1;
2056 int carry_out = (avr_qw_cmpu(*a, *b) > 0);
2057 if (!carry_out && carry_in) {
2058 ppc_avr_t tmp;
2059 avr_qw_not(&tmp, *b);
2060 avr_qw_add(&tmp, *a, tmp);
2061 carry_out = ((tmp.u64[HI_IDX] == -1ull) && (tmp.u64[LO_IDX] == -1ull));
2062 }
2063
2064 r->u64[HI_IDX] = 0;
2065 r->u64[LO_IDX] = carry_out;
2066#endif
2067}
2068
f293f04a 2069
64654ded
BS
2070#undef VECTOR_FOR_INORDER_I
2071#undef HI_IDX
2072#undef LO_IDX
2073
2074/*****************************************************************************/
2075/* SPE extension helpers */
2076/* Use a table to make this quicker */
ea6c0dac 2077static const uint8_t hbrev[16] = {
64654ded
BS
2078 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
2079 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
2080};
2081
2082static inline uint8_t byte_reverse(uint8_t val)
2083{
2084 return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
2085}
2086
2087static inline uint32_t word_reverse(uint32_t val)
2088{
2089 return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
2090 (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
2091}
2092
2093#define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
2094target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
2095{
2096 uint32_t a, b, d, mask;
2097
2098 mask = UINT32_MAX >> (32 - MASKBITS);
2099 a = arg1 & mask;
2100 b = arg2 & mask;
2101 d = word_reverse(1 + word_reverse(a | ~b));
2102 return (arg1 & ~mask) | (d & b);
2103}
2104
2105uint32_t helper_cntlsw32(uint32_t val)
2106{
2107 if (val & 0x80000000) {
2108 return clz32(~val);
2109 } else {
2110 return clz32(val);
2111 }
2112}
2113
2114uint32_t helper_cntlzw32(uint32_t val)
2115{
2116 return clz32(val);
2117}
2118
2119/* 440 specific */
d15f74fb
BS
2120target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high,
2121 target_ulong low, uint32_t update_Rc)
64654ded
BS
2122{
2123 target_ulong mask;
2124 int i;
2125
2126 i = 1;
2127 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
2128 if ((high & mask) == 0) {
2129 if (update_Rc) {
2130 env->crf[0] = 0x4;
2131 }
2132 goto done;
2133 }
2134 i++;
2135 }
2136 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
2137 if ((low & mask) == 0) {
2138 if (update_Rc) {
2139 env->crf[0] = 0x8;
2140 }
2141 goto done;
2142 }
2143 i++;
2144 }
2145 if (update_Rc) {
2146 env->crf[0] = 0x2;
2147 }
2148 done:
2149 env->xer = (env->xer & ~0x7F) | i;
2150 if (update_Rc) {
2151 env->crf[0] |= xer_so;
2152 }
2153 return i;
2154}
This page took 0.476574 seconds and 4 git commands to generate.