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