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