target-ppc: Add ISA2.06 divdeu[o] Instructions
[qemu-kvm.git] / target-ppc / int_helper.c
blob6f3d8fd805cbc3e8322b543bd5ef489eb8752881
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 #if defined(TARGET_PPC64)
46 uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe)
48 uint64_t rt = 0;
49 int overflow = 0;
51 overflow = divu128(&rt, &ra, rb);
53 if (unlikely(overflow)) {
54 rt = 0; /* Undefined */
57 if (oe) {
58 if (unlikely(overflow)) {
59 env->so = env->ov = 1;
60 } else {
61 env->ov = 0;
65 return rt;
68 #endif
71 target_ulong helper_cntlzw(target_ulong t)
73 return clz32(t);
76 #if defined(TARGET_PPC64)
77 target_ulong helper_cntlzd(target_ulong t)
79 return clz64(t);
81 #endif
83 #if defined(TARGET_PPC64)
85 uint64_t helper_bpermd(uint64_t rs, uint64_t rb)
87 int i;
88 uint64_t ra = 0;
90 for (i = 0; i < 8; i++) {
91 int index = (rs >> (i*8)) & 0xFF;
92 if (index < 64) {
93 if (rb & (1ull << (63-index))) {
94 ra |= 1 << i;
98 return ra;
101 #endif
103 target_ulong helper_cmpb(target_ulong rs, target_ulong rb)
105 target_ulong mask = 0xff;
106 target_ulong ra = 0;
107 int i;
109 for (i = 0; i < sizeof(target_ulong); i++) {
110 if ((rs & mask) == (rb & mask)) {
111 ra |= mask;
113 mask <<= 8;
115 return ra;
118 /* shift right arithmetic helper */
119 target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
120 target_ulong shift)
122 int32_t ret;
124 if (likely(!(shift & 0x20))) {
125 if (likely((uint32_t)shift != 0)) {
126 shift &= 0x1f;
127 ret = (int32_t)value >> shift;
128 if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
129 env->ca = 0;
130 } else {
131 env->ca = 1;
133 } else {
134 ret = (int32_t)value;
135 env->ca = 0;
137 } else {
138 ret = (int32_t)value >> 31;
139 env->ca = (ret != 0);
141 return (target_long)ret;
144 #if defined(TARGET_PPC64)
145 target_ulong helper_srad(CPUPPCState *env, target_ulong value,
146 target_ulong shift)
148 int64_t ret;
150 if (likely(!(shift & 0x40))) {
151 if (likely((uint64_t)shift != 0)) {
152 shift &= 0x3f;
153 ret = (int64_t)value >> shift;
154 if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
155 env->ca = 0;
156 } else {
157 env->ca = 1;
159 } else {
160 ret = (int64_t)value;
161 env->ca = 0;
163 } else {
164 ret = (int64_t)value >> 63;
165 env->ca = (ret != 0);
167 return ret;
169 #endif
171 #if defined(TARGET_PPC64)
172 target_ulong helper_popcntb(target_ulong val)
174 val = (val & 0x5555555555555555ULL) + ((val >> 1) &
175 0x5555555555555555ULL);
176 val = (val & 0x3333333333333333ULL) + ((val >> 2) &
177 0x3333333333333333ULL);
178 val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) &
179 0x0f0f0f0f0f0f0f0fULL);
180 return val;
183 target_ulong helper_popcntw(target_ulong val)
185 val = (val & 0x5555555555555555ULL) + ((val >> 1) &
186 0x5555555555555555ULL);
187 val = (val & 0x3333333333333333ULL) + ((val >> 2) &
188 0x3333333333333333ULL);
189 val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) &
190 0x0f0f0f0f0f0f0f0fULL);
191 val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) &
192 0x00ff00ff00ff00ffULL);
193 val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
194 0x0000ffff0000ffffULL);
195 return val;
198 target_ulong helper_popcntd(target_ulong val)
200 return ctpop64(val);
202 #else
203 target_ulong helper_popcntb(target_ulong val)
205 val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
206 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
207 val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
208 return val;
211 target_ulong helper_popcntw(target_ulong val)
213 val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
214 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
215 val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
216 val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff);
217 val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
218 return val;
220 #endif
222 /*****************************************************************************/
223 /* PowerPC 601 specific instructions (POWER bridge) */
224 target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
226 uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
228 if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
229 (int32_t)arg2 == 0) {
230 env->spr[SPR_MQ] = 0;
231 return INT32_MIN;
232 } else {
233 env->spr[SPR_MQ] = tmp % arg2;
234 return tmp / (int32_t)arg2;
238 target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
239 target_ulong arg2)
241 uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
243 if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
244 (int32_t)arg2 == 0) {
245 env->so = env->ov = 1;
246 env->spr[SPR_MQ] = 0;
247 return INT32_MIN;
248 } else {
249 env->spr[SPR_MQ] = tmp % arg2;
250 tmp /= (int32_t)arg2;
251 if ((int32_t)tmp != tmp) {
252 env->so = env->ov = 1;
253 } else {
254 env->ov = 0;
256 return tmp;
260 target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
261 target_ulong arg2)
263 if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
264 (int32_t)arg2 == 0) {
265 env->spr[SPR_MQ] = 0;
266 return INT32_MIN;
267 } else {
268 env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
269 return (int32_t)arg1 / (int32_t)arg2;
273 target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
274 target_ulong arg2)
276 if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
277 (int32_t)arg2 == 0) {
278 env->so = env->ov = 1;
279 env->spr[SPR_MQ] = 0;
280 return INT32_MIN;
281 } else {
282 env->ov = 0;
283 env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
284 return (int32_t)arg1 / (int32_t)arg2;
288 /*****************************************************************************/
289 /* 602 specific instructions */
290 /* mfrom is the most crazy instruction ever seen, imho ! */
291 /* Real implementation uses a ROM table. Do the same */
292 /* Extremely decomposed:
293 * -arg / 256
294 * return 256 * log10(10 + 1.0) + 0.5
296 #if !defined(CONFIG_USER_ONLY)
297 target_ulong helper_602_mfrom(target_ulong arg)
299 if (likely(arg < 602)) {
300 #include "mfrom_table.c"
301 return mfrom_ROM_table[arg];
302 } else {
303 return 0;
306 #endif
308 /*****************************************************************************/
309 /* Altivec extension helpers */
310 #if defined(HOST_WORDS_BIGENDIAN)
311 #define HI_IDX 0
312 #define LO_IDX 1
313 #else
314 #define HI_IDX 1
315 #define LO_IDX 0
316 #endif
318 #if defined(HOST_WORDS_BIGENDIAN)
319 #define VECTOR_FOR_INORDER_I(index, element) \
320 for (index = 0; index < ARRAY_SIZE(r->element); index++)
321 #else
322 #define VECTOR_FOR_INORDER_I(index, element) \
323 for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
324 #endif
326 /* Saturating arithmetic helpers. */
327 #define SATCVT(from, to, from_type, to_type, min, max) \
328 static inline to_type cvt##from##to(from_type x, int *sat) \
330 to_type r; \
332 if (x < (from_type)min) { \
333 r = min; \
334 *sat = 1; \
335 } else if (x > (from_type)max) { \
336 r = max; \
337 *sat = 1; \
338 } else { \
339 r = x; \
341 return r; \
343 #define SATCVTU(from, to, from_type, to_type, min, max) \
344 static inline to_type cvt##from##to(from_type x, int *sat) \
346 to_type r; \
348 if (x > (from_type)max) { \
349 r = max; \
350 *sat = 1; \
351 } else { \
352 r = x; \
354 return r; \
356 SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX)
357 SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX)
358 SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX)
360 SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX)
361 SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX)
362 SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX)
363 SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX)
364 SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX)
365 SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
366 #undef SATCVT
367 #undef SATCVTU
369 void helper_lvsl(ppc_avr_t *r, target_ulong sh)
371 int i, j = (sh & 0xf);
373 VECTOR_FOR_INORDER_I(i, u8) {
374 r->u8[i] = j++;
378 void helper_lvsr(ppc_avr_t *r, target_ulong sh)
380 int i, j = 0x10 - (sh & 0xf);
382 VECTOR_FOR_INORDER_I(i, u8) {
383 r->u8[i] = j++;
387 void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
389 #if defined(HOST_WORDS_BIGENDIAN)
390 env->vscr = r->u32[3];
391 #else
392 env->vscr = r->u32[0];
393 #endif
394 set_flush_to_zero(vscr_nj, &env->vec_status);
397 void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
399 int i;
401 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
402 r->u32[i] = ~a->u32[i] < b->u32[i];
406 #define VARITH_DO(name, op, element) \
407 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
409 int i; \
411 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
412 r->element[i] = a->element[i] op b->element[i]; \
415 #define VARITH(suffix, element) \
416 VARITH_DO(add##suffix, +, element) \
417 VARITH_DO(sub##suffix, -, element)
418 VARITH(ubm, u8)
419 VARITH(uhm, u16)
420 VARITH(uwm, u32)
421 #undef VARITH_DO
422 #undef VARITH
424 #define VARITHFP(suffix, func) \
425 void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
426 ppc_avr_t *b) \
428 int i; \
430 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
431 r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
434 VARITHFP(addfp, float32_add)
435 VARITHFP(subfp, float32_sub)
436 VARITHFP(minfp, float32_min)
437 VARITHFP(maxfp, float32_max)
438 #undef VARITHFP
440 #define VARITHFPFMA(suffix, type) \
441 void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
442 ppc_avr_t *b, ppc_avr_t *c) \
444 int i; \
445 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
446 r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i], \
447 type, &env->vec_status); \
450 VARITHFPFMA(maddfp, 0);
451 VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
452 #undef VARITHFPFMA
454 #define VARITHSAT_CASE(type, op, cvt, element) \
456 type result = (type)a->element[i] op (type)b->element[i]; \
457 r->element[i] = cvt(result, &sat); \
460 #define VARITHSAT_DO(name, op, optype, cvt, element) \
461 void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
462 ppc_avr_t *b) \
464 int sat = 0; \
465 int i; \
467 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
468 switch (sizeof(r->element[0])) { \
469 case 1: \
470 VARITHSAT_CASE(optype, op, cvt, element); \
471 break; \
472 case 2: \
473 VARITHSAT_CASE(optype, op, cvt, element); \
474 break; \
475 case 4: \
476 VARITHSAT_CASE(optype, op, cvt, element); \
477 break; \
480 if (sat) { \
481 env->vscr |= (1 << VSCR_SAT); \
484 #define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
485 VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element) \
486 VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
487 #define VARITHSAT_UNSIGNED(suffix, element, optype, cvt) \
488 VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element) \
489 VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
490 VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
491 VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
492 VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
493 VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
494 VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
495 VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
496 #undef VARITHSAT_CASE
497 #undef VARITHSAT_DO
498 #undef VARITHSAT_SIGNED
499 #undef VARITHSAT_UNSIGNED
501 #define VAVG_DO(name, element, etype) \
502 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
504 int i; \
506 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
507 etype x = (etype)a->element[i] + (etype)b->element[i] + 1; \
508 r->element[i] = x >> 1; \
512 #define VAVG(type, signed_element, signed_type, unsigned_element, \
513 unsigned_type) \
514 VAVG_DO(avgs##type, signed_element, signed_type) \
515 VAVG_DO(avgu##type, unsigned_element, unsigned_type)
516 VAVG(b, s8, int16_t, u8, uint16_t)
517 VAVG(h, s16, int32_t, u16, uint32_t)
518 VAVG(w, s32, int64_t, u32, uint64_t)
519 #undef VAVG_DO
520 #undef VAVG
522 #define VCF(suffix, cvt, element) \
523 void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r, \
524 ppc_avr_t *b, uint32_t uim) \
526 int i; \
528 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
529 float32 t = cvt(b->element[i], &env->vec_status); \
530 r->f[i] = float32_scalbn(t, -uim, &env->vec_status); \
533 VCF(ux, uint32_to_float32, u32)
534 VCF(sx, int32_to_float32, s32)
535 #undef VCF
537 #define VCMP_DO(suffix, compare, element, record) \
538 void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
539 ppc_avr_t *a, ppc_avr_t *b) \
541 uint32_t ones = (uint32_t)-1; \
542 uint32_t all = ones; \
543 uint32_t none = 0; \
544 int i; \
546 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
547 uint32_t result = (a->element[i] compare b->element[i] ? \
548 ones : 0x0); \
549 switch (sizeof(a->element[0])) { \
550 case 4: \
551 r->u32[i] = result; \
552 break; \
553 case 2: \
554 r->u16[i] = result; \
555 break; \
556 case 1: \
557 r->u8[i] = result; \
558 break; \
560 all &= result; \
561 none |= result; \
563 if (record) { \
564 env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
567 #define VCMP(suffix, compare, element) \
568 VCMP_DO(suffix, compare, element, 0) \
569 VCMP_DO(suffix##_dot, compare, element, 1)
570 VCMP(equb, ==, u8)
571 VCMP(equh, ==, u16)
572 VCMP(equw, ==, u32)
573 VCMP(gtub, >, u8)
574 VCMP(gtuh, >, u16)
575 VCMP(gtuw, >, u32)
576 VCMP(gtsb, >, s8)
577 VCMP(gtsh, >, s16)
578 VCMP(gtsw, >, s32)
579 #undef VCMP_DO
580 #undef VCMP
582 #define VCMPFP_DO(suffix, compare, order, record) \
583 void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
584 ppc_avr_t *a, ppc_avr_t *b) \
586 uint32_t ones = (uint32_t)-1; \
587 uint32_t all = ones; \
588 uint32_t none = 0; \
589 int i; \
591 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
592 uint32_t result; \
593 int rel = float32_compare_quiet(a->f[i], b->f[i], \
594 &env->vec_status); \
595 if (rel == float_relation_unordered) { \
596 result = 0; \
597 } else if (rel compare order) { \
598 result = ones; \
599 } else { \
600 result = 0; \
602 r->u32[i] = result; \
603 all &= result; \
604 none |= result; \
606 if (record) { \
607 env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
610 #define VCMPFP(suffix, compare, order) \
611 VCMPFP_DO(suffix, compare, order, 0) \
612 VCMPFP_DO(suffix##_dot, compare, order, 1)
613 VCMPFP(eqfp, ==, float_relation_equal)
614 VCMPFP(gefp, !=, float_relation_less)
615 VCMPFP(gtfp, ==, float_relation_greater)
616 #undef VCMPFP_DO
617 #undef VCMPFP
619 static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r,
620 ppc_avr_t *a, ppc_avr_t *b, int record)
622 int i;
623 int all_in = 0;
625 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
626 int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
627 if (le_rel == float_relation_unordered) {
628 r->u32[i] = 0xc0000000;
629 /* ALL_IN does not need to be updated here. */
630 } else {
631 float32 bneg = float32_chs(b->f[i]);
632 int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
633 int le = le_rel != float_relation_greater;
634 int ge = ge_rel != float_relation_less;
636 r->u32[i] = ((!le) << 31) | ((!ge) << 30);
637 all_in |= (!le | !ge);
640 if (record) {
641 env->crf[6] = (all_in == 0) << 1;
645 void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
647 vcmpbfp_internal(env, r, a, b, 0);
650 void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
651 ppc_avr_t *b)
653 vcmpbfp_internal(env, r, a, b, 1);
656 #define VCT(suffix, satcvt, element) \
657 void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r, \
658 ppc_avr_t *b, uint32_t uim) \
660 int i; \
661 int sat = 0; \
662 float_status s = env->vec_status; \
664 set_float_rounding_mode(float_round_to_zero, &s); \
665 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
666 if (float32_is_any_nan(b->f[i])) { \
667 r->element[i] = 0; \
668 } else { \
669 float64 t = float32_to_float64(b->f[i], &s); \
670 int64_t j; \
672 t = float64_scalbn(t, uim, &s); \
673 j = float64_to_int64(t, &s); \
674 r->element[i] = satcvt(j, &sat); \
677 if (sat) { \
678 env->vscr |= (1 << VSCR_SAT); \
681 VCT(uxs, cvtsduw, u32)
682 VCT(sxs, cvtsdsw, s32)
683 #undef VCT
685 void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
686 ppc_avr_t *b, ppc_avr_t *c)
688 int sat = 0;
689 int i;
691 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
692 int32_t prod = a->s16[i] * b->s16[i];
693 int32_t t = (int32_t)c->s16[i] + (prod >> 15);
695 r->s16[i] = cvtswsh(t, &sat);
698 if (sat) {
699 env->vscr |= (1 << VSCR_SAT);
703 void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
704 ppc_avr_t *b, ppc_avr_t *c)
706 int sat = 0;
707 int i;
709 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
710 int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
711 int32_t t = (int32_t)c->s16[i] + (prod >> 15);
712 r->s16[i] = cvtswsh(t, &sat);
715 if (sat) {
716 env->vscr |= (1 << VSCR_SAT);
720 #define VMINMAX_DO(name, compare, element) \
721 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
723 int i; \
725 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
726 if (a->element[i] compare b->element[i]) { \
727 r->element[i] = b->element[i]; \
728 } else { \
729 r->element[i] = a->element[i]; \
733 #define VMINMAX(suffix, element) \
734 VMINMAX_DO(min##suffix, >, element) \
735 VMINMAX_DO(max##suffix, <, element)
736 VMINMAX(sb, s8)
737 VMINMAX(sh, s16)
738 VMINMAX(sw, s32)
739 VMINMAX(ub, u8)
740 VMINMAX(uh, u16)
741 VMINMAX(uw, u32)
742 #undef VMINMAX_DO
743 #undef VMINMAX
745 void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
747 int i;
749 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
750 int32_t prod = a->s16[i] * b->s16[i];
751 r->s16[i] = (int16_t) (prod + c->s16[i]);
755 #define VMRG_DO(name, element, highp) \
756 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
758 ppc_avr_t result; \
759 int i; \
760 size_t n_elems = ARRAY_SIZE(r->element); \
762 for (i = 0; i < n_elems / 2; i++) { \
763 if (highp) { \
764 result.element[i*2+HI_IDX] = a->element[i]; \
765 result.element[i*2+LO_IDX] = b->element[i]; \
766 } else { \
767 result.element[n_elems - i * 2 - (1 + HI_IDX)] = \
768 b->element[n_elems - i - 1]; \
769 result.element[n_elems - i * 2 - (1 + LO_IDX)] = \
770 a->element[n_elems - i - 1]; \
773 *r = result; \
775 #if defined(HOST_WORDS_BIGENDIAN)
776 #define MRGHI 0
777 #define MRGLO 1
778 #else
779 #define MRGHI 1
780 #define MRGLO 0
781 #endif
782 #define VMRG(suffix, element) \
783 VMRG_DO(mrgl##suffix, element, MRGHI) \
784 VMRG_DO(mrgh##suffix, element, MRGLO)
785 VMRG(b, u8)
786 VMRG(h, u16)
787 VMRG(w, u32)
788 #undef VMRG_DO
789 #undef VMRG
790 #undef MRGHI
791 #undef MRGLO
793 void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
794 ppc_avr_t *b, ppc_avr_t *c)
796 int32_t prod[16];
797 int i;
799 for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
800 prod[i] = (int32_t)a->s8[i] * b->u8[i];
803 VECTOR_FOR_INORDER_I(i, s32) {
804 r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
805 prod[4 * i + 2] + prod[4 * i + 3];
809 void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
810 ppc_avr_t *b, ppc_avr_t *c)
812 int32_t prod[8];
813 int i;
815 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
816 prod[i] = a->s16[i] * b->s16[i];
819 VECTOR_FOR_INORDER_I(i, s32) {
820 r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
824 void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
825 ppc_avr_t *b, ppc_avr_t *c)
827 int32_t prod[8];
828 int i;
829 int sat = 0;
831 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
832 prod[i] = (int32_t)a->s16[i] * b->s16[i];
835 VECTOR_FOR_INORDER_I(i, s32) {
836 int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
838 r->u32[i] = cvtsdsw(t, &sat);
841 if (sat) {
842 env->vscr |= (1 << VSCR_SAT);
846 void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
847 ppc_avr_t *b, ppc_avr_t *c)
849 uint16_t prod[16];
850 int i;
852 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
853 prod[i] = a->u8[i] * b->u8[i];
856 VECTOR_FOR_INORDER_I(i, u32) {
857 r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
858 prod[4 * i + 2] + prod[4 * i + 3];
862 void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
863 ppc_avr_t *b, ppc_avr_t *c)
865 uint32_t prod[8];
866 int i;
868 for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
869 prod[i] = a->u16[i] * b->u16[i];
872 VECTOR_FOR_INORDER_I(i, u32) {
873 r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
877 void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
878 ppc_avr_t *b, ppc_avr_t *c)
880 uint32_t prod[8];
881 int i;
882 int sat = 0;
884 for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
885 prod[i] = a->u16[i] * b->u16[i];
888 VECTOR_FOR_INORDER_I(i, s32) {
889 uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
891 r->u32[i] = cvtuduw(t, &sat);
894 if (sat) {
895 env->vscr |= (1 << VSCR_SAT);
899 #define VMUL_DO(name, mul_element, prod_element, evenp) \
900 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
902 int i; \
904 VECTOR_FOR_INORDER_I(i, prod_element) { \
905 if (evenp) { \
906 r->prod_element[i] = a->mul_element[i * 2 + HI_IDX] * \
907 b->mul_element[i * 2 + HI_IDX]; \
908 } else { \
909 r->prod_element[i] = a->mul_element[i * 2 + LO_IDX] * \
910 b->mul_element[i * 2 + LO_IDX]; \
914 #define VMUL(suffix, mul_element, prod_element) \
915 VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
916 VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
917 VMUL(sb, s8, s16)
918 VMUL(sh, s16, s32)
919 VMUL(ub, u8, u16)
920 VMUL(uh, u16, u32)
921 #undef VMUL_DO
922 #undef VMUL
924 void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
925 ppc_avr_t *c)
927 ppc_avr_t result;
928 int i;
930 VECTOR_FOR_INORDER_I(i, u8) {
931 int s = c->u8[i] & 0x1f;
932 #if defined(HOST_WORDS_BIGENDIAN)
933 int index = s & 0xf;
934 #else
935 int index = 15 - (s & 0xf);
936 #endif
938 if (s & 0x10) {
939 result.u8[i] = b->u8[index];
940 } else {
941 result.u8[i] = a->u8[index];
944 *r = result;
947 #if defined(HOST_WORDS_BIGENDIAN)
948 #define PKBIG 1
949 #else
950 #define PKBIG 0
951 #endif
952 void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
954 int i, j;
955 ppc_avr_t result;
956 #if defined(HOST_WORDS_BIGENDIAN)
957 const ppc_avr_t *x[2] = { a, b };
958 #else
959 const ppc_avr_t *x[2] = { b, a };
960 #endif
962 VECTOR_FOR_INORDER_I(i, u64) {
963 VECTOR_FOR_INORDER_I(j, u32) {
964 uint32_t e = x[i]->u32[j];
966 result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
967 ((e >> 6) & 0x3e0) |
968 ((e >> 3) & 0x1f));
971 *r = result;
974 #define VPK(suffix, from, to, cvt, dosat) \
975 void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r, \
976 ppc_avr_t *a, ppc_avr_t *b) \
978 int i; \
979 int sat = 0; \
980 ppc_avr_t result; \
981 ppc_avr_t *a0 = PKBIG ? a : b; \
982 ppc_avr_t *a1 = PKBIG ? b : a; \
984 VECTOR_FOR_INORDER_I(i, from) { \
985 result.to[i] = cvt(a0->from[i], &sat); \
986 result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat); \
988 *r = result; \
989 if (dosat && sat) { \
990 env->vscr |= (1 << VSCR_SAT); \
993 #define I(x, y) (x)
994 VPK(shss, s16, s8, cvtshsb, 1)
995 VPK(shus, s16, u8, cvtshub, 1)
996 VPK(swss, s32, s16, cvtswsh, 1)
997 VPK(swus, s32, u16, cvtswuh, 1)
998 VPK(uhus, u16, u8, cvtuhub, 1)
999 VPK(uwus, u32, u16, cvtuwuh, 1)
1000 VPK(uhum, u16, u8, I, 0)
1001 VPK(uwum, u32, u16, I, 0)
1002 #undef I
1003 #undef VPK
1004 #undef PKBIG
1006 void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1008 int i;
1010 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1011 r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
1015 #define VRFI(suffix, rounding) \
1016 void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r, \
1017 ppc_avr_t *b) \
1019 int i; \
1020 float_status s = env->vec_status; \
1022 set_float_rounding_mode(rounding, &s); \
1023 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
1024 r->f[i] = float32_round_to_int (b->f[i], &s); \
1027 VRFI(n, float_round_nearest_even)
1028 VRFI(m, float_round_down)
1029 VRFI(p, float_round_up)
1030 VRFI(z, float_round_to_zero)
1031 #undef VRFI
1033 #define VROTATE(suffix, element) \
1034 void helper_vrl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1036 int i; \
1038 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1039 unsigned int mask = ((1 << \
1040 (3 + (sizeof(a->element[0]) >> 1))) \
1041 - 1); \
1042 unsigned int shift = b->element[i] & mask; \
1043 r->element[i] = (a->element[i] << shift) | \
1044 (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
1047 VROTATE(b, u8)
1048 VROTATE(h, u16)
1049 VROTATE(w, u32)
1050 #undef VROTATE
1052 void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1054 int i;
1056 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1057 float32 t = float32_sqrt(b->f[i], &env->vec_status);
1059 r->f[i] = float32_div(float32_one, t, &env->vec_status);
1063 void helper_vsel(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1064 ppc_avr_t *c)
1066 r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
1067 r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
1070 void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1072 int i;
1074 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1075 r->f[i] = float32_exp2(b->f[i], &env->vec_status);
1079 void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1081 int i;
1083 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1084 r->f[i] = float32_log2(b->f[i], &env->vec_status);
1088 #if defined(HOST_WORDS_BIGENDIAN)
1089 #define LEFT 0
1090 #define RIGHT 1
1091 #else
1092 #define LEFT 1
1093 #define RIGHT 0
1094 #endif
1095 /* The specification says that the results are undefined if all of the
1096 * shift counts are not identical. We check to make sure that they are
1097 * to conform to what real hardware appears to do. */
1098 #define VSHIFT(suffix, leftp) \
1099 void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1101 int shift = b->u8[LO_IDX*15] & 0x7; \
1102 int doit = 1; \
1103 int i; \
1105 for (i = 0; i < ARRAY_SIZE(r->u8); i++) { \
1106 doit = doit && ((b->u8[i] & 0x7) == shift); \
1108 if (doit) { \
1109 if (shift == 0) { \
1110 *r = *a; \
1111 } else if (leftp) { \
1112 uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \
1114 r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \
1115 r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \
1116 } else { \
1117 uint64_t carry = a->u64[HI_IDX] << (64 - shift); \
1119 r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \
1120 r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \
1124 VSHIFT(l, LEFT)
1125 VSHIFT(r, RIGHT)
1126 #undef VSHIFT
1127 #undef LEFT
1128 #undef RIGHT
1130 #define VSL(suffix, element) \
1131 void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1133 int i; \
1135 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1136 unsigned int mask = ((1 << \
1137 (3 + (sizeof(a->element[0]) >> 1))) \
1138 - 1); \
1139 unsigned int shift = b->element[i] & mask; \
1141 r->element[i] = a->element[i] << shift; \
1144 VSL(b, u8)
1145 VSL(h, u16)
1146 VSL(w, u32)
1147 #undef VSL
1149 void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
1151 int sh = shift & 0xf;
1152 int i;
1153 ppc_avr_t result;
1155 #if defined(HOST_WORDS_BIGENDIAN)
1156 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1157 int index = sh + i;
1158 if (index > 0xf) {
1159 result.u8[i] = b->u8[index - 0x10];
1160 } else {
1161 result.u8[i] = a->u8[index];
1164 #else
1165 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1166 int index = (16 - sh) + i;
1167 if (index > 0xf) {
1168 result.u8[i] = a->u8[index - 0x10];
1169 } else {
1170 result.u8[i] = b->u8[index];
1173 #endif
1174 *r = result;
1177 void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1179 int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
1181 #if defined(HOST_WORDS_BIGENDIAN)
1182 memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1183 memset(&r->u8[16-sh], 0, sh);
1184 #else
1185 memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1186 memset(&r->u8[0], 0, sh);
1187 #endif
1190 /* Experimental testing shows that hardware masks the immediate. */
1191 #define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
1192 #if defined(HOST_WORDS_BIGENDIAN)
1193 #define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
1194 #else
1195 #define SPLAT_ELEMENT(element) \
1196 (ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element))
1197 #endif
1198 #define VSPLT(suffix, element) \
1199 void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
1201 uint32_t s = b->element[SPLAT_ELEMENT(element)]; \
1202 int i; \
1204 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1205 r->element[i] = s; \
1208 VSPLT(b, u8)
1209 VSPLT(h, u16)
1210 VSPLT(w, u32)
1211 #undef VSPLT
1212 #undef SPLAT_ELEMENT
1213 #undef _SPLAT_MASKED
1215 #define VSPLTI(suffix, element, splat_type) \
1216 void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
1218 splat_type x = (int8_t)(splat << 3) >> 3; \
1219 int i; \
1221 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1222 r->element[i] = x; \
1225 VSPLTI(b, s8, int8_t)
1226 VSPLTI(h, s16, int16_t)
1227 VSPLTI(w, s32, int32_t)
1228 #undef VSPLTI
1230 #define VSR(suffix, element) \
1231 void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1233 int i; \
1235 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1236 unsigned int mask = ((1 << \
1237 (3 + (sizeof(a->element[0]) >> 1))) \
1238 - 1); \
1239 unsigned int shift = b->element[i] & mask; \
1241 r->element[i] = a->element[i] >> shift; \
1244 VSR(ab, s8)
1245 VSR(ah, s16)
1246 VSR(aw, s32)
1247 VSR(b, u8)
1248 VSR(h, u16)
1249 VSR(w, u32)
1250 #undef VSR
1252 void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1254 int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf;
1256 #if defined(HOST_WORDS_BIGENDIAN)
1257 memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1258 memset(&r->u8[0], 0, sh);
1259 #else
1260 memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1261 memset(&r->u8[16 - sh], 0, sh);
1262 #endif
1265 void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1267 int i;
1269 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1270 r->u32[i] = a->u32[i] >= b->u32[i];
1274 void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1276 int64_t t;
1277 int i, upper;
1278 ppc_avr_t result;
1279 int sat = 0;
1281 #if defined(HOST_WORDS_BIGENDIAN)
1282 upper = ARRAY_SIZE(r->s32)-1;
1283 #else
1284 upper = 0;
1285 #endif
1286 t = (int64_t)b->s32[upper];
1287 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1288 t += a->s32[i];
1289 result.s32[i] = 0;
1291 result.s32[upper] = cvtsdsw(t, &sat);
1292 *r = result;
1294 if (sat) {
1295 env->vscr |= (1 << VSCR_SAT);
1299 void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1301 int i, j, upper;
1302 ppc_avr_t result;
1303 int sat = 0;
1305 #if defined(HOST_WORDS_BIGENDIAN)
1306 upper = 1;
1307 #else
1308 upper = 0;
1309 #endif
1310 for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1311 int64_t t = (int64_t)b->s32[upper + i * 2];
1313 result.u64[i] = 0;
1314 for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
1315 t += a->s32[2 * i + j];
1317 result.s32[upper + i * 2] = cvtsdsw(t, &sat);
1320 *r = result;
1321 if (sat) {
1322 env->vscr |= (1 << VSCR_SAT);
1326 void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1328 int i, j;
1329 int sat = 0;
1331 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1332 int64_t t = (int64_t)b->s32[i];
1334 for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
1335 t += a->s8[4 * i + j];
1337 r->s32[i] = cvtsdsw(t, &sat);
1340 if (sat) {
1341 env->vscr |= (1 << VSCR_SAT);
1345 void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1347 int sat = 0;
1348 int i;
1350 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1351 int64_t t = (int64_t)b->s32[i];
1353 t += a->s16[2 * i] + a->s16[2 * i + 1];
1354 r->s32[i] = cvtsdsw(t, &sat);
1357 if (sat) {
1358 env->vscr |= (1 << VSCR_SAT);
1362 void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1364 int i, j;
1365 int sat = 0;
1367 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1368 uint64_t t = (uint64_t)b->u32[i];
1370 for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
1371 t += a->u8[4 * i + j];
1373 r->u32[i] = cvtuduw(t, &sat);
1376 if (sat) {
1377 env->vscr |= (1 << VSCR_SAT);
1381 #if defined(HOST_WORDS_BIGENDIAN)
1382 #define UPKHI 1
1383 #define UPKLO 0
1384 #else
1385 #define UPKHI 0
1386 #define UPKLO 1
1387 #endif
1388 #define VUPKPX(suffix, hi) \
1389 void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \
1391 int i; \
1392 ppc_avr_t result; \
1394 for (i = 0; i < ARRAY_SIZE(r->u32); i++) { \
1395 uint16_t e = b->u16[hi ? i : i+4]; \
1396 uint8_t a = (e >> 15) ? 0xff : 0; \
1397 uint8_t r = (e >> 10) & 0x1f; \
1398 uint8_t g = (e >> 5) & 0x1f; \
1399 uint8_t b = e & 0x1f; \
1401 result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b; \
1403 *r = result; \
1405 VUPKPX(lpx, UPKLO)
1406 VUPKPX(hpx, UPKHI)
1407 #undef VUPKPX
1409 #define VUPK(suffix, unpacked, packee, hi) \
1410 void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \
1412 int i; \
1413 ppc_avr_t result; \
1415 if (hi) { \
1416 for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) { \
1417 result.unpacked[i] = b->packee[i]; \
1419 } else { \
1420 for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
1421 i++) { \
1422 result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
1425 *r = result; \
1427 VUPK(hsb, s16, s8, UPKHI)
1428 VUPK(hsh, s32, s16, UPKHI)
1429 VUPK(lsb, s16, s8, UPKLO)
1430 VUPK(lsh, s32, s16, UPKLO)
1431 #undef VUPK
1432 #undef UPKHI
1433 #undef UPKLO
1435 #undef VECTOR_FOR_INORDER_I
1436 #undef HI_IDX
1437 #undef LO_IDX
1439 /*****************************************************************************/
1440 /* SPE extension helpers */
1441 /* Use a table to make this quicker */
1442 static const uint8_t hbrev[16] = {
1443 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1444 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1447 static inline uint8_t byte_reverse(uint8_t val)
1449 return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1452 static inline uint32_t word_reverse(uint32_t val)
1454 return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1455 (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1458 #define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
1459 target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
1461 uint32_t a, b, d, mask;
1463 mask = UINT32_MAX >> (32 - MASKBITS);
1464 a = arg1 & mask;
1465 b = arg2 & mask;
1466 d = word_reverse(1 + word_reverse(a | ~b));
1467 return (arg1 & ~mask) | (d & b);
1470 uint32_t helper_cntlsw32(uint32_t val)
1472 if (val & 0x80000000) {
1473 return clz32(~val);
1474 } else {
1475 return clz32(val);
1479 uint32_t helper_cntlzw32(uint32_t val)
1481 return clz32(val);
1484 /* 440 specific */
1485 target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high,
1486 target_ulong low, uint32_t update_Rc)
1488 target_ulong mask;
1489 int i;
1491 i = 1;
1492 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1493 if ((high & mask) == 0) {
1494 if (update_Rc) {
1495 env->crf[0] = 0x4;
1497 goto done;
1499 i++;
1501 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1502 if ((low & mask) == 0) {
1503 if (update_Rc) {
1504 env->crf[0] = 0x8;
1506 goto done;
1508 i++;
1510 if (update_Rc) {
1511 env->crf[0] = 0x2;
1513 done:
1514 env->xer = (env->xer & ~0x7F) | i;
1515 if (update_Rc) {
1516 env->crf[0] |= xer_so;
1518 return i;