]> Git Repo - qemu.git/blob - target-ppc/int_helper.c
target-ppc: Altivec 2.07: Add Vector Count Leading Zeroes
[qemu.git] / target-ppc / int_helper.c
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"
20 #include "qemu/host-utils.h"
21 #include "helper.h"
22
23 #include "helper_regs.h"
24 /*****************************************************************************/
25 /* Fixed point operations helpers */
26 #if defined(TARGET_PPC64)
27
28 uint64_t helper_mulldo(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
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)) {
36         env->ov = 0;
37     } else {
38         env->so = env->ov = 1;
39     }
40     return (int64_t)tl;
41 }
42 #endif
43
44 target_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
75 target_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
107 #if defined(TARGET_PPC64)
108
109 uint64_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
131 uint64_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
154 #endif
155
156
157 target_ulong helper_cntlzw(target_ulong t)
158 {
159     return clz32(t);
160 }
161
162 #if defined(TARGET_PPC64)
163 target_ulong helper_cntlzd(target_ulong t)
164 {
165     return clz64(t);
166 }
167 #endif
168
169 #if defined(TARGET_PPC64)
170
171 uint64_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
189 target_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
204 /* shift right arithmetic helper */
205 target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
206                          target_ulong shift)
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)) {
215                 env->ca = 0;
216             } else {
217                 env->ca = 1;
218             }
219         } else {
220             ret = (int32_t)value;
221             env->ca = 0;
222         }
223     } else {
224         ret = (int32_t)value >> 31;
225         env->ca = (ret != 0);
226     }
227     return (target_long)ret;
228 }
229
230 #if defined(TARGET_PPC64)
231 target_ulong helper_srad(CPUPPCState *env, target_ulong value,
232                          target_ulong shift)
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)) {
241                 env->ca = 0;
242             } else {
243                 env->ca = 1;
244             }
245         } else {
246             ret = (int64_t)value;
247             env->ca = 0;
248         }
249     } else {
250         ret = (int64_t)value >> 63;
251         env->ca = (ret != 0);
252     }
253     return ret;
254 }
255 #endif
256
257 #if defined(TARGET_PPC64)
258 target_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
269 target_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
284 target_ulong helper_popcntd(target_ulong val)
285 {
286     return ctpop64(val);
287 }
288 #else
289 target_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
297 target_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) */
310 target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
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
324 target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
325                          target_ulong arg2)
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) {
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;
341         }
342         return tmp;
343     }
344 }
345
346 target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
347                          target_ulong arg2)
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
359 target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
360                           target_ulong arg2)
361 {
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;
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)
383 target_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
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     }
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)
445
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
454
455 void 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
464 void 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
473 void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
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
483 void 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)
504 VARITH(ubm, u8)
505 VARITH(uhm, u16)
506 VARITH(uwm, u32)
507 VARITH(udm, u64)
508 VARITH_DO(muluwm, *, u32)
509 #undef VARITH_DO
510 #undef VARITH
511
512 #define VARITHFP(suffix, func)                                          \
513     void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
514                           ppc_avr_t *b)                                 \
515     {                                                                   \
516         int i;                                                          \
517                                                                         \
518         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
519             r->f[i] = func(a->f[i], b->f[i], &env->vec_status);         \
520         }                                                               \
521     }
522 VARITHFP(addfp, float32_add)
523 VARITHFP(subfp, float32_sub)
524 VARITHFP(minfp, float32_min)
525 VARITHFP(maxfp, float32_max)
526 #undef VARITHFP
527
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     }
538 VARITHFPFMA(maddfp, 0);
539 VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
540 #undef VARITHFPFMA
541
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)                    \
549     void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,   \
550                         ppc_avr_t *b)                                   \
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)
578 VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
579 VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
580 VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
581 VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
582 VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
583 VARITHSAT_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)
604 VAVG(b, s8, int16_t, u8, uint16_t)
605 VAVG(h, s16, int32_t, u16, uint32_t)
606 VAVG(w, s32, int64_t, u32, uint64_t)
607 #undef VAVG_DO
608 #undef VAVG
609
610 #define VCF(suffix, cvt, element)                                       \
611     void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r,             \
612                             ppc_avr_t *b, uint32_t uim)                 \
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     }
621 VCF(ux, uint32_to_float32, u32)
622 VCF(sx, int32_to_float32, s32)
623 #undef VCF
624
625 #define VCMP_DO(suffix, compare, element, record)                       \
626     void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r,            \
627                              ppc_avr_t *a, ppc_avr_t *b)                \
628     {                                                                   \
629         uint32_t ones = (uint32_t)-1;                                   \
630         uint32_t all = ones;                                            \
631         uint32_t none = 0;                                              \
632         int i;                                                          \
633                                                                         \
634         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
635             uint32_t result = (a->element[i] compare b->element[i] ?    \
636                                ones : 0x0);                             \
637             switch (sizeof(a->element[0])) {                            \
638             case 4:                                                     \
639                 r->u32[i] = result;                                     \
640                 break;                                                  \
641             case 2:                                                     \
642                 r->u16[i] = result;                                     \
643                 break;                                                  \
644             case 1:                                                     \
645                 r->u8[i] = result;                                      \
646                 break;                                                  \
647             }                                                           \
648             all &= result;                                              \
649             none |= result;                                             \
650         }                                                               \
651         if (record) {                                                   \
652             env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
653         }                                                               \
654     }
655 #define VCMP(suffix, compare, element)          \
656     VCMP_DO(suffix, compare, element, 0)        \
657     VCMP_DO(suffix##_dot, compare, element, 1)
658 VCMP(equb, ==, u8)
659 VCMP(equh, ==, u16)
660 VCMP(equw, ==, u32)
661 VCMP(gtub, >, u8)
662 VCMP(gtuh, >, u16)
663 VCMP(gtuw, >, u32)
664 VCMP(gtsb, >, s8)
665 VCMP(gtsh, >, s16)
666 VCMP(gtsw, >, s32)
667 #undef VCMP_DO
668 #undef VCMP
669
670 #define VCMPFP_DO(suffix, compare, order, record)                       \
671     void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r,            \
672                              ppc_avr_t *a, ppc_avr_t *b)                \
673     {                                                                   \
674         uint32_t ones = (uint32_t)-1;                                   \
675         uint32_t all = ones;                                            \
676         uint32_t none = 0;                                              \
677         int i;                                                          \
678                                                                         \
679         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
680             uint32_t result;                                            \
681             int rel = float32_compare_quiet(a->f[i], b->f[i],           \
682                                             &env->vec_status);          \
683             if (rel == float_relation_unordered) {                      \
684                 result = 0;                                             \
685             } else if (rel compare order) {                             \
686                 result = ones;                                          \
687             } else {                                                    \
688                 result = 0;                                             \
689             }                                                           \
690             r->u32[i] = result;                                         \
691             all &= result;                                              \
692             none |= result;                                             \
693         }                                                               \
694         if (record) {                                                   \
695             env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
696         }                                                               \
697     }
698 #define VCMPFP(suffix, compare, order)          \
699     VCMPFP_DO(suffix, compare, order, 0)        \
700     VCMPFP_DO(suffix##_dot, compare, order, 1)
701 VCMPFP(eqfp, ==, float_relation_equal)
702 VCMPFP(gefp, !=, float_relation_less)
703 VCMPFP(gtfp, ==, float_relation_greater)
704 #undef VCMPFP_DO
705 #undef VCMPFP
706
707 static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r,
708                                     ppc_avr_t *a, ppc_avr_t *b, int record)
709 {
710     int i;
711     int all_in = 0;
712
713     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
714         int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
715         if (le_rel == float_relation_unordered) {
716             r->u32[i] = 0xc0000000;
717             /* ALL_IN does not need to be updated here.  */
718         } else {
719             float32 bneg = float32_chs(b->f[i]);
720             int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
721             int le = le_rel != float_relation_greater;
722             int ge = ge_rel != float_relation_less;
723
724             r->u32[i] = ((!le) << 31) | ((!ge) << 30);
725             all_in |= (!le | !ge);
726         }
727     }
728     if (record) {
729         env->crf[6] = (all_in == 0) << 1;
730     }
731 }
732
733 void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
734 {
735     vcmpbfp_internal(env, r, a, b, 0);
736 }
737
738 void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
739                         ppc_avr_t *b)
740 {
741     vcmpbfp_internal(env, r, a, b, 1);
742 }
743
744 #define VCT(suffix, satcvt, element)                                    \
745     void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r,             \
746                             ppc_avr_t *b, uint32_t uim)                 \
747     {                                                                   \
748         int i;                                                          \
749         int sat = 0;                                                    \
750         float_status s = env->vec_status;                               \
751                                                                         \
752         set_float_rounding_mode(float_round_to_zero, &s);               \
753         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
754             if (float32_is_any_nan(b->f[i])) {                          \
755                 r->element[i] = 0;                                      \
756             } else {                                                    \
757                 float64 t = float32_to_float64(b->f[i], &s);            \
758                 int64_t j;                                              \
759                                                                         \
760                 t = float64_scalbn(t, uim, &s);                         \
761                 j = float64_to_int64(t, &s);                            \
762                 r->element[i] = satcvt(j, &sat);                        \
763             }                                                           \
764         }                                                               \
765         if (sat) {                                                      \
766             env->vscr |= (1 << VSCR_SAT);                               \
767         }                                                               \
768     }
769 VCT(uxs, cvtsduw, u32)
770 VCT(sxs, cvtsdsw, s32)
771 #undef VCT
772
773 void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
774                       ppc_avr_t *b, ppc_avr_t *c)
775 {
776     int sat = 0;
777     int i;
778
779     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
780         int32_t prod = a->s16[i] * b->s16[i];
781         int32_t t = (int32_t)c->s16[i] + (prod >> 15);
782
783         r->s16[i] = cvtswsh(t, &sat);
784     }
785
786     if (sat) {
787         env->vscr |= (1 << VSCR_SAT);
788     }
789 }
790
791 void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
792                        ppc_avr_t *b, ppc_avr_t *c)
793 {
794     int sat = 0;
795     int i;
796
797     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
798         int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
799         int32_t t = (int32_t)c->s16[i] + (prod >> 15);
800         r->s16[i] = cvtswsh(t, &sat);
801     }
802
803     if (sat) {
804         env->vscr |= (1 << VSCR_SAT);
805     }
806 }
807
808 #define VMINMAX_DO(name, compare, element)                              \
809     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
810     {                                                                   \
811         int i;                                                          \
812                                                                         \
813         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
814             if (a->element[i] compare b->element[i]) {                  \
815                 r->element[i] = b->element[i];                          \
816             } else {                                                    \
817                 r->element[i] = a->element[i];                          \
818             }                                                           \
819         }                                                               \
820     }
821 #define VMINMAX(suffix, element)                \
822     VMINMAX_DO(min##suffix, >, element)         \
823     VMINMAX_DO(max##suffix, <, element)
824 VMINMAX(sb, s8)
825 VMINMAX(sh, s16)
826 VMINMAX(sw, s32)
827 VMINMAX(ub, u8)
828 VMINMAX(uh, u16)
829 VMINMAX(uw, u32)
830 #undef VMINMAX_DO
831 #undef VMINMAX
832
833 void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
834 {
835     int i;
836
837     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
838         int32_t prod = a->s16[i] * b->s16[i];
839         r->s16[i] = (int16_t) (prod + c->s16[i]);
840     }
841 }
842
843 #define VMRG_DO(name, element, highp)                                   \
844     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
845     {                                                                   \
846         ppc_avr_t result;                                               \
847         int i;                                                          \
848         size_t n_elems = ARRAY_SIZE(r->element);                        \
849                                                                         \
850         for (i = 0; i < n_elems / 2; i++) {                             \
851             if (highp) {                                                \
852                 result.element[i*2+HI_IDX] = a->element[i];             \
853                 result.element[i*2+LO_IDX] = b->element[i];             \
854             } else {                                                    \
855                 result.element[n_elems - i * 2 - (1 + HI_IDX)] =        \
856                     b->element[n_elems - i - 1];                        \
857                 result.element[n_elems - i * 2 - (1 + LO_IDX)] =        \
858                     a->element[n_elems - i - 1];                        \
859             }                                                           \
860         }                                                               \
861         *r = result;                                                    \
862     }
863 #if defined(HOST_WORDS_BIGENDIAN)
864 #define MRGHI 0
865 #define MRGLO 1
866 #else
867 #define MRGHI 1
868 #define MRGLO 0
869 #endif
870 #define VMRG(suffix, element)                   \
871     VMRG_DO(mrgl##suffix, element, MRGHI)       \
872     VMRG_DO(mrgh##suffix, element, MRGLO)
873 VMRG(b, u8)
874 VMRG(h, u16)
875 VMRG(w, u32)
876 #undef VMRG_DO
877 #undef VMRG
878 #undef MRGHI
879 #undef MRGLO
880
881 void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
882                      ppc_avr_t *b, ppc_avr_t *c)
883 {
884     int32_t prod[16];
885     int i;
886
887     for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
888         prod[i] = (int32_t)a->s8[i] * b->u8[i];
889     }
890
891     VECTOR_FOR_INORDER_I(i, s32) {
892         r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
893             prod[4 * i + 2] + prod[4 * i + 3];
894     }
895 }
896
897 void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
898                      ppc_avr_t *b, ppc_avr_t *c)
899 {
900     int32_t prod[8];
901     int i;
902
903     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
904         prod[i] = a->s16[i] * b->s16[i];
905     }
906
907     VECTOR_FOR_INORDER_I(i, s32) {
908         r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
909     }
910 }
911
912 void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
913                      ppc_avr_t *b, ppc_avr_t *c)
914 {
915     int32_t prod[8];
916     int i;
917     int sat = 0;
918
919     for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
920         prod[i] = (int32_t)a->s16[i] * b->s16[i];
921     }
922
923     VECTOR_FOR_INORDER_I(i, s32) {
924         int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
925
926         r->u32[i] = cvtsdsw(t, &sat);
927     }
928
929     if (sat) {
930         env->vscr |= (1 << VSCR_SAT);
931     }
932 }
933
934 void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
935                      ppc_avr_t *b, ppc_avr_t *c)
936 {
937     uint16_t prod[16];
938     int i;
939
940     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
941         prod[i] = a->u8[i] * b->u8[i];
942     }
943
944     VECTOR_FOR_INORDER_I(i, u32) {
945         r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
946             prod[4 * i + 2] + prod[4 * i + 3];
947     }
948 }
949
950 void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
951                      ppc_avr_t *b, ppc_avr_t *c)
952 {
953     uint32_t prod[8];
954     int i;
955
956     for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
957         prod[i] = a->u16[i] * b->u16[i];
958     }
959
960     VECTOR_FOR_INORDER_I(i, u32) {
961         r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
962     }
963 }
964
965 void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
966                      ppc_avr_t *b, ppc_avr_t *c)
967 {
968     uint32_t prod[8];
969     int i;
970     int sat = 0;
971
972     for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
973         prod[i] = a->u16[i] * b->u16[i];
974     }
975
976     VECTOR_FOR_INORDER_I(i, s32) {
977         uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
978
979         r->u32[i] = cvtuduw(t, &sat);
980     }
981
982     if (sat) {
983         env->vscr |= (1 << VSCR_SAT);
984     }
985 }
986
987 #define VMUL_DO(name, mul_element, prod_element, cast, evenp)           \
988     void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
989     {                                                                   \
990         int i;                                                          \
991                                                                         \
992         VECTOR_FOR_INORDER_I(i, prod_element) {                         \
993             if (evenp) {                                                \
994                 r->prod_element[i] =                                    \
995                     (cast)a->mul_element[i * 2 + HI_IDX] *              \
996                     (cast)b->mul_element[i * 2 + HI_IDX];               \
997             } else {                                                    \
998                 r->prod_element[i] =                                    \
999                     (cast)a->mul_element[i * 2 + LO_IDX] *              \
1000                     (cast)b->mul_element[i * 2 + LO_IDX];               \
1001             }                                                           \
1002         }                                                               \
1003     }
1004 #define VMUL(suffix, mul_element, prod_element, cast)            \
1005     VMUL_DO(mule##suffix, mul_element, prod_element, cast, 1)    \
1006     VMUL_DO(mulo##suffix, mul_element, prod_element, cast, 0)
1007 VMUL(sb, s8, s16, int16_t)
1008 VMUL(sh, s16, s32, int32_t)
1009 VMUL(sw, s32, s64, int64_t)
1010 VMUL(ub, u8, u16, uint16_t)
1011 VMUL(uh, u16, u32, uint32_t)
1012 VMUL(uw, u32, u64, uint64_t)
1013 #undef VMUL_DO
1014 #undef VMUL
1015
1016 void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1017                   ppc_avr_t *c)
1018 {
1019     ppc_avr_t result;
1020     int i;
1021
1022     VECTOR_FOR_INORDER_I(i, u8) {
1023         int s = c->u8[i] & 0x1f;
1024 #if defined(HOST_WORDS_BIGENDIAN)
1025         int index = s & 0xf;
1026 #else
1027         int index = 15 - (s & 0xf);
1028 #endif
1029
1030         if (s & 0x10) {
1031             result.u8[i] = b->u8[index];
1032         } else {
1033             result.u8[i] = a->u8[index];
1034         }
1035     }
1036     *r = result;
1037 }
1038
1039 #if defined(HOST_WORDS_BIGENDIAN)
1040 #define PKBIG 1
1041 #else
1042 #define PKBIG 0
1043 #endif
1044 void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1045 {
1046     int i, j;
1047     ppc_avr_t result;
1048 #if defined(HOST_WORDS_BIGENDIAN)
1049     const ppc_avr_t *x[2] = { a, b };
1050 #else
1051     const ppc_avr_t *x[2] = { b, a };
1052 #endif
1053
1054     VECTOR_FOR_INORDER_I(i, u64) {
1055         VECTOR_FOR_INORDER_I(j, u32) {
1056             uint32_t e = x[i]->u32[j];
1057
1058             result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
1059                                  ((e >> 6) & 0x3e0) |
1060                                  ((e >> 3) & 0x1f));
1061         }
1062     }
1063     *r = result;
1064 }
1065
1066 #define VPK(suffix, from, to, cvt, dosat)                               \
1067     void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r,             \
1068                             ppc_avr_t *a, ppc_avr_t *b)                 \
1069     {                                                                   \
1070         int i;                                                          \
1071         int sat = 0;                                                    \
1072         ppc_avr_t result;                                               \
1073         ppc_avr_t *a0 = PKBIG ? a : b;                                  \
1074         ppc_avr_t *a1 = PKBIG ? b : a;                                  \
1075                                                                         \
1076         VECTOR_FOR_INORDER_I(i, from) {                                 \
1077             result.to[i] = cvt(a0->from[i], &sat);                      \
1078             result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);  \
1079         }                                                               \
1080         *r = result;                                                    \
1081         if (dosat && sat) {                                             \
1082             env->vscr |= (1 << VSCR_SAT);                               \
1083         }                                                               \
1084     }
1085 #define I(x, y) (x)
1086 VPK(shss, s16, s8, cvtshsb, 1)
1087 VPK(shus, s16, u8, cvtshub, 1)
1088 VPK(swss, s32, s16, cvtswsh, 1)
1089 VPK(swus, s32, u16, cvtswuh, 1)
1090 VPK(uhus, u16, u8, cvtuhub, 1)
1091 VPK(uwus, u32, u16, cvtuwuh, 1)
1092 VPK(uhum, u16, u8, I, 0)
1093 VPK(uwum, u32, u16, I, 0)
1094 #undef I
1095 #undef VPK
1096 #undef PKBIG
1097
1098 void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1099 {
1100     int i;
1101
1102     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1103         r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
1104     }
1105 }
1106
1107 #define VRFI(suffix, rounding)                                  \
1108     void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r,    \
1109                              ppc_avr_t *b)                      \
1110     {                                                           \
1111         int i;                                                  \
1112         float_status s = env->vec_status;                       \
1113                                                                 \
1114         set_float_rounding_mode(rounding, &s);                  \
1115         for (i = 0; i < ARRAY_SIZE(r->f); i++) {                \
1116             r->f[i] = float32_round_to_int (b->f[i], &s);       \
1117         }                                                       \
1118     }
1119 VRFI(n, float_round_nearest_even)
1120 VRFI(m, float_round_down)
1121 VRFI(p, float_round_up)
1122 VRFI(z, float_round_to_zero)
1123 #undef VRFI
1124
1125 #define VROTATE(suffix, element)                                        \
1126     void helper_vrl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
1127     {                                                                   \
1128         int i;                                                          \
1129                                                                         \
1130         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1131             unsigned int mask = ((1 <<                                  \
1132                                   (3 + (sizeof(a->element[0]) >> 1)))   \
1133                                  - 1);                                  \
1134             unsigned int shift = b->element[i] & mask;                  \
1135             r->element[i] = (a->element[i] << shift) |                  \
1136                 (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
1137         }                                                               \
1138     }
1139 VROTATE(b, u8)
1140 VROTATE(h, u16)
1141 VROTATE(w, u32)
1142 #undef VROTATE
1143
1144 void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1145 {
1146     int i;
1147
1148     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1149         float32 t = float32_sqrt(b->f[i], &env->vec_status);
1150
1151         r->f[i] = float32_div(float32_one, t, &env->vec_status);
1152     }
1153 }
1154
1155 void helper_vsel(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1156                  ppc_avr_t *c)
1157 {
1158     r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
1159     r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
1160 }
1161
1162 void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1163 {
1164     int i;
1165
1166     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1167         r->f[i] = float32_exp2(b->f[i], &env->vec_status);
1168     }
1169 }
1170
1171 void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1172 {
1173     int i;
1174
1175     for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1176         r->f[i] = float32_log2(b->f[i], &env->vec_status);
1177     }
1178 }
1179
1180 #if defined(HOST_WORDS_BIGENDIAN)
1181 #define LEFT 0
1182 #define RIGHT 1
1183 #else
1184 #define LEFT 1
1185 #define RIGHT 0
1186 #endif
1187 /* The specification says that the results are undefined if all of the
1188  * shift counts are not identical.  We check to make sure that they are
1189  * to conform to what real hardware appears to do.  */
1190 #define VSHIFT(suffix, leftp)                                           \
1191     void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
1192     {                                                                   \
1193         int shift = b->u8[LO_IDX*15] & 0x7;                             \
1194         int doit = 1;                                                   \
1195         int i;                                                          \
1196                                                                         \
1197         for (i = 0; i < ARRAY_SIZE(r->u8); i++) {                       \
1198             doit = doit && ((b->u8[i] & 0x7) == shift);                 \
1199         }                                                               \
1200         if (doit) {                                                     \
1201             if (shift == 0) {                                           \
1202                 *r = *a;                                                \
1203             } else if (leftp) {                                         \
1204                 uint64_t carry = a->u64[LO_IDX] >> (64 - shift);        \
1205                                                                         \
1206                 r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry;     \
1207                 r->u64[LO_IDX] = a->u64[LO_IDX] << shift;               \
1208             } else {                                                    \
1209                 uint64_t carry = a->u64[HI_IDX] << (64 - shift);        \
1210                                                                         \
1211                 r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry;     \
1212                 r->u64[HI_IDX] = a->u64[HI_IDX] >> shift;               \
1213             }                                                           \
1214         }                                                               \
1215     }
1216 VSHIFT(l, LEFT)
1217 VSHIFT(r, RIGHT)
1218 #undef VSHIFT
1219 #undef LEFT
1220 #undef RIGHT
1221
1222 #define VSL(suffix, element)                                            \
1223     void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
1224     {                                                                   \
1225         int i;                                                          \
1226                                                                         \
1227         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1228             unsigned int mask = ((1 <<                                  \
1229                                   (3 + (sizeof(a->element[0]) >> 1)))   \
1230                                  - 1);                                  \
1231             unsigned int shift = b->element[i] & mask;                  \
1232                                                                         \
1233             r->element[i] = a->element[i] << shift;                     \
1234         }                                                               \
1235     }
1236 VSL(b, u8)
1237 VSL(h, u16)
1238 VSL(w, u32)
1239 #undef VSL
1240
1241 void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
1242 {
1243     int sh = shift & 0xf;
1244     int i;
1245     ppc_avr_t result;
1246
1247 #if defined(HOST_WORDS_BIGENDIAN)
1248     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1249         int index = sh + i;
1250         if (index > 0xf) {
1251             result.u8[i] = b->u8[index - 0x10];
1252         } else {
1253             result.u8[i] = a->u8[index];
1254         }
1255     }
1256 #else
1257     for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1258         int index = (16 - sh) + i;
1259         if (index > 0xf) {
1260             result.u8[i] = a->u8[index - 0x10];
1261         } else {
1262             result.u8[i] = b->u8[index];
1263         }
1264     }
1265 #endif
1266     *r = result;
1267 }
1268
1269 void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1270 {
1271     int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
1272
1273 #if defined(HOST_WORDS_BIGENDIAN)
1274     memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1275     memset(&r->u8[16-sh], 0, sh);
1276 #else
1277     memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1278     memset(&r->u8[0], 0, sh);
1279 #endif
1280 }
1281
1282 /* Experimental testing shows that hardware masks the immediate.  */
1283 #define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
1284 #if defined(HOST_WORDS_BIGENDIAN)
1285 #define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
1286 #else
1287 #define SPLAT_ELEMENT(element)                                  \
1288     (ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element))
1289 #endif
1290 #define VSPLT(suffix, element)                                          \
1291     void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
1292     {                                                                   \
1293         uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
1294         int i;                                                          \
1295                                                                         \
1296         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1297             r->element[i] = s;                                          \
1298         }                                                               \
1299     }
1300 VSPLT(b, u8)
1301 VSPLT(h, u16)
1302 VSPLT(w, u32)
1303 #undef VSPLT
1304 #undef SPLAT_ELEMENT
1305 #undef _SPLAT_MASKED
1306
1307 #define VSPLTI(suffix, element, splat_type)                     \
1308     void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat)   \
1309     {                                                           \
1310         splat_type x = (int8_t)(splat << 3) >> 3;               \
1311         int i;                                                  \
1312                                                                 \
1313         for (i = 0; i < ARRAY_SIZE(r->element); i++) {          \
1314             r->element[i] = x;                                  \
1315         }                                                       \
1316     }
1317 VSPLTI(b, s8, int8_t)
1318 VSPLTI(h, s16, int16_t)
1319 VSPLTI(w, s32, int32_t)
1320 #undef VSPLTI
1321
1322 #define VSR(suffix, element)                                            \
1323     void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
1324     {                                                                   \
1325         int i;                                                          \
1326                                                                         \
1327         for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1328             unsigned int mask = ((1 <<                                  \
1329                                   (3 + (sizeof(a->element[0]) >> 1)))   \
1330                                  - 1);                                  \
1331             unsigned int shift = b->element[i] & mask;                  \
1332                                                                         \
1333             r->element[i] = a->element[i] >> shift;                     \
1334         }                                                               \
1335     }
1336 VSR(ab, s8)
1337 VSR(ah, s16)
1338 VSR(aw, s32)
1339 VSR(b, u8)
1340 VSR(h, u16)
1341 VSR(w, u32)
1342 #undef VSR
1343
1344 void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1345 {
1346     int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf;
1347
1348 #if defined(HOST_WORDS_BIGENDIAN)
1349     memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1350     memset(&r->u8[0], 0, sh);
1351 #else
1352     memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1353     memset(&r->u8[16 - sh], 0, sh);
1354 #endif
1355 }
1356
1357 void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1358 {
1359     int i;
1360
1361     for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1362         r->u32[i] = a->u32[i] >= b->u32[i];
1363     }
1364 }
1365
1366 void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1367 {
1368     int64_t t;
1369     int i, upper;
1370     ppc_avr_t result;
1371     int sat = 0;
1372
1373 #if defined(HOST_WORDS_BIGENDIAN)
1374     upper = ARRAY_SIZE(r->s32)-1;
1375 #else
1376     upper = 0;
1377 #endif
1378     t = (int64_t)b->s32[upper];
1379     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1380         t += a->s32[i];
1381         result.s32[i] = 0;
1382     }
1383     result.s32[upper] = cvtsdsw(t, &sat);
1384     *r = result;
1385
1386     if (sat) {
1387         env->vscr |= (1 << VSCR_SAT);
1388     }
1389 }
1390
1391 void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1392 {
1393     int i, j, upper;
1394     ppc_avr_t result;
1395     int sat = 0;
1396
1397 #if defined(HOST_WORDS_BIGENDIAN)
1398     upper = 1;
1399 #else
1400     upper = 0;
1401 #endif
1402     for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1403         int64_t t = (int64_t)b->s32[upper + i * 2];
1404
1405         result.u64[i] = 0;
1406         for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
1407             t += a->s32[2 * i + j];
1408         }
1409         result.s32[upper + i * 2] = cvtsdsw(t, &sat);
1410     }
1411
1412     *r = result;
1413     if (sat) {
1414         env->vscr |= (1 << VSCR_SAT);
1415     }
1416 }
1417
1418 void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1419 {
1420     int i, j;
1421     int sat = 0;
1422
1423     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1424         int64_t t = (int64_t)b->s32[i];
1425
1426         for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
1427             t += a->s8[4 * i + j];
1428         }
1429         r->s32[i] = cvtsdsw(t, &sat);
1430     }
1431
1432     if (sat) {
1433         env->vscr |= (1 << VSCR_SAT);
1434     }
1435 }
1436
1437 void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1438 {
1439     int sat = 0;
1440     int i;
1441
1442     for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1443         int64_t t = (int64_t)b->s32[i];
1444
1445         t += a->s16[2 * i] + a->s16[2 * i + 1];
1446         r->s32[i] = cvtsdsw(t, &sat);
1447     }
1448
1449     if (sat) {
1450         env->vscr |= (1 << VSCR_SAT);
1451     }
1452 }
1453
1454 void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1455 {
1456     int i, j;
1457     int sat = 0;
1458
1459     for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1460         uint64_t t = (uint64_t)b->u32[i];
1461
1462         for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
1463             t += a->u8[4 * i + j];
1464         }
1465         r->u32[i] = cvtuduw(t, &sat);
1466     }
1467
1468     if (sat) {
1469         env->vscr |= (1 << VSCR_SAT);
1470     }
1471 }
1472
1473 #if defined(HOST_WORDS_BIGENDIAN)
1474 #define UPKHI 1
1475 #define UPKLO 0
1476 #else
1477 #define UPKHI 0
1478 #define UPKLO 1
1479 #endif
1480 #define VUPKPX(suffix, hi)                                              \
1481     void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
1482     {                                                                   \
1483         int i;                                                          \
1484         ppc_avr_t result;                                               \
1485                                                                         \
1486         for (i = 0; i < ARRAY_SIZE(r->u32); i++) {                      \
1487             uint16_t e = b->u16[hi ? i : i+4];                          \
1488             uint8_t a = (e >> 15) ? 0xff : 0;                           \
1489             uint8_t r = (e >> 10) & 0x1f;                               \
1490             uint8_t g = (e >> 5) & 0x1f;                                \
1491             uint8_t b = e & 0x1f;                                       \
1492                                                                         \
1493             result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
1494         }                                                               \
1495         *r = result;                                                    \
1496     }
1497 VUPKPX(lpx, UPKLO)
1498 VUPKPX(hpx, UPKHI)
1499 #undef VUPKPX
1500
1501 #define VUPK(suffix, unpacked, packee, hi)                              \
1502     void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
1503     {                                                                   \
1504         int i;                                                          \
1505         ppc_avr_t result;                                               \
1506                                                                         \
1507         if (hi) {                                                       \
1508             for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
1509                 result.unpacked[i] = b->packee[i];                      \
1510             }                                                           \
1511         } else {                                                        \
1512             for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
1513                  i++) {                                                 \
1514                 result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
1515             }                                                           \
1516         }                                                               \
1517         *r = result;                                                    \
1518     }
1519 VUPK(hsb, s16, s8, UPKHI)
1520 VUPK(hsh, s32, s16, UPKHI)
1521 VUPK(lsb, s16, s8, UPKLO)
1522 VUPK(lsh, s32, s16, UPKLO)
1523 #undef VUPK
1524 #undef UPKHI
1525 #undef UPKLO
1526
1527 #define VGENERIC_DO(name, element)                                      \
1528     void helper_v##name(ppc_avr_t *r, ppc_avr_t *b)                     \
1529     {                                                                   \
1530         int i;                                                          \
1531                                                                         \
1532         VECTOR_FOR_INORDER_I(i, element) {                              \
1533             r->element[i] = name(b->element[i]);                        \
1534         }                                                               \
1535     }
1536
1537 #define clzb(v) ((v) ? clz32((uint32_t)(v) << 24) : 8)
1538 #define clzh(v) ((v) ? clz32((uint32_t)(v) << 16) : 16)
1539 #define clzw(v) clz32((v))
1540 #define clzd(v) clz64((v))
1541
1542 VGENERIC_DO(clzb, u8)
1543 VGENERIC_DO(clzh, u16)
1544 VGENERIC_DO(clzw, u32)
1545 VGENERIC_DO(clzd, u64)
1546
1547 #undef clzb
1548 #undef clzh
1549 #undef clzw
1550 #undef clzd
1551
1552
1553 #undef VGENERIC_DO
1554
1555
1556 #undef VECTOR_FOR_INORDER_I
1557 #undef HI_IDX
1558 #undef LO_IDX
1559
1560 /*****************************************************************************/
1561 /* SPE extension helpers */
1562 /* Use a table to make this quicker */
1563 static const uint8_t hbrev[16] = {
1564     0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1565     0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1566 };
1567
1568 static inline uint8_t byte_reverse(uint8_t val)
1569 {
1570     return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1571 }
1572
1573 static inline uint32_t word_reverse(uint32_t val)
1574 {
1575     return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1576         (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1577 }
1578
1579 #define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
1580 target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
1581 {
1582     uint32_t a, b, d, mask;
1583
1584     mask = UINT32_MAX >> (32 - MASKBITS);
1585     a = arg1 & mask;
1586     b = arg2 & mask;
1587     d = word_reverse(1 + word_reverse(a | ~b));
1588     return (arg1 & ~mask) | (d & b);
1589 }
1590
1591 uint32_t helper_cntlsw32(uint32_t val)
1592 {
1593     if (val & 0x80000000) {
1594         return clz32(~val);
1595     } else {
1596         return clz32(val);
1597     }
1598 }
1599
1600 uint32_t helper_cntlzw32(uint32_t val)
1601 {
1602     return clz32(val);
1603 }
1604
1605 /* 440 specific */
1606 target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high,
1607                           target_ulong low, uint32_t update_Rc)
1608 {
1609     target_ulong mask;
1610     int i;
1611
1612     i = 1;
1613     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1614         if ((high & mask) == 0) {
1615             if (update_Rc) {
1616                 env->crf[0] = 0x4;
1617             }
1618             goto done;
1619         }
1620         i++;
1621     }
1622     for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1623         if ((low & mask) == 0) {
1624             if (update_Rc) {
1625                 env->crf[0] = 0x8;
1626             }
1627             goto done;
1628         }
1629         i++;
1630     }
1631     if (update_Rc) {
1632         env->crf[0] = 0x2;
1633     }
1634  done:
1635     env->xer = (env->xer & ~0x7F) | i;
1636     if (update_Rc) {
1637         env->crf[0] |= xer_so;
1638     }
1639     return i;
1640 }
This page took 0.128302 seconds and 4 git commands to generate.