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