target-ppc: Altivec 2.07: Multiply Even/Odd Word Instructions
[qemu/ar7.git] / target-ppc / int_helper.c
blob09590c71a26187097ba7f4e7139044f67b75570b
1 /*
2 * PowerPC integer and vector emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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.
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.
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/>.
19 #include "cpu.h"
20 #include "qemu/host-utils.h"
21 #include "helper.h"
23 #include "helper_regs.h"
24 /*****************************************************************************/
25 /* Fixed point operations helpers */
26 #if defined(TARGET_PPC64)
28 uint64_t helper_mulldo(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
30 int64_t th;
31 uint64_t tl;
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)) {
36 env->ov = 0;
37 } else {
38 env->so = env->ov = 1;
40 return (int64_t)tl;
42 #endif
44 target_ulong helper_divweu(CPUPPCState *env, target_ulong ra, target_ulong rb,
45 uint32_t oe)
47 uint64_t rt = 0;
48 int overflow = 0;
50 uint64_t dividend = (uint64_t)ra << 32;
51 uint64_t divisor = (uint32_t)rb;
53 if (unlikely(divisor == 0)) {
54 overflow = 1;
55 } else {
56 rt = dividend / divisor;
57 overflow = rt > UINT32_MAX;
60 if (unlikely(overflow)) {
61 rt = 0; /* Undefined */
64 if (oe) {
65 if (unlikely(overflow)) {
66 env->so = env->ov = 1;
67 } else {
68 env->ov = 0;
72 return (target_ulong)rt;
75 target_ulong helper_divwe(CPUPPCState *env, target_ulong ra, target_ulong rb,
76 uint32_t oe)
78 int64_t rt = 0;
79 int overflow = 0;
81 int64_t dividend = (int64_t)ra << 32;
82 int64_t divisor = (int64_t)((int32_t)rb);
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;
92 if (unlikely(overflow)) {
93 rt = 0; /* Undefined */
96 if (oe) {
97 if (unlikely(overflow)) {
98 env->so = env->ov = 1;
99 } else {
100 env->ov = 0;
104 return (target_ulong)rt;
107 #if defined(TARGET_PPC64)
109 uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe)
111 uint64_t rt = 0;
112 int overflow = 0;
114 overflow = divu128(&rt, &ra, rb);
116 if (unlikely(overflow)) {
117 rt = 0; /* Undefined */
120 if (oe) {
121 if (unlikely(overflow)) {
122 env->so = env->ov = 1;
123 } else {
124 env->ov = 0;
128 return rt;
131 uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
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);
138 if (unlikely(overflow)) {
139 rt = 0; /* Undefined */
142 if (oe) {
144 if (unlikely(overflow)) {
145 env->so = env->ov = 1;
146 } else {
147 env->ov = 0;
151 return rt;
154 #endif
157 target_ulong helper_cntlzw(target_ulong t)
159 return clz32(t);
162 #if defined(TARGET_PPC64)
163 target_ulong helper_cntlzd(target_ulong t)
165 return clz64(t);
167 #endif
169 #if defined(TARGET_PPC64)
171 uint64_t helper_bpermd(uint64_t rs, uint64_t rb)
173 int i;
174 uint64_t ra = 0;
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;
184 return ra;
187 #endif
189 target_ulong helper_cmpb(target_ulong rs, target_ulong rb)
191 target_ulong mask = 0xff;
192 target_ulong ra = 0;
193 int i;
195 for (i = 0; i < sizeof(target_ulong); i++) {
196 if ((rs & mask) == (rb & mask)) {
197 ra |= mask;
199 mask <<= 8;
201 return ra;
204 /* shift right arithmetic helper */
205 target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
206 target_ulong shift)
208 int32_t ret;
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)) {
215 env->ca = 0;
216 } else {
217 env->ca = 1;
219 } else {
220 ret = (int32_t)value;
221 env->ca = 0;
223 } else {
224 ret = (int32_t)value >> 31;
225 env->ca = (ret != 0);
227 return (target_long)ret;
230 #if defined(TARGET_PPC64)
231 target_ulong helper_srad(CPUPPCState *env, target_ulong value,
232 target_ulong shift)
234 int64_t ret;
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)) {
241 env->ca = 0;
242 } else {
243 env->ca = 1;
245 } else {
246 ret = (int64_t)value;
247 env->ca = 0;
249 } else {
250 ret = (int64_t)value >> 63;
251 env->ca = (ret != 0);
253 return ret;
255 #endif
257 #if defined(TARGET_PPC64)
258 target_ulong helper_popcntb(target_ulong val)
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;
269 target_ulong helper_popcntw(target_ulong val)
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;
284 target_ulong helper_popcntd(target_ulong val)
286 return ctpop64(val);
288 #else
289 target_ulong helper_popcntb(target_ulong val)
291 val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
292 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
293 val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
294 return val;
297 target_ulong helper_popcntw(target_ulong val)
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;
306 #endif
308 /*****************************************************************************/
309 /* PowerPC 601 specific instructions (POWER bridge) */
310 target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
312 uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
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;
324 target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
325 target_ulong arg2)
327 uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
329 if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
330 (int32_t)arg2 == 0) {
331 env->so = env->ov = 1;
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) {
338 env->so = env->ov = 1;
339 } else {
340 env->ov = 0;
342 return tmp;
346 target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
347 target_ulong arg2)
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;
359 target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
360 target_ulong arg2)
362 if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
363 (int32_t)arg2 == 0) {
364 env->so = env->ov = 1;
365 env->spr[SPR_MQ] = 0;
366 return INT32_MIN;
367 } else {
368 env->ov = 0;
369 env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
370 return (int32_t)arg1 / (int32_t)arg2;
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
382 #if !defined(CONFIG_USER_ONLY)
383 target_ulong helper_602_mfrom(target_ulong arg)
385 if (likely(arg < 602)) {
386 #include "mfrom_table.c"
387 return mfrom_ROM_table[arg];
388 } else {
389 return 0;
392 #endif
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
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
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) \
416 to_type r; \
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; \
427 return r; \
429 #define SATCVTU(from, to, from_type, to_type, min, max) \
430 static inline to_type cvt##from##to(from_type x, int *sat) \
432 to_type r; \
434 if (x > (from_type)max) { \
435 r = max; \
436 *sat = 1; \
437 } else { \
438 r = x; \
440 return r; \
442 SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX)
443 SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX)
444 SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX)
446 SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX)
447 SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX)
448 SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX)
449 SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX)
450 SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX)
451 SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
452 #undef SATCVT
453 #undef SATCVTU
455 void helper_lvsl(ppc_avr_t *r, target_ulong sh)
457 int i, j = (sh & 0xf);
459 VECTOR_FOR_INORDER_I(i, u8) {
460 r->u8[i] = j++;
464 void helper_lvsr(ppc_avr_t *r, target_ulong sh)
466 int i, j = 0x10 - (sh & 0xf);
468 VECTOR_FOR_INORDER_I(i, u8) {
469 r->u8[i] = j++;
473 void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
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);
483 void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
485 int i;
487 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
488 r->u32[i] = ~a->u32[i] < b->u32[i];
492 #define VARITH_DO(name, op, element) \
493 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
495 int i; \
497 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
498 r->element[i] = a->element[i] op b->element[i]; \
501 #define VARITH(suffix, element) \
502 VARITH_DO(add##suffix, +, element) \
503 VARITH_DO(sub##suffix, -, element)
504 VARITH(ubm, u8)
505 VARITH(uhm, u16)
506 VARITH(uwm, u32)
507 VARITH(udm, u64)
508 #undef VARITH_DO
509 #undef VARITH
511 #define VARITHFP(suffix, func) \
512 void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
513 ppc_avr_t *b) \
515 int i; \
517 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
518 r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
521 VARITHFP(addfp, float32_add)
522 VARITHFP(subfp, float32_sub)
523 VARITHFP(minfp, float32_min)
524 VARITHFP(maxfp, float32_max)
525 #undef VARITHFP
527 #define VARITHFPFMA(suffix, type) \
528 void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
529 ppc_avr_t *b, ppc_avr_t *c) \
531 int i; \
532 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
533 r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i], \
534 type, &env->vec_status); \
537 VARITHFPFMA(maddfp, 0);
538 VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
539 #undef VARITHFPFMA
541 #define VARITHSAT_CASE(type, op, cvt, element) \
543 type result = (type)a->element[i] op (type)b->element[i]; \
544 r->element[i] = cvt(result, &sat); \
547 #define VARITHSAT_DO(name, op, optype, cvt, element) \
548 void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
549 ppc_avr_t *b) \
551 int sat = 0; \
552 int i; \
554 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
555 switch (sizeof(r->element[0])) { \
556 case 1: \
557 VARITHSAT_CASE(optype, op, cvt, element); \
558 break; \
559 case 2: \
560 VARITHSAT_CASE(optype, op, cvt, element); \
561 break; \
562 case 4: \
563 VARITHSAT_CASE(optype, op, cvt, element); \
564 break; \
567 if (sat) { \
568 env->vscr |= (1 << VSCR_SAT); \
571 #define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
572 VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element) \
573 VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
574 #define VARITHSAT_UNSIGNED(suffix, element, optype, cvt) \
575 VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element) \
576 VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
577 VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
578 VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
579 VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
580 VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
581 VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
582 VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
583 #undef VARITHSAT_CASE
584 #undef VARITHSAT_DO
585 #undef VARITHSAT_SIGNED
586 #undef VARITHSAT_UNSIGNED
588 #define VAVG_DO(name, element, etype) \
589 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
591 int i; \
593 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
594 etype x = (etype)a->element[i] + (etype)b->element[i] + 1; \
595 r->element[i] = x >> 1; \
599 #define VAVG(type, signed_element, signed_type, unsigned_element, \
600 unsigned_type) \
601 VAVG_DO(avgs##type, signed_element, signed_type) \
602 VAVG_DO(avgu##type, unsigned_element, unsigned_type)
603 VAVG(b, s8, int16_t, u8, uint16_t)
604 VAVG(h, s16, int32_t, u16, uint32_t)
605 VAVG(w, s32, int64_t, u32, uint64_t)
606 #undef VAVG_DO
607 #undef VAVG
609 #define VCF(suffix, cvt, element) \
610 void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r, \
611 ppc_avr_t *b, uint32_t uim) \
613 int i; \
615 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
616 float32 t = cvt(b->element[i], &env->vec_status); \
617 r->f[i] = float32_scalbn(t, -uim, &env->vec_status); \
620 VCF(ux, uint32_to_float32, u32)
621 VCF(sx, int32_to_float32, s32)
622 #undef VCF
624 #define VCMP_DO(suffix, compare, element, record) \
625 void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
626 ppc_avr_t *a, ppc_avr_t *b) \
628 uint32_t ones = (uint32_t)-1; \
629 uint32_t all = ones; \
630 uint32_t none = 0; \
631 int i; \
633 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
634 uint32_t result = (a->element[i] compare b->element[i] ? \
635 ones : 0x0); \
636 switch (sizeof(a->element[0])) { \
637 case 4: \
638 r->u32[i] = result; \
639 break; \
640 case 2: \
641 r->u16[i] = result; \
642 break; \
643 case 1: \
644 r->u8[i] = result; \
645 break; \
647 all &= result; \
648 none |= result; \
650 if (record) { \
651 env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
654 #define VCMP(suffix, compare, element) \
655 VCMP_DO(suffix, compare, element, 0) \
656 VCMP_DO(suffix##_dot, compare, element, 1)
657 VCMP(equb, ==, u8)
658 VCMP(equh, ==, u16)
659 VCMP(equw, ==, u32)
660 VCMP(gtub, >, u8)
661 VCMP(gtuh, >, u16)
662 VCMP(gtuw, >, u32)
663 VCMP(gtsb, >, s8)
664 VCMP(gtsh, >, s16)
665 VCMP(gtsw, >, s32)
666 #undef VCMP_DO
667 #undef VCMP
669 #define VCMPFP_DO(suffix, compare, order, record) \
670 void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
671 ppc_avr_t *a, ppc_avr_t *b) \
673 uint32_t ones = (uint32_t)-1; \
674 uint32_t all = ones; \
675 uint32_t none = 0; \
676 int i; \
678 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
679 uint32_t result; \
680 int rel = float32_compare_quiet(a->f[i], b->f[i], \
681 &env->vec_status); \
682 if (rel == float_relation_unordered) { \
683 result = 0; \
684 } else if (rel compare order) { \
685 result = ones; \
686 } else { \
687 result = 0; \
689 r->u32[i] = result; \
690 all &= result; \
691 none |= result; \
693 if (record) { \
694 env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
697 #define VCMPFP(suffix, compare, order) \
698 VCMPFP_DO(suffix, compare, order, 0) \
699 VCMPFP_DO(suffix##_dot, compare, order, 1)
700 VCMPFP(eqfp, ==, float_relation_equal)
701 VCMPFP(gefp, !=, float_relation_less)
702 VCMPFP(gtfp, ==, float_relation_greater)
703 #undef VCMPFP_DO
704 #undef VCMPFP
706 static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r,
707 ppc_avr_t *a, ppc_avr_t *b, int record)
709 int i;
710 int all_in = 0;
712 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
713 int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
714 if (le_rel == float_relation_unordered) {
715 r->u32[i] = 0xc0000000;
716 /* ALL_IN does not need to be updated here. */
717 } else {
718 float32 bneg = float32_chs(b->f[i]);
719 int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
720 int le = le_rel != float_relation_greater;
721 int ge = ge_rel != float_relation_less;
723 r->u32[i] = ((!le) << 31) | ((!ge) << 30);
724 all_in |= (!le | !ge);
727 if (record) {
728 env->crf[6] = (all_in == 0) << 1;
732 void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
734 vcmpbfp_internal(env, r, a, b, 0);
737 void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
738 ppc_avr_t *b)
740 vcmpbfp_internal(env, r, a, b, 1);
743 #define VCT(suffix, satcvt, element) \
744 void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r, \
745 ppc_avr_t *b, uint32_t uim) \
747 int i; \
748 int sat = 0; \
749 float_status s = env->vec_status; \
751 set_float_rounding_mode(float_round_to_zero, &s); \
752 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
753 if (float32_is_any_nan(b->f[i])) { \
754 r->element[i] = 0; \
755 } else { \
756 float64 t = float32_to_float64(b->f[i], &s); \
757 int64_t j; \
759 t = float64_scalbn(t, uim, &s); \
760 j = float64_to_int64(t, &s); \
761 r->element[i] = satcvt(j, &sat); \
764 if (sat) { \
765 env->vscr |= (1 << VSCR_SAT); \
768 VCT(uxs, cvtsduw, u32)
769 VCT(sxs, cvtsdsw, s32)
770 #undef VCT
772 void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
773 ppc_avr_t *b, ppc_avr_t *c)
775 int sat = 0;
776 int i;
778 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
779 int32_t prod = a->s16[i] * b->s16[i];
780 int32_t t = (int32_t)c->s16[i] + (prod >> 15);
782 r->s16[i] = cvtswsh(t, &sat);
785 if (sat) {
786 env->vscr |= (1 << VSCR_SAT);
790 void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
791 ppc_avr_t *b, ppc_avr_t *c)
793 int sat = 0;
794 int i;
796 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
797 int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
798 int32_t t = (int32_t)c->s16[i] + (prod >> 15);
799 r->s16[i] = cvtswsh(t, &sat);
802 if (sat) {
803 env->vscr |= (1 << VSCR_SAT);
807 #define VMINMAX_DO(name, compare, element) \
808 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
810 int i; \
812 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
813 if (a->element[i] compare b->element[i]) { \
814 r->element[i] = b->element[i]; \
815 } else { \
816 r->element[i] = a->element[i]; \
820 #define VMINMAX(suffix, element) \
821 VMINMAX_DO(min##suffix, >, element) \
822 VMINMAX_DO(max##suffix, <, element)
823 VMINMAX(sb, s8)
824 VMINMAX(sh, s16)
825 VMINMAX(sw, s32)
826 VMINMAX(ub, u8)
827 VMINMAX(uh, u16)
828 VMINMAX(uw, u32)
829 #undef VMINMAX_DO
830 #undef VMINMAX
832 void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
834 int i;
836 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
837 int32_t prod = a->s16[i] * b->s16[i];
838 r->s16[i] = (int16_t) (prod + c->s16[i]);
842 #define VMRG_DO(name, element, highp) \
843 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
845 ppc_avr_t result; \
846 int i; \
847 size_t n_elems = ARRAY_SIZE(r->element); \
849 for (i = 0; i < n_elems / 2; i++) { \
850 if (highp) { \
851 result.element[i*2+HI_IDX] = a->element[i]; \
852 result.element[i*2+LO_IDX] = b->element[i]; \
853 } else { \
854 result.element[n_elems - i * 2 - (1 + HI_IDX)] = \
855 b->element[n_elems - i - 1]; \
856 result.element[n_elems - i * 2 - (1 + LO_IDX)] = \
857 a->element[n_elems - i - 1]; \
860 *r = result; \
862 #if defined(HOST_WORDS_BIGENDIAN)
863 #define MRGHI 0
864 #define MRGLO 1
865 #else
866 #define MRGHI 1
867 #define MRGLO 0
868 #endif
869 #define VMRG(suffix, element) \
870 VMRG_DO(mrgl##suffix, element, MRGHI) \
871 VMRG_DO(mrgh##suffix, element, MRGLO)
872 VMRG(b, u8)
873 VMRG(h, u16)
874 VMRG(w, u32)
875 #undef VMRG_DO
876 #undef VMRG
877 #undef MRGHI
878 #undef MRGLO
880 void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
881 ppc_avr_t *b, ppc_avr_t *c)
883 int32_t prod[16];
884 int i;
886 for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
887 prod[i] = (int32_t)a->s8[i] * b->u8[i];
890 VECTOR_FOR_INORDER_I(i, s32) {
891 r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
892 prod[4 * i + 2] + prod[4 * i + 3];
896 void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
897 ppc_avr_t *b, ppc_avr_t *c)
899 int32_t prod[8];
900 int i;
902 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
903 prod[i] = a->s16[i] * b->s16[i];
906 VECTOR_FOR_INORDER_I(i, s32) {
907 r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
911 void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
912 ppc_avr_t *b, ppc_avr_t *c)
914 int32_t prod[8];
915 int i;
916 int sat = 0;
918 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
919 prod[i] = (int32_t)a->s16[i] * b->s16[i];
922 VECTOR_FOR_INORDER_I(i, s32) {
923 int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
925 r->u32[i] = cvtsdsw(t, &sat);
928 if (sat) {
929 env->vscr |= (1 << VSCR_SAT);
933 void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
934 ppc_avr_t *b, ppc_avr_t *c)
936 uint16_t prod[16];
937 int i;
939 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
940 prod[i] = a->u8[i] * b->u8[i];
943 VECTOR_FOR_INORDER_I(i, u32) {
944 r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
945 prod[4 * i + 2] + prod[4 * i + 3];
949 void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
950 ppc_avr_t *b, ppc_avr_t *c)
952 uint32_t prod[8];
953 int i;
955 for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
956 prod[i] = a->u16[i] * b->u16[i];
959 VECTOR_FOR_INORDER_I(i, u32) {
960 r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
964 void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
965 ppc_avr_t *b, ppc_avr_t *c)
967 uint32_t prod[8];
968 int i;
969 int sat = 0;
971 for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
972 prod[i] = a->u16[i] * b->u16[i];
975 VECTOR_FOR_INORDER_I(i, s32) {
976 uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
978 r->u32[i] = cvtuduw(t, &sat);
981 if (sat) {
982 env->vscr |= (1 << VSCR_SAT);
986 #define VMUL_DO(name, mul_element, prod_element, cast, evenp) \
987 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
989 int i; \
991 VECTOR_FOR_INORDER_I(i, prod_element) { \
992 if (evenp) { \
993 r->prod_element[i] = \
994 (cast)a->mul_element[i * 2 + HI_IDX] * \
995 (cast)b->mul_element[i * 2 + HI_IDX]; \
996 } else { \
997 r->prod_element[i] = \
998 (cast)a->mul_element[i * 2 + LO_IDX] * \
999 (cast)b->mul_element[i * 2 + LO_IDX]; \
1003 #define VMUL(suffix, mul_element, prod_element, cast) \
1004 VMUL_DO(mule##suffix, mul_element, prod_element, cast, 1) \
1005 VMUL_DO(mulo##suffix, mul_element, prod_element, cast, 0)
1006 VMUL(sb, s8, s16, int16_t)
1007 VMUL(sh, s16, s32, int32_t)
1008 VMUL(sw, s32, s64, int64_t)
1009 VMUL(ub, u8, u16, uint16_t)
1010 VMUL(uh, u16, u32, uint32_t)
1011 VMUL(uw, u32, u64, uint64_t)
1012 #undef VMUL_DO
1013 #undef VMUL
1015 void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1016 ppc_avr_t *c)
1018 ppc_avr_t result;
1019 int i;
1021 VECTOR_FOR_INORDER_I(i, u8) {
1022 int s = c->u8[i] & 0x1f;
1023 #if defined(HOST_WORDS_BIGENDIAN)
1024 int index = s & 0xf;
1025 #else
1026 int index = 15 - (s & 0xf);
1027 #endif
1029 if (s & 0x10) {
1030 result.u8[i] = b->u8[index];
1031 } else {
1032 result.u8[i] = a->u8[index];
1035 *r = result;
1038 #if defined(HOST_WORDS_BIGENDIAN)
1039 #define PKBIG 1
1040 #else
1041 #define PKBIG 0
1042 #endif
1043 void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1045 int i, j;
1046 ppc_avr_t result;
1047 #if defined(HOST_WORDS_BIGENDIAN)
1048 const ppc_avr_t *x[2] = { a, b };
1049 #else
1050 const ppc_avr_t *x[2] = { b, a };
1051 #endif
1053 VECTOR_FOR_INORDER_I(i, u64) {
1054 VECTOR_FOR_INORDER_I(j, u32) {
1055 uint32_t e = x[i]->u32[j];
1057 result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
1058 ((e >> 6) & 0x3e0) |
1059 ((e >> 3) & 0x1f));
1062 *r = result;
1065 #define VPK(suffix, from, to, cvt, dosat) \
1066 void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r, \
1067 ppc_avr_t *a, ppc_avr_t *b) \
1069 int i; \
1070 int sat = 0; \
1071 ppc_avr_t result; \
1072 ppc_avr_t *a0 = PKBIG ? a : b; \
1073 ppc_avr_t *a1 = PKBIG ? b : a; \
1075 VECTOR_FOR_INORDER_I(i, from) { \
1076 result.to[i] = cvt(a0->from[i], &sat); \
1077 result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat); \
1079 *r = result; \
1080 if (dosat && sat) { \
1081 env->vscr |= (1 << VSCR_SAT); \
1084 #define I(x, y) (x)
1085 VPK(shss, s16, s8, cvtshsb, 1)
1086 VPK(shus, s16, u8, cvtshub, 1)
1087 VPK(swss, s32, s16, cvtswsh, 1)
1088 VPK(swus, s32, u16, cvtswuh, 1)
1089 VPK(uhus, u16, u8, cvtuhub, 1)
1090 VPK(uwus, u32, u16, cvtuwuh, 1)
1091 VPK(uhum, u16, u8, I, 0)
1092 VPK(uwum, u32, u16, I, 0)
1093 #undef I
1094 #undef VPK
1095 #undef PKBIG
1097 void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1099 int i;
1101 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1102 r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
1106 #define VRFI(suffix, rounding) \
1107 void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r, \
1108 ppc_avr_t *b) \
1110 int i; \
1111 float_status s = env->vec_status; \
1113 set_float_rounding_mode(rounding, &s); \
1114 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
1115 r->f[i] = float32_round_to_int (b->f[i], &s); \
1118 VRFI(n, float_round_nearest_even)
1119 VRFI(m, float_round_down)
1120 VRFI(p, float_round_up)
1121 VRFI(z, float_round_to_zero)
1122 #undef VRFI
1124 #define VROTATE(suffix, element) \
1125 void helper_vrl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1127 int i; \
1129 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1130 unsigned int mask = ((1 << \
1131 (3 + (sizeof(a->element[0]) >> 1))) \
1132 - 1); \
1133 unsigned int shift = b->element[i] & mask; \
1134 r->element[i] = (a->element[i] << shift) | \
1135 (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
1138 VROTATE(b, u8)
1139 VROTATE(h, u16)
1140 VROTATE(w, u32)
1141 #undef VROTATE
1143 void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1145 int i;
1147 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1148 float32 t = float32_sqrt(b->f[i], &env->vec_status);
1150 r->f[i] = float32_div(float32_one, t, &env->vec_status);
1154 void helper_vsel(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1155 ppc_avr_t *c)
1157 r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
1158 r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
1161 void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1163 int i;
1165 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1166 r->f[i] = float32_exp2(b->f[i], &env->vec_status);
1170 void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1172 int i;
1174 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1175 r->f[i] = float32_log2(b->f[i], &env->vec_status);
1179 #if defined(HOST_WORDS_BIGENDIAN)
1180 #define LEFT 0
1181 #define RIGHT 1
1182 #else
1183 #define LEFT 1
1184 #define RIGHT 0
1185 #endif
1186 /* The specification says that the results are undefined if all of the
1187 * shift counts are not identical. We check to make sure that they are
1188 * to conform to what real hardware appears to do. */
1189 #define VSHIFT(suffix, leftp) \
1190 void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1192 int shift = b->u8[LO_IDX*15] & 0x7; \
1193 int doit = 1; \
1194 int i; \
1196 for (i = 0; i < ARRAY_SIZE(r->u8); i++) { \
1197 doit = doit && ((b->u8[i] & 0x7) == shift); \
1199 if (doit) { \
1200 if (shift == 0) { \
1201 *r = *a; \
1202 } else if (leftp) { \
1203 uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \
1205 r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \
1206 r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \
1207 } else { \
1208 uint64_t carry = a->u64[HI_IDX] << (64 - shift); \
1210 r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \
1211 r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \
1215 VSHIFT(l, LEFT)
1216 VSHIFT(r, RIGHT)
1217 #undef VSHIFT
1218 #undef LEFT
1219 #undef RIGHT
1221 #define VSL(suffix, element) \
1222 void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1224 int i; \
1226 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1227 unsigned int mask = ((1 << \
1228 (3 + (sizeof(a->element[0]) >> 1))) \
1229 - 1); \
1230 unsigned int shift = b->element[i] & mask; \
1232 r->element[i] = a->element[i] << shift; \
1235 VSL(b, u8)
1236 VSL(h, u16)
1237 VSL(w, u32)
1238 #undef VSL
1240 void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
1242 int sh = shift & 0xf;
1243 int i;
1244 ppc_avr_t result;
1246 #if defined(HOST_WORDS_BIGENDIAN)
1247 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1248 int index = sh + i;
1249 if (index > 0xf) {
1250 result.u8[i] = b->u8[index - 0x10];
1251 } else {
1252 result.u8[i] = a->u8[index];
1255 #else
1256 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1257 int index = (16 - sh) + i;
1258 if (index > 0xf) {
1259 result.u8[i] = a->u8[index - 0x10];
1260 } else {
1261 result.u8[i] = b->u8[index];
1264 #endif
1265 *r = result;
1268 void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1270 int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
1272 #if defined(HOST_WORDS_BIGENDIAN)
1273 memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1274 memset(&r->u8[16-sh], 0, sh);
1275 #else
1276 memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1277 memset(&r->u8[0], 0, sh);
1278 #endif
1281 /* Experimental testing shows that hardware masks the immediate. */
1282 #define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
1283 #if defined(HOST_WORDS_BIGENDIAN)
1284 #define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
1285 #else
1286 #define SPLAT_ELEMENT(element) \
1287 (ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element))
1288 #endif
1289 #define VSPLT(suffix, element) \
1290 void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
1292 uint32_t s = b->element[SPLAT_ELEMENT(element)]; \
1293 int i; \
1295 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1296 r->element[i] = s; \
1299 VSPLT(b, u8)
1300 VSPLT(h, u16)
1301 VSPLT(w, u32)
1302 #undef VSPLT
1303 #undef SPLAT_ELEMENT
1304 #undef _SPLAT_MASKED
1306 #define VSPLTI(suffix, element, splat_type) \
1307 void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
1309 splat_type x = (int8_t)(splat << 3) >> 3; \
1310 int i; \
1312 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1313 r->element[i] = x; \
1316 VSPLTI(b, s8, int8_t)
1317 VSPLTI(h, s16, int16_t)
1318 VSPLTI(w, s32, int32_t)
1319 #undef VSPLTI
1321 #define VSR(suffix, element) \
1322 void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1324 int i; \
1326 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1327 unsigned int mask = ((1 << \
1328 (3 + (sizeof(a->element[0]) >> 1))) \
1329 - 1); \
1330 unsigned int shift = b->element[i] & mask; \
1332 r->element[i] = a->element[i] >> shift; \
1335 VSR(ab, s8)
1336 VSR(ah, s16)
1337 VSR(aw, s32)
1338 VSR(b, u8)
1339 VSR(h, u16)
1340 VSR(w, u32)
1341 #undef VSR
1343 void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1345 int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf;
1347 #if defined(HOST_WORDS_BIGENDIAN)
1348 memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1349 memset(&r->u8[0], 0, sh);
1350 #else
1351 memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1352 memset(&r->u8[16 - sh], 0, sh);
1353 #endif
1356 void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1358 int i;
1360 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1361 r->u32[i] = a->u32[i] >= b->u32[i];
1365 void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1367 int64_t t;
1368 int i, upper;
1369 ppc_avr_t result;
1370 int sat = 0;
1372 #if defined(HOST_WORDS_BIGENDIAN)
1373 upper = ARRAY_SIZE(r->s32)-1;
1374 #else
1375 upper = 0;
1376 #endif
1377 t = (int64_t)b->s32[upper];
1378 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1379 t += a->s32[i];
1380 result.s32[i] = 0;
1382 result.s32[upper] = cvtsdsw(t, &sat);
1383 *r = result;
1385 if (sat) {
1386 env->vscr |= (1 << VSCR_SAT);
1390 void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1392 int i, j, upper;
1393 ppc_avr_t result;
1394 int sat = 0;
1396 #if defined(HOST_WORDS_BIGENDIAN)
1397 upper = 1;
1398 #else
1399 upper = 0;
1400 #endif
1401 for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1402 int64_t t = (int64_t)b->s32[upper + i * 2];
1404 result.u64[i] = 0;
1405 for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
1406 t += a->s32[2 * i + j];
1408 result.s32[upper + i * 2] = cvtsdsw(t, &sat);
1411 *r = result;
1412 if (sat) {
1413 env->vscr |= (1 << VSCR_SAT);
1417 void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1419 int i, j;
1420 int sat = 0;
1422 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1423 int64_t t = (int64_t)b->s32[i];
1425 for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
1426 t += a->s8[4 * i + j];
1428 r->s32[i] = cvtsdsw(t, &sat);
1431 if (sat) {
1432 env->vscr |= (1 << VSCR_SAT);
1436 void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1438 int sat = 0;
1439 int i;
1441 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1442 int64_t t = (int64_t)b->s32[i];
1444 t += a->s16[2 * i] + a->s16[2 * i + 1];
1445 r->s32[i] = cvtsdsw(t, &sat);
1448 if (sat) {
1449 env->vscr |= (1 << VSCR_SAT);
1453 void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1455 int i, j;
1456 int sat = 0;
1458 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1459 uint64_t t = (uint64_t)b->u32[i];
1461 for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
1462 t += a->u8[4 * i + j];
1464 r->u32[i] = cvtuduw(t, &sat);
1467 if (sat) {
1468 env->vscr |= (1 << VSCR_SAT);
1472 #if defined(HOST_WORDS_BIGENDIAN)
1473 #define UPKHI 1
1474 #define UPKLO 0
1475 #else
1476 #define UPKHI 0
1477 #define UPKLO 1
1478 #endif
1479 #define VUPKPX(suffix, hi) \
1480 void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \
1482 int i; \
1483 ppc_avr_t result; \
1485 for (i = 0; i < ARRAY_SIZE(r->u32); i++) { \
1486 uint16_t e = b->u16[hi ? i : i+4]; \
1487 uint8_t a = (e >> 15) ? 0xff : 0; \
1488 uint8_t r = (e >> 10) & 0x1f; \
1489 uint8_t g = (e >> 5) & 0x1f; \
1490 uint8_t b = e & 0x1f; \
1492 result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b; \
1494 *r = result; \
1496 VUPKPX(lpx, UPKLO)
1497 VUPKPX(hpx, UPKHI)
1498 #undef VUPKPX
1500 #define VUPK(suffix, unpacked, packee, hi) \
1501 void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \
1503 int i; \
1504 ppc_avr_t result; \
1506 if (hi) { \
1507 for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) { \
1508 result.unpacked[i] = b->packee[i]; \
1510 } else { \
1511 for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
1512 i++) { \
1513 result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
1516 *r = result; \
1518 VUPK(hsb, s16, s8, UPKHI)
1519 VUPK(hsh, s32, s16, UPKHI)
1520 VUPK(lsb, s16, s8, UPKLO)
1521 VUPK(lsh, s32, s16, UPKLO)
1522 #undef VUPK
1523 #undef UPKHI
1524 #undef UPKLO
1526 #undef VECTOR_FOR_INORDER_I
1527 #undef HI_IDX
1528 #undef LO_IDX
1530 /*****************************************************************************/
1531 /* SPE extension helpers */
1532 /* Use a table to make this quicker */
1533 static const uint8_t hbrev[16] = {
1534 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1535 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1538 static inline uint8_t byte_reverse(uint8_t val)
1540 return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1543 static inline uint32_t word_reverse(uint32_t val)
1545 return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1546 (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1549 #define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
1550 target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
1552 uint32_t a, b, d, mask;
1554 mask = UINT32_MAX >> (32 - MASKBITS);
1555 a = arg1 & mask;
1556 b = arg2 & mask;
1557 d = word_reverse(1 + word_reverse(a | ~b));
1558 return (arg1 & ~mask) | (d & b);
1561 uint32_t helper_cntlsw32(uint32_t val)
1563 if (val & 0x80000000) {
1564 return clz32(~val);
1565 } else {
1566 return clz32(val);
1570 uint32_t helper_cntlzw32(uint32_t val)
1572 return clz32(val);
1575 /* 440 specific */
1576 target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high,
1577 target_ulong low, uint32_t update_Rc)
1579 target_ulong mask;
1580 int i;
1582 i = 1;
1583 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1584 if ((high & mask) == 0) {
1585 if (update_Rc) {
1586 env->crf[0] = 0x4;
1588 goto done;
1590 i++;
1592 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1593 if ((low & mask) == 0) {
1594 if (update_Rc) {
1595 env->crf[0] = 0x8;
1597 goto done;
1599 i++;
1601 if (update_Rc) {
1602 env->crf[0] = 0x2;
1604 done:
1605 env->xer = (env->xer & ~0x7F) | i;
1606 if (update_Rc) {
1607 env->crf[0] |= xer_so;
1609 return i;