]> Git Repo - qemu.git/blame - target-ppc/int_helper.c
target-ppc: Altivec 2.07: Vector Logical Instructions
[qemu.git] / target-ppc / int_helper.c
CommitLineData
64654ded
BS
1/*
2 * PowerPC integer and vector emulation helpers for QEMU.
3 *
4 * Copyright (c) 2003-2007 Jocelyn Mayer
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19#include "cpu.h"
1de7afc9 20#include "qemu/host-utils.h"
64654ded
BS
21#include "helper.h"
22
23#include "helper_regs.h"
24/*****************************************************************************/
25/* Fixed point operations helpers */
26#if defined(TARGET_PPC64)
27
d15f74fb 28uint64_t helper_mulldo(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
64654ded
BS
29{
30 int64_t th;
31 uint64_t tl;
32
33 muls64(&tl, (uint64_t *)&th, arg1, arg2);
34 /* If th != 0 && th != -1, then we had an overflow */
35 if (likely((uint64_t)(th + 1) <= 1)) {
da91a00f 36 env->ov = 0;
64654ded 37 } else {
da91a00f 38 env->so = env->ov = 1;
64654ded
BS
39 }
40 return (int64_t)tl;
41}
42#endif
43
6a4fda33
TM
44target_ulong helper_divweu(CPUPPCState *env, target_ulong ra, target_ulong rb,
45 uint32_t oe)
46{
47 uint64_t rt = 0;
48 int overflow = 0;
49
50 uint64_t dividend = (uint64_t)ra << 32;
51 uint64_t divisor = (uint32_t)rb;
52
53 if (unlikely(divisor == 0)) {
54 overflow = 1;
55 } else {
56 rt = dividend / divisor;
57 overflow = rt > UINT32_MAX;
58 }
59
60 if (unlikely(overflow)) {
61 rt = 0; /* Undefined */
62 }
63
64 if (oe) {
65 if (unlikely(overflow)) {
66 env->so = env->ov = 1;
67 } else {
68 env->ov = 0;
69 }
70 }
71
72 return (target_ulong)rt;
73}
74
a98eb9e9
TM
75target_ulong helper_divwe(CPUPPCState *env, target_ulong ra, target_ulong rb,
76 uint32_t oe)
77{
78 int64_t rt = 0;
79 int overflow = 0;
80
81 int64_t dividend = (int64_t)ra << 32;
82 int64_t divisor = (int64_t)((int32_t)rb);
83
84 if (unlikely((divisor == 0) ||
85 ((divisor == -1ull) && (dividend == INT64_MIN)))) {
86 overflow = 1;
87 } else {
88 rt = dividend / divisor;
89 overflow = rt != (int32_t)rt;
90 }
91
92 if (unlikely(overflow)) {
93 rt = 0; /* Undefined */
94 }
95
96 if (oe) {
97 if (unlikely(overflow)) {
98 env->so = env->ov = 1;
99 } else {
100 env->ov = 0;
101 }
102 }
103
104 return (target_ulong)rt;
105}
106
98d1eb27
TM
107#if defined(TARGET_PPC64)
108
109uint64_t helper_divdeu(CPUPPCState *env, uint64_t ra, uint64_t rb, uint32_t oe)
110{
111 uint64_t rt = 0;
112 int overflow = 0;
113
114 overflow = divu128(&rt, &ra, rb);
115
116 if (unlikely(overflow)) {
117 rt = 0; /* Undefined */
118 }
119
120 if (oe) {
121 if (unlikely(overflow)) {
122 env->so = env->ov = 1;
123 } else {
124 env->ov = 0;
125 }
126 }
127
128 return rt;
129}
130
e44259b6
TM
131uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
132{
133 int64_t rt = 0;
134 int64_t ra = (int64_t)rau;
135 int64_t rb = (int64_t)rbu;
136 int overflow = divs128(&rt, &ra, rb);
137
138 if (unlikely(overflow)) {
139 rt = 0; /* Undefined */
140 }
141
142 if (oe) {
143
144 if (unlikely(overflow)) {
145 env->so = env->ov = 1;
146 } else {
147 env->ov = 0;
148 }
149 }
150
151 return rt;
152}
153
98d1eb27
TM
154#endif
155
156
64654ded
BS
157target_ulong helper_cntlzw(target_ulong t)
158{
159 return clz32(t);
160}
161
162#if defined(TARGET_PPC64)
163target_ulong helper_cntlzd(target_ulong t)
164{
165 return clz64(t);
166}
167#endif
168
86ba37ed
TM
169#if defined(TARGET_PPC64)
170
171uint64_t helper_bpermd(uint64_t rs, uint64_t rb)
172{
173 int i;
174 uint64_t ra = 0;
175
176 for (i = 0; i < 8; i++) {
177 int index = (rs >> (i*8)) & 0xFF;
178 if (index < 64) {
179 if (rb & (1ull << (63-index))) {
180 ra |= 1 << i;
181 }
182 }
183 }
184 return ra;
185}
186
187#endif
188
fcfda20f
AJ
189target_ulong helper_cmpb(target_ulong rs, target_ulong rb)
190{
191 target_ulong mask = 0xff;
192 target_ulong ra = 0;
193 int i;
194
195 for (i = 0; i < sizeof(target_ulong); i++) {
196 if ((rs & mask) == (rb & mask)) {
197 ra |= mask;
198 }
199 mask <<= 8;
200 }
201 return ra;
202}
203
64654ded 204/* shift right arithmetic helper */
d15f74fb
BS
205target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
206 target_ulong shift)
64654ded
BS
207{
208 int32_t ret;
209
210 if (likely(!(shift & 0x20))) {
211 if (likely((uint32_t)shift != 0)) {
212 shift &= 0x1f;
213 ret = (int32_t)value >> shift;
214 if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
da91a00f 215 env->ca = 0;
64654ded 216 } else {
da91a00f 217 env->ca = 1;
64654ded
BS
218 }
219 } else {
220 ret = (int32_t)value;
da91a00f 221 env->ca = 0;
64654ded
BS
222 }
223 } else {
224 ret = (int32_t)value >> 31;
da91a00f 225 env->ca = (ret != 0);
64654ded
BS
226 }
227 return (target_long)ret;
228}
229
230#if defined(TARGET_PPC64)
d15f74fb
BS
231target_ulong helper_srad(CPUPPCState *env, target_ulong value,
232 target_ulong shift)
64654ded
BS
233{
234 int64_t ret;
235
236 if (likely(!(shift & 0x40))) {
237 if (likely((uint64_t)shift != 0)) {
238 shift &= 0x3f;
239 ret = (int64_t)value >> shift;
240 if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
da91a00f 241 env->ca = 0;
64654ded 242 } else {
da91a00f 243 env->ca = 1;
64654ded
BS
244 }
245 } else {
246 ret = (int64_t)value;
da91a00f 247 env->ca = 0;
64654ded
BS
248 }
249 } else {
250 ret = (int64_t)value >> 63;
da91a00f 251 env->ca = (ret != 0);
64654ded
BS
252 }
253 return ret;
254}
255#endif
256
257#if defined(TARGET_PPC64)
258target_ulong helper_popcntb(target_ulong val)
259{
260 val = (val & 0x5555555555555555ULL) + ((val >> 1) &
261 0x5555555555555555ULL);
262 val = (val & 0x3333333333333333ULL) + ((val >> 2) &
263 0x3333333333333333ULL);
264 val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) &
265 0x0f0f0f0f0f0f0f0fULL);
266 return val;
267}
268
269target_ulong helper_popcntw(target_ulong val)
270{
271 val = (val & 0x5555555555555555ULL) + ((val >> 1) &
272 0x5555555555555555ULL);
273 val = (val & 0x3333333333333333ULL) + ((val >> 2) &
274 0x3333333333333333ULL);
275 val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) &
276 0x0f0f0f0f0f0f0f0fULL);
277 val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) &
278 0x00ff00ff00ff00ffULL);
279 val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
280 0x0000ffff0000ffffULL);
281 return val;
282}
283
284target_ulong helper_popcntd(target_ulong val)
285{
286 return ctpop64(val);
287}
288#else
289target_ulong helper_popcntb(target_ulong val)
290{
291 val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
292 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
293 val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
294 return val;
295}
296
297target_ulong helper_popcntw(target_ulong val)
298{
299 val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
300 val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
301 val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
302 val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff);
303 val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
304 return val;
305}
306#endif
307
308/*****************************************************************************/
309/* PowerPC 601 specific instructions (POWER bridge) */
d15f74fb 310target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
64654ded
BS
311{
312 uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
313
314 if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
315 (int32_t)arg2 == 0) {
316 env->spr[SPR_MQ] = 0;
317 return INT32_MIN;
318 } else {
319 env->spr[SPR_MQ] = tmp % arg2;
320 return tmp / (int32_t)arg2;
321 }
322}
323
d15f74fb
BS
324target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
325 target_ulong arg2)
64654ded
BS
326{
327 uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
328
329 if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
330 (int32_t)arg2 == 0) {
da91a00f 331 env->so = env->ov = 1;
64654ded
BS
332 env->spr[SPR_MQ] = 0;
333 return INT32_MIN;
334 } else {
335 env->spr[SPR_MQ] = tmp % arg2;
336 tmp /= (int32_t)arg2;
337 if ((int32_t)tmp != tmp) {
da91a00f 338 env->so = env->ov = 1;
64654ded 339 } else {
da91a00f 340 env->ov = 0;
64654ded
BS
341 }
342 return tmp;
343 }
344}
345
d15f74fb
BS
346target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
347 target_ulong arg2)
64654ded
BS
348{
349 if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
350 (int32_t)arg2 == 0) {
351 env->spr[SPR_MQ] = 0;
352 return INT32_MIN;
353 } else {
354 env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
355 return (int32_t)arg1 / (int32_t)arg2;
356 }
357}
358
d15f74fb
BS
359target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
360 target_ulong arg2)
64654ded
BS
361{
362 if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
363 (int32_t)arg2 == 0) {
da91a00f 364 env->so = env->ov = 1;
64654ded
BS
365 env->spr[SPR_MQ] = 0;
366 return INT32_MIN;
367 } else {
da91a00f 368 env->ov = 0;
64654ded
BS
369 env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
370 return (int32_t)arg1 / (int32_t)arg2;
371 }
372}
373
374/*****************************************************************************/
375/* 602 specific instructions */
376/* mfrom is the most crazy instruction ever seen, imho ! */
377/* Real implementation uses a ROM table. Do the same */
378/* Extremely decomposed:
379 * -arg / 256
380 * return 256 * log10(10 + 1.0) + 0.5
381 */
382#if !defined(CONFIG_USER_ONLY)
383target_ulong helper_602_mfrom(target_ulong arg)
384{
385 if (likely(arg < 602)) {
386#include "mfrom_table.c"
387 return mfrom_ROM_table[arg];
388 } else {
389 return 0;
390 }
391}
392#endif
393
394/*****************************************************************************/
395/* Altivec extension helpers */
396#if defined(HOST_WORDS_BIGENDIAN)
397#define HI_IDX 0
398#define LO_IDX 1
399#else
400#define HI_IDX 1
401#define LO_IDX 0
402#endif
403
404#if defined(HOST_WORDS_BIGENDIAN)
405#define VECTOR_FOR_INORDER_I(index, element) \
406 for (index = 0; index < ARRAY_SIZE(r->element); index++)
407#else
408#define VECTOR_FOR_INORDER_I(index, element) \
409 for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
410#endif
411
64654ded
BS
412/* Saturating arithmetic helpers. */
413#define SATCVT(from, to, from_type, to_type, min, max) \
414 static inline to_type cvt##from##to(from_type x, int *sat) \
415 { \
416 to_type r; \
417 \
418 if (x < (from_type)min) { \
419 r = min; \
420 *sat = 1; \
421 } else if (x > (from_type)max) { \
422 r = max; \
423 *sat = 1; \
424 } else { \
425 r = x; \
426 } \
427 return r; \
428 }
429#define SATCVTU(from, to, from_type, to_type, min, max) \
430 static inline to_type cvt##from##to(from_type x, int *sat) \
431 { \
432 to_type r; \
433 \
434 if (x > (from_type)max) { \
435 r = max; \
436 *sat = 1; \
437 } else { \
438 r = x; \
439 } \
440 return r; \
441 }
442SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX)
443SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX)
444SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX)
445
446SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX)
447SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX)
448SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX)
449SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX)
450SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX)
451SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
452#undef SATCVT
453#undef SATCVTU
454
455void helper_lvsl(ppc_avr_t *r, target_ulong sh)
456{
457 int i, j = (sh & 0xf);
458
459 VECTOR_FOR_INORDER_I(i, u8) {
460 r->u8[i] = j++;
461 }
462}
463
464void helper_lvsr(ppc_avr_t *r, target_ulong sh)
465{
466 int i, j = 0x10 - (sh & 0xf);
467
468 VECTOR_FOR_INORDER_I(i, u8) {
469 r->u8[i] = j++;
470 }
471}
472
d15f74fb 473void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
64654ded
BS
474{
475#if defined(HOST_WORDS_BIGENDIAN)
476 env->vscr = r->u32[3];
477#else
478 env->vscr = r->u32[0];
479#endif
480 set_flush_to_zero(vscr_nj, &env->vec_status);
481}
482
483void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
484{
485 int i;
486
487 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
488 r->u32[i] = ~a->u32[i] < b->u32[i];
489 }
490}
491
492#define VARITH_DO(name, op, element) \
493 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
494 { \
495 int i; \
496 \
497 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
498 r->element[i] = a->element[i] op b->element[i]; \
499 } \
500 }
501#define VARITH(suffix, element) \
502 VARITH_DO(add##suffix, +, element) \
503 VARITH_DO(sub##suffix, -, element)
504VARITH(ubm, u8)
505VARITH(uhm, u16)
506VARITH(uwm, u32)
507#undef VARITH_DO
508#undef VARITH
509
510#define VARITHFP(suffix, func) \
d15f74fb
BS
511 void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
512 ppc_avr_t *b) \
64654ded
BS
513 { \
514 int i; \
515 \
516 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
ef9bd150 517 r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
64654ded
BS
518 } \
519 }
520VARITHFP(addfp, float32_add)
521VARITHFP(subfp, float32_sub)
db1babb8
AJ
522VARITHFP(minfp, float32_min)
523VARITHFP(maxfp, float32_max)
64654ded
BS
524#undef VARITHFP
525
2f93c23f
AJ
526#define VARITHFPFMA(suffix, type) \
527 void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
528 ppc_avr_t *b, ppc_avr_t *c) \
529 { \
530 int i; \
531 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
532 r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i], \
533 type, &env->vec_status); \
534 } \
535 }
536VARITHFPFMA(maddfp, 0);
537VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
538#undef VARITHFPFMA
539
64654ded
BS
540#define VARITHSAT_CASE(type, op, cvt, element) \
541 { \
542 type result = (type)a->element[i] op (type)b->element[i]; \
543 r->element[i] = cvt(result, &sat); \
544 }
545
546#define VARITHSAT_DO(name, op, optype, cvt, element) \
d15f74fb
BS
547 void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
548 ppc_avr_t *b) \
64654ded
BS
549 { \
550 int sat = 0; \
551 int i; \
552 \
553 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
554 switch (sizeof(r->element[0])) { \
555 case 1: \
556 VARITHSAT_CASE(optype, op, cvt, element); \
557 break; \
558 case 2: \
559 VARITHSAT_CASE(optype, op, cvt, element); \
560 break; \
561 case 4: \
562 VARITHSAT_CASE(optype, op, cvt, element); \
563 break; \
564 } \
565 } \
566 if (sat) { \
567 env->vscr |= (1 << VSCR_SAT); \
568 } \
569 }
570#define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
571 VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element) \
572 VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
573#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt) \
574 VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element) \
575 VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
576VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
577VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
578VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
579VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
580VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
581VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
582#undef VARITHSAT_CASE
583#undef VARITHSAT_DO
584#undef VARITHSAT_SIGNED
585#undef VARITHSAT_UNSIGNED
586
587#define VAVG_DO(name, element, etype) \
588 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
589 { \
590 int i; \
591 \
592 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
593 etype x = (etype)a->element[i] + (etype)b->element[i] + 1; \
594 r->element[i] = x >> 1; \
595 } \
596 }
597
598#define VAVG(type, signed_element, signed_type, unsigned_element, \
599 unsigned_type) \
600 VAVG_DO(avgs##type, signed_element, signed_type) \
601 VAVG_DO(avgu##type, unsigned_element, unsigned_type)
602VAVG(b, s8, int16_t, u8, uint16_t)
603VAVG(h, s16, int32_t, u16, uint32_t)
604VAVG(w, s32, int64_t, u32, uint64_t)
605#undef VAVG_DO
606#undef VAVG
607
608#define VCF(suffix, cvt, element) \
d15f74fb
BS
609 void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r, \
610 ppc_avr_t *b, uint32_t uim) \
64654ded
BS
611 { \
612 int i; \
613 \
614 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
615 float32 t = cvt(b->element[i], &env->vec_status); \
616 r->f[i] = float32_scalbn(t, -uim, &env->vec_status); \
617 } \
618 }
619VCF(ux, uint32_to_float32, u32)
620VCF(sx, int32_to_float32, s32)
621#undef VCF
622
623#define VCMP_DO(suffix, compare, element, record) \
d15f74fb
BS
624 void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
625 ppc_avr_t *a, ppc_avr_t *b) \
64654ded
BS
626 { \
627 uint32_t ones = (uint32_t)-1; \
628 uint32_t all = ones; \
629 uint32_t none = 0; \
630 int i; \
631 \
632 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
633 uint32_t result = (a->element[i] compare b->element[i] ? \
634 ones : 0x0); \
635 switch (sizeof(a->element[0])) { \
636 case 4: \
637 r->u32[i] = result; \
638 break; \
639 case 2: \
640 r->u16[i] = result; \
641 break; \
642 case 1: \
643 r->u8[i] = result; \
644 break; \
645 } \
646 all &= result; \
647 none |= result; \
648 } \
649 if (record) { \
650 env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
651 } \
652 }
653#define VCMP(suffix, compare, element) \
654 VCMP_DO(suffix, compare, element, 0) \
655 VCMP_DO(suffix##_dot, compare, element, 1)
656VCMP(equb, ==, u8)
657VCMP(equh, ==, u16)
658VCMP(equw, ==, u32)
659VCMP(gtub, >, u8)
660VCMP(gtuh, >, u16)
661VCMP(gtuw, >, u32)
662VCMP(gtsb, >, s8)
663VCMP(gtsh, >, s16)
664VCMP(gtsw, >, s32)
665#undef VCMP_DO
666#undef VCMP
667
668#define VCMPFP_DO(suffix, compare, order, record) \
d15f74fb
BS
669 void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r, \
670 ppc_avr_t *a, ppc_avr_t *b) \
64654ded
BS
671 { \
672 uint32_t ones = (uint32_t)-1; \
673 uint32_t all = ones; \
674 uint32_t none = 0; \
675 int i; \
676 \
677 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
678 uint32_t result; \
679 int rel = float32_compare_quiet(a->f[i], b->f[i], \
680 &env->vec_status); \
681 if (rel == float_relation_unordered) { \
682 result = 0; \
683 } else if (rel compare order) { \
684 result = ones; \
685 } else { \
686 result = 0; \
687 } \
688 r->u32[i] = result; \
689 all &= result; \
690 none |= result; \
691 } \
692 if (record) { \
693 env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
694 } \
695 }
696#define VCMPFP(suffix, compare, order) \
697 VCMPFP_DO(suffix, compare, order, 0) \
698 VCMPFP_DO(suffix##_dot, compare, order, 1)
699VCMPFP(eqfp, ==, float_relation_equal)
700VCMPFP(gefp, !=, float_relation_less)
701VCMPFP(gtfp, ==, float_relation_greater)
702#undef VCMPFP_DO
703#undef VCMPFP
704
d15f74fb
BS
705static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r,
706 ppc_avr_t *a, ppc_avr_t *b, int record)
64654ded
BS
707{
708 int i;
709 int all_in = 0;
710
711 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
712 int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
713 if (le_rel == float_relation_unordered) {
714 r->u32[i] = 0xc0000000;
715 /* ALL_IN does not need to be updated here. */
716 } else {
717 float32 bneg = float32_chs(b->f[i]);
718 int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
719 int le = le_rel != float_relation_greater;
720 int ge = ge_rel != float_relation_less;
721
722 r->u32[i] = ((!le) << 31) | ((!ge) << 30);
723 all_in |= (!le | !ge);
724 }
725 }
726 if (record) {
727 env->crf[6] = (all_in == 0) << 1;
728 }
729}
730
d15f74fb 731void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded 732{
d15f74fb 733 vcmpbfp_internal(env, r, a, b, 0);
64654ded
BS
734}
735
d15f74fb
BS
736void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
737 ppc_avr_t *b)
64654ded 738{
d15f74fb 739 vcmpbfp_internal(env, r, a, b, 1);
64654ded
BS
740}
741
742#define VCT(suffix, satcvt, element) \
d15f74fb
BS
743 void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r, \
744 ppc_avr_t *b, uint32_t uim) \
64654ded
BS
745 { \
746 int i; \
747 int sat = 0; \
748 float_status s = env->vec_status; \
749 \
750 set_float_rounding_mode(float_round_to_zero, &s); \
751 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
752 if (float32_is_any_nan(b->f[i])) { \
753 r->element[i] = 0; \
754 } else { \
755 float64 t = float32_to_float64(b->f[i], &s); \
756 int64_t j; \
757 \
758 t = float64_scalbn(t, uim, &s); \
759 j = float64_to_int64(t, &s); \
760 r->element[i] = satcvt(j, &sat); \
761 } \
762 } \
763 if (sat) { \
764 env->vscr |= (1 << VSCR_SAT); \
765 } \
766 }
767VCT(uxs, cvtsduw, u32)
768VCT(sxs, cvtsdsw, s32)
769#undef VCT
770
d15f74fb
BS
771void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
772 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
773{
774 int sat = 0;
775 int i;
776
777 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
778 int32_t prod = a->s16[i] * b->s16[i];
779 int32_t t = (int32_t)c->s16[i] + (prod >> 15);
780
781 r->s16[i] = cvtswsh(t, &sat);
782 }
783
784 if (sat) {
785 env->vscr |= (1 << VSCR_SAT);
786 }
787}
788
d15f74fb
BS
789void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
790 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
791{
792 int sat = 0;
793 int i;
794
795 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
796 int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
797 int32_t t = (int32_t)c->s16[i] + (prod >> 15);
798 r->s16[i] = cvtswsh(t, &sat);
799 }
800
801 if (sat) {
802 env->vscr |= (1 << VSCR_SAT);
803 }
804}
805
806#define VMINMAX_DO(name, compare, element) \
807 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
808 { \
809 int i; \
810 \
811 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
812 if (a->element[i] compare b->element[i]) { \
813 r->element[i] = b->element[i]; \
814 } else { \
815 r->element[i] = a->element[i]; \
816 } \
817 } \
818 }
819#define VMINMAX(suffix, element) \
820 VMINMAX_DO(min##suffix, >, element) \
821 VMINMAX_DO(max##suffix, <, element)
822VMINMAX(sb, s8)
823VMINMAX(sh, s16)
824VMINMAX(sw, s32)
825VMINMAX(ub, u8)
826VMINMAX(uh, u16)
827VMINMAX(uw, u32)
828#undef VMINMAX_DO
829#undef VMINMAX
830
64654ded
BS
831void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
832{
833 int i;
834
835 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
836 int32_t prod = a->s16[i] * b->s16[i];
837 r->s16[i] = (int16_t) (prod + c->s16[i]);
838 }
839}
840
841#define VMRG_DO(name, element, highp) \
842 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
843 { \
844 ppc_avr_t result; \
845 int i; \
846 size_t n_elems = ARRAY_SIZE(r->element); \
847 \
848 for (i = 0; i < n_elems / 2; i++) { \
849 if (highp) { \
850 result.element[i*2+HI_IDX] = a->element[i]; \
851 result.element[i*2+LO_IDX] = b->element[i]; \
852 } else { \
853 result.element[n_elems - i * 2 - (1 + HI_IDX)] = \
854 b->element[n_elems - i - 1]; \
855 result.element[n_elems - i * 2 - (1 + LO_IDX)] = \
856 a->element[n_elems - i - 1]; \
857 } \
858 } \
859 *r = result; \
860 }
861#if defined(HOST_WORDS_BIGENDIAN)
862#define MRGHI 0
863#define MRGLO 1
864#else
865#define MRGHI 1
866#define MRGLO 0
867#endif
868#define VMRG(suffix, element) \
869 VMRG_DO(mrgl##suffix, element, MRGHI) \
870 VMRG_DO(mrgh##suffix, element, MRGLO)
871VMRG(b, u8)
872VMRG(h, u16)
873VMRG(w, u32)
874#undef VMRG_DO
875#undef VMRG
876#undef MRGHI
877#undef MRGLO
878
d15f74fb
BS
879void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
880 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
881{
882 int32_t prod[16];
883 int i;
884
885 for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
886 prod[i] = (int32_t)a->s8[i] * b->u8[i];
887 }
888
889 VECTOR_FOR_INORDER_I(i, s32) {
890 r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
891 prod[4 * i + 2] + prod[4 * i + 3];
892 }
893}
894
d15f74fb
BS
895void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
896 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
897{
898 int32_t prod[8];
899 int i;
900
901 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
902 prod[i] = a->s16[i] * b->s16[i];
903 }
904
905 VECTOR_FOR_INORDER_I(i, s32) {
906 r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
907 }
908}
909
d15f74fb
BS
910void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
911 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
912{
913 int32_t prod[8];
914 int i;
915 int sat = 0;
916
917 for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
918 prod[i] = (int32_t)a->s16[i] * b->s16[i];
919 }
920
921 VECTOR_FOR_INORDER_I(i, s32) {
922 int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
923
924 r->u32[i] = cvtsdsw(t, &sat);
925 }
926
927 if (sat) {
928 env->vscr |= (1 << VSCR_SAT);
929 }
930}
931
d15f74fb
BS
932void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
933 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
934{
935 uint16_t prod[16];
936 int i;
937
938 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
939 prod[i] = a->u8[i] * b->u8[i];
940 }
941
942 VECTOR_FOR_INORDER_I(i, u32) {
943 r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
944 prod[4 * i + 2] + prod[4 * i + 3];
945 }
946}
947
d15f74fb
BS
948void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
949 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
950{
951 uint32_t prod[8];
952 int i;
953
954 for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
955 prod[i] = a->u16[i] * b->u16[i];
956 }
957
958 VECTOR_FOR_INORDER_I(i, u32) {
959 r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
960 }
961}
962
d15f74fb
BS
963void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
964 ppc_avr_t *b, ppc_avr_t *c)
64654ded
BS
965{
966 uint32_t prod[8];
967 int i;
968 int sat = 0;
969
970 for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
971 prod[i] = a->u16[i] * b->u16[i];
972 }
973
974 VECTOR_FOR_INORDER_I(i, s32) {
975 uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
976
977 r->u32[i] = cvtuduw(t, &sat);
978 }
979
980 if (sat) {
981 env->vscr |= (1 << VSCR_SAT);
982 }
983}
984
985#define VMUL_DO(name, mul_element, prod_element, evenp) \
986 void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
987 { \
988 int i; \
989 \
990 VECTOR_FOR_INORDER_I(i, prod_element) { \
991 if (evenp) { \
992 r->prod_element[i] = a->mul_element[i * 2 + HI_IDX] * \
993 b->mul_element[i * 2 + HI_IDX]; \
994 } else { \
995 r->prod_element[i] = a->mul_element[i * 2 + LO_IDX] * \
996 b->mul_element[i * 2 + LO_IDX]; \
997 } \
998 } \
999 }
1000#define VMUL(suffix, mul_element, prod_element) \
1001 VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
1002 VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
1003VMUL(sb, s8, s16)
1004VMUL(sh, s16, s32)
1005VMUL(ub, u8, u16)
1006VMUL(uh, u16, u32)
1007#undef VMUL_DO
1008#undef VMUL
1009
d15f74fb
BS
1010void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1011 ppc_avr_t *c)
64654ded
BS
1012{
1013 ppc_avr_t result;
1014 int i;
1015
1016 VECTOR_FOR_INORDER_I(i, u8) {
1017 int s = c->u8[i] & 0x1f;
1018#if defined(HOST_WORDS_BIGENDIAN)
1019 int index = s & 0xf;
1020#else
1021 int index = 15 - (s & 0xf);
1022#endif
1023
1024 if (s & 0x10) {
1025 result.u8[i] = b->u8[index];
1026 } else {
1027 result.u8[i] = a->u8[index];
1028 }
1029 }
1030 *r = result;
1031}
1032
1033#if defined(HOST_WORDS_BIGENDIAN)
1034#define PKBIG 1
1035#else
1036#define PKBIG 0
1037#endif
1038void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1039{
1040 int i, j;
1041 ppc_avr_t result;
1042#if defined(HOST_WORDS_BIGENDIAN)
1043 const ppc_avr_t *x[2] = { a, b };
1044#else
1045 const ppc_avr_t *x[2] = { b, a };
1046#endif
1047
1048 VECTOR_FOR_INORDER_I(i, u64) {
1049 VECTOR_FOR_INORDER_I(j, u32) {
1050 uint32_t e = x[i]->u32[j];
1051
1052 result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
1053 ((e >> 6) & 0x3e0) |
1054 ((e >> 3) & 0x1f));
1055 }
1056 }
1057 *r = result;
1058}
1059
1060#define VPK(suffix, from, to, cvt, dosat) \
d15f74fb
BS
1061 void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r, \
1062 ppc_avr_t *a, ppc_avr_t *b) \
64654ded
BS
1063 { \
1064 int i; \
1065 int sat = 0; \
1066 ppc_avr_t result; \
1067 ppc_avr_t *a0 = PKBIG ? a : b; \
1068 ppc_avr_t *a1 = PKBIG ? b : a; \
1069 \
1070 VECTOR_FOR_INORDER_I(i, from) { \
1071 result.to[i] = cvt(a0->from[i], &sat); \
1072 result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat); \
1073 } \
1074 *r = result; \
1075 if (dosat && sat) { \
1076 env->vscr |= (1 << VSCR_SAT); \
1077 } \
1078 }
1079#define I(x, y) (x)
1080VPK(shss, s16, s8, cvtshsb, 1)
1081VPK(shus, s16, u8, cvtshub, 1)
1082VPK(swss, s32, s16, cvtswsh, 1)
1083VPK(swus, s32, u16, cvtswuh, 1)
1084VPK(uhus, u16, u8, cvtuhub, 1)
1085VPK(uwus, u32, u16, cvtuwuh, 1)
1086VPK(uhum, u16, u8, I, 0)
1087VPK(uwum, u32, u16, I, 0)
1088#undef I
1089#undef VPK
1090#undef PKBIG
1091
d15f74fb 1092void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
64654ded
BS
1093{
1094 int i;
1095
1096 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
ef9bd150 1097 r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
64654ded
BS
1098 }
1099}
1100
1101#define VRFI(suffix, rounding) \
d15f74fb
BS
1102 void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r, \
1103 ppc_avr_t *b) \
64654ded
BS
1104 { \
1105 int i; \
1106 float_status s = env->vec_status; \
1107 \
1108 set_float_rounding_mode(rounding, &s); \
1109 for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
ef9bd150 1110 r->f[i] = float32_round_to_int (b->f[i], &s); \
64654ded
BS
1111 } \
1112 }
1113VRFI(n, float_round_nearest_even)
1114VRFI(m, float_round_down)
1115VRFI(p, float_round_up)
1116VRFI(z, float_round_to_zero)
1117#undef VRFI
1118
1119#define VROTATE(suffix, element) \
1120 void helper_vrl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1121 { \
1122 int i; \
1123 \
1124 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1125 unsigned int mask = ((1 << \
1126 (3 + (sizeof(a->element[0]) >> 1))) \
1127 - 1); \
1128 unsigned int shift = b->element[i] & mask; \
1129 r->element[i] = (a->element[i] << shift) | \
1130 (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
1131 } \
1132 }
1133VROTATE(b, u8)
1134VROTATE(h, u16)
1135VROTATE(w, u32)
1136#undef VROTATE
1137
d15f74fb 1138void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
64654ded
BS
1139{
1140 int i;
1141
1142 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
ef9bd150 1143 float32 t = float32_sqrt(b->f[i], &env->vec_status);
64654ded 1144
ef9bd150 1145 r->f[i] = float32_div(float32_one, t, &env->vec_status);
64654ded
BS
1146 }
1147}
1148
d15f74fb
BS
1149void helper_vsel(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1150 ppc_avr_t *c)
64654ded
BS
1151{
1152 r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
1153 r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
1154}
1155
d15f74fb 1156void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
64654ded
BS
1157{
1158 int i;
1159
1160 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
ef9bd150 1161 r->f[i] = float32_exp2(b->f[i], &env->vec_status);
64654ded
BS
1162 }
1163}
1164
d15f74fb 1165void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
64654ded
BS
1166{
1167 int i;
1168
1169 for (i = 0; i < ARRAY_SIZE(r->f); i++) {
ef9bd150 1170 r->f[i] = float32_log2(b->f[i], &env->vec_status);
64654ded
BS
1171 }
1172}
1173
1174#if defined(HOST_WORDS_BIGENDIAN)
1175#define LEFT 0
1176#define RIGHT 1
1177#else
1178#define LEFT 1
1179#define RIGHT 0
1180#endif
1181/* The specification says that the results are undefined if all of the
1182 * shift counts are not identical. We check to make sure that they are
1183 * to conform to what real hardware appears to do. */
1184#define VSHIFT(suffix, leftp) \
1185 void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1186 { \
1187 int shift = b->u8[LO_IDX*15] & 0x7; \
1188 int doit = 1; \
1189 int i; \
1190 \
1191 for (i = 0; i < ARRAY_SIZE(r->u8); i++) { \
1192 doit = doit && ((b->u8[i] & 0x7) == shift); \
1193 } \
1194 if (doit) { \
1195 if (shift == 0) { \
1196 *r = *a; \
1197 } else if (leftp) { \
1198 uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \
1199 \
1200 r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \
1201 r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \
1202 } else { \
1203 uint64_t carry = a->u64[HI_IDX] << (64 - shift); \
1204 \
1205 r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \
1206 r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \
1207 } \
1208 } \
1209 }
1210VSHIFT(l, LEFT)
1211VSHIFT(r, RIGHT)
1212#undef VSHIFT
1213#undef LEFT
1214#undef RIGHT
1215
1216#define VSL(suffix, element) \
1217 void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1218 { \
1219 int i; \
1220 \
1221 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1222 unsigned int mask = ((1 << \
1223 (3 + (sizeof(a->element[0]) >> 1))) \
1224 - 1); \
1225 unsigned int shift = b->element[i] & mask; \
1226 \
1227 r->element[i] = a->element[i] << shift; \
1228 } \
1229 }
1230VSL(b, u8)
1231VSL(h, u16)
1232VSL(w, u32)
1233#undef VSL
1234
1235void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
1236{
1237 int sh = shift & 0xf;
1238 int i;
1239 ppc_avr_t result;
1240
1241#if defined(HOST_WORDS_BIGENDIAN)
1242 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1243 int index = sh + i;
1244 if (index > 0xf) {
1245 result.u8[i] = b->u8[index - 0x10];
1246 } else {
1247 result.u8[i] = a->u8[index];
1248 }
1249 }
1250#else
1251 for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1252 int index = (16 - sh) + i;
1253 if (index > 0xf) {
1254 result.u8[i] = a->u8[index - 0x10];
1255 } else {
1256 result.u8[i] = b->u8[index];
1257 }
1258 }
1259#endif
1260 *r = result;
1261}
1262
1263void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1264{
1265 int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
1266
1267#if defined(HOST_WORDS_BIGENDIAN)
1268 memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1269 memset(&r->u8[16-sh], 0, sh);
1270#else
1271 memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1272 memset(&r->u8[0], 0, sh);
1273#endif
1274}
1275
1276/* Experimental testing shows that hardware masks the immediate. */
1277#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
1278#if defined(HOST_WORDS_BIGENDIAN)
1279#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
1280#else
1281#define SPLAT_ELEMENT(element) \
1282 (ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element))
1283#endif
1284#define VSPLT(suffix, element) \
1285 void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
1286 { \
1287 uint32_t s = b->element[SPLAT_ELEMENT(element)]; \
1288 int i; \
1289 \
1290 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1291 r->element[i] = s; \
1292 } \
1293 }
1294VSPLT(b, u8)
1295VSPLT(h, u16)
1296VSPLT(w, u32)
1297#undef VSPLT
1298#undef SPLAT_ELEMENT
1299#undef _SPLAT_MASKED
1300
1301#define VSPLTI(suffix, element, splat_type) \
1302 void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat) \
1303 { \
1304 splat_type x = (int8_t)(splat << 3) >> 3; \
1305 int i; \
1306 \
1307 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1308 r->element[i] = x; \
1309 } \
1310 }
1311VSPLTI(b, s8, int8_t)
1312VSPLTI(h, s16, int16_t)
1313VSPLTI(w, s32, int32_t)
1314#undef VSPLTI
1315
1316#define VSR(suffix, element) \
1317 void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
1318 { \
1319 int i; \
1320 \
1321 for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
1322 unsigned int mask = ((1 << \
1323 (3 + (sizeof(a->element[0]) >> 1))) \
1324 - 1); \
1325 unsigned int shift = b->element[i] & mask; \
1326 \
1327 r->element[i] = a->element[i] >> shift; \
1328 } \
1329 }
1330VSR(ab, s8)
1331VSR(ah, s16)
1332VSR(aw, s32)
1333VSR(b, u8)
1334VSR(h, u16)
1335VSR(w, u32)
1336#undef VSR
1337
1338void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1339{
1340 int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf;
1341
1342#if defined(HOST_WORDS_BIGENDIAN)
1343 memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1344 memset(&r->u8[0], 0, sh);
1345#else
1346 memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1347 memset(&r->u8[16 - sh], 0, sh);
1348#endif
1349}
1350
1351void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1352{
1353 int i;
1354
1355 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1356 r->u32[i] = a->u32[i] >= b->u32[i];
1357 }
1358}
1359
d15f74fb 1360void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1361{
1362 int64_t t;
1363 int i, upper;
1364 ppc_avr_t result;
1365 int sat = 0;
1366
1367#if defined(HOST_WORDS_BIGENDIAN)
1368 upper = ARRAY_SIZE(r->s32)-1;
1369#else
1370 upper = 0;
1371#endif
1372 t = (int64_t)b->s32[upper];
1373 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1374 t += a->s32[i];
1375 result.s32[i] = 0;
1376 }
1377 result.s32[upper] = cvtsdsw(t, &sat);
1378 *r = result;
1379
1380 if (sat) {
1381 env->vscr |= (1 << VSCR_SAT);
1382 }
1383}
1384
d15f74fb 1385void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1386{
1387 int i, j, upper;
1388 ppc_avr_t result;
1389 int sat = 0;
1390
1391#if defined(HOST_WORDS_BIGENDIAN)
1392 upper = 1;
1393#else
1394 upper = 0;
1395#endif
1396 for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1397 int64_t t = (int64_t)b->s32[upper + i * 2];
1398
1399 result.u64[i] = 0;
1400 for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
1401 t += a->s32[2 * i + j];
1402 }
1403 result.s32[upper + i * 2] = cvtsdsw(t, &sat);
1404 }
1405
1406 *r = result;
1407 if (sat) {
1408 env->vscr |= (1 << VSCR_SAT);
1409 }
1410}
1411
d15f74fb 1412void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1413{
1414 int i, j;
1415 int sat = 0;
1416
1417 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1418 int64_t t = (int64_t)b->s32[i];
1419
1420 for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
1421 t += a->s8[4 * i + j];
1422 }
1423 r->s32[i] = cvtsdsw(t, &sat);
1424 }
1425
1426 if (sat) {
1427 env->vscr |= (1 << VSCR_SAT);
1428 }
1429}
1430
d15f74fb 1431void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1432{
1433 int sat = 0;
1434 int i;
1435
1436 for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1437 int64_t t = (int64_t)b->s32[i];
1438
1439 t += a->s16[2 * i] + a->s16[2 * i + 1];
1440 r->s32[i] = cvtsdsw(t, &sat);
1441 }
1442
1443 if (sat) {
1444 env->vscr |= (1 << VSCR_SAT);
1445 }
1446}
1447
d15f74fb 1448void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
64654ded
BS
1449{
1450 int i, j;
1451 int sat = 0;
1452
1453 for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1454 uint64_t t = (uint64_t)b->u32[i];
1455
1456 for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
1457 t += a->u8[4 * i + j];
1458 }
1459 r->u32[i] = cvtuduw(t, &sat);
1460 }
1461
1462 if (sat) {
1463 env->vscr |= (1 << VSCR_SAT);
1464 }
1465}
1466
1467#if defined(HOST_WORDS_BIGENDIAN)
1468#define UPKHI 1
1469#define UPKLO 0
1470#else
1471#define UPKHI 0
1472#define UPKLO 1
1473#endif
1474#define VUPKPX(suffix, hi) \
1475 void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \
1476 { \
1477 int i; \
1478 ppc_avr_t result; \
1479 \
1480 for (i = 0; i < ARRAY_SIZE(r->u32); i++) { \
1481 uint16_t e = b->u16[hi ? i : i+4]; \
1482 uint8_t a = (e >> 15) ? 0xff : 0; \
1483 uint8_t r = (e >> 10) & 0x1f; \
1484 uint8_t g = (e >> 5) & 0x1f; \
1485 uint8_t b = e & 0x1f; \
1486 \
1487 result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b; \
1488 } \
1489 *r = result; \
1490 }
1491VUPKPX(lpx, UPKLO)
1492VUPKPX(hpx, UPKHI)
1493#undef VUPKPX
1494
1495#define VUPK(suffix, unpacked, packee, hi) \
1496 void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b) \
1497 { \
1498 int i; \
1499 ppc_avr_t result; \
1500 \
1501 if (hi) { \
1502 for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) { \
1503 result.unpacked[i] = b->packee[i]; \
1504 } \
1505 } else { \
1506 for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
1507 i++) { \
1508 result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
1509 } \
1510 } \
1511 *r = result; \
1512 }
1513VUPK(hsb, s16, s8, UPKHI)
1514VUPK(hsh, s32, s16, UPKHI)
1515VUPK(lsb, s16, s8, UPKLO)
1516VUPK(lsh, s32, s16, UPKLO)
1517#undef VUPK
1518#undef UPKHI
1519#undef UPKLO
1520
64654ded
BS
1521#undef VECTOR_FOR_INORDER_I
1522#undef HI_IDX
1523#undef LO_IDX
1524
1525/*****************************************************************************/
1526/* SPE extension helpers */
1527/* Use a table to make this quicker */
ea6c0dac 1528static const uint8_t hbrev[16] = {
64654ded
BS
1529 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1530 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1531};
1532
1533static inline uint8_t byte_reverse(uint8_t val)
1534{
1535 return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1536}
1537
1538static inline uint32_t word_reverse(uint32_t val)
1539{
1540 return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1541 (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1542}
1543
1544#define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
1545target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
1546{
1547 uint32_t a, b, d, mask;
1548
1549 mask = UINT32_MAX >> (32 - MASKBITS);
1550 a = arg1 & mask;
1551 b = arg2 & mask;
1552 d = word_reverse(1 + word_reverse(a | ~b));
1553 return (arg1 & ~mask) | (d & b);
1554}
1555
1556uint32_t helper_cntlsw32(uint32_t val)
1557{
1558 if (val & 0x80000000) {
1559 return clz32(~val);
1560 } else {
1561 return clz32(val);
1562 }
1563}
1564
1565uint32_t helper_cntlzw32(uint32_t val)
1566{
1567 return clz32(val);
1568}
1569
1570/* 440 specific */
d15f74fb
BS
1571target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high,
1572 target_ulong low, uint32_t update_Rc)
64654ded
BS
1573{
1574 target_ulong mask;
1575 int i;
1576
1577 i = 1;
1578 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1579 if ((high & mask) == 0) {
1580 if (update_Rc) {
1581 env->crf[0] = 0x4;
1582 }
1583 goto done;
1584 }
1585 i++;
1586 }
1587 for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1588 if ((low & mask) == 0) {
1589 if (update_Rc) {
1590 env->crf[0] = 0x8;
1591 }
1592 goto done;
1593 }
1594 i++;
1595 }
1596 if (update_Rc) {
1597 env->crf[0] = 0x2;
1598 }
1599 done:
1600 env->xer = (env->xer & ~0x7F) | i;
1601 if (update_Rc) {
1602 env->crf[0] |= xer_so;
1603 }
1604 return i;
1605}
This page took 0.416 seconds and 4 git commands to generate.