Statistics
| Branch: | Revision:

root / target-ppc / int_helper.c @ 60925d26

History | View | Annotate | Download (53.2 kB)

1
/*
2
 *  PowerPC integer and vector emulation helpers for QEMU.
3
 *
4
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include "cpu.h"
20
#include "qemu/host-utils.h"
21
#include "helper.h"
22

    
23
#include "helper_regs.h"
24
/*****************************************************************************/
25
/* Fixed point operations helpers */
26
#if defined(TARGET_PPC64)
27

    
28
/* multiply high word */
29
uint64_t helper_mulhd(uint64_t arg1, uint64_t arg2)
30
{
31
    uint64_t tl, th;
32

    
33
    muls64(&tl, &th, arg1, arg2);
34
    return th;
35
}
36

    
37
/* multiply high word unsigned */
38
uint64_t helper_mulhdu(uint64_t arg1, uint64_t arg2)
39
{
40
    uint64_t tl, th;
41

    
42
    mulu64(&tl, &th, arg1, arg2);
43
    return th;
44
}
45

    
46
uint64_t helper_mulldo(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
47
{
48
    int64_t th;
49
    uint64_t tl;
50

    
51
    muls64(&tl, (uint64_t *)&th, arg1, arg2);
52
    /* If th != 0 && th != -1, then we had an overflow */
53
    if (likely((uint64_t)(th + 1) <= 1)) {
54
        env->xer &= ~(1 << XER_OV);
55
    } else {
56
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
57
    }
58
    return (int64_t)tl;
59
}
60
#endif
61

    
62
target_ulong helper_cntlzw(target_ulong t)
63
{
64
    return clz32(t);
65
}
66

    
67
#if defined(TARGET_PPC64)
68
target_ulong helper_cntlzd(target_ulong t)
69
{
70
    return clz64(t);
71
}
72
#endif
73

    
74
/* shift right arithmetic helper */
75
target_ulong helper_sraw(CPUPPCState *env, target_ulong value,
76
                         target_ulong shift)
77
{
78
    int32_t ret;
79

    
80
    if (likely(!(shift & 0x20))) {
81
        if (likely((uint32_t)shift != 0)) {
82
            shift &= 0x1f;
83
            ret = (int32_t)value >> shift;
84
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
85
                env->xer &= ~(1 << XER_CA);
86
            } else {
87
                env->xer |= (1 << XER_CA);
88
            }
89
        } else {
90
            ret = (int32_t)value;
91
            env->xer &= ~(1 << XER_CA);
92
        }
93
    } else {
94
        ret = (int32_t)value >> 31;
95
        if (ret) {
96
            env->xer |= (1 << XER_CA);
97
        } else {
98
            env->xer &= ~(1 << XER_CA);
99
        }
100
    }
101
    return (target_long)ret;
102
}
103

    
104
#if defined(TARGET_PPC64)
105
target_ulong helper_srad(CPUPPCState *env, target_ulong value,
106
                         target_ulong shift)
107
{
108
    int64_t ret;
109

    
110
    if (likely(!(shift & 0x40))) {
111
        if (likely((uint64_t)shift != 0)) {
112
            shift &= 0x3f;
113
            ret = (int64_t)value >> shift;
114
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
115
                env->xer &= ~(1 << XER_CA);
116
            } else {
117
                env->xer |= (1 << XER_CA);
118
            }
119
        } else {
120
            ret = (int64_t)value;
121
            env->xer &= ~(1 << XER_CA);
122
        }
123
    } else {
124
        ret = (int64_t)value >> 63;
125
        if (ret) {
126
            env->xer |= (1 << XER_CA);
127
        } else {
128
            env->xer &= ~(1 << XER_CA);
129
        }
130
    }
131
    return ret;
132
}
133
#endif
134

    
135
#if defined(TARGET_PPC64)
136
target_ulong helper_popcntb(target_ulong val)
137
{
138
    val = (val & 0x5555555555555555ULL) + ((val >>  1) &
139
                                           0x5555555555555555ULL);
140
    val = (val & 0x3333333333333333ULL) + ((val >>  2) &
141
                                           0x3333333333333333ULL);
142
    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
143
                                           0x0f0f0f0f0f0f0f0fULL);
144
    return val;
145
}
146

    
147
target_ulong helper_popcntw(target_ulong val)
148
{
149
    val = (val & 0x5555555555555555ULL) + ((val >>  1) &
150
                                           0x5555555555555555ULL);
151
    val = (val & 0x3333333333333333ULL) + ((val >>  2) &
152
                                           0x3333333333333333ULL);
153
    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) &
154
                                           0x0f0f0f0f0f0f0f0fULL);
155
    val = (val & 0x00ff00ff00ff00ffULL) + ((val >>  8) &
156
                                           0x00ff00ff00ff00ffULL);
157
    val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) &
158
                                           0x0000ffff0000ffffULL);
159
    return val;
160
}
161

    
162
target_ulong helper_popcntd(target_ulong val)
163
{
164
    return ctpop64(val);
165
}
166
#else
167
target_ulong helper_popcntb(target_ulong val)
168
{
169
    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
170
    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
171
    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
172
    return val;
173
}
174

    
175
target_ulong helper_popcntw(target_ulong val)
176
{
177
    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
178
    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
179
    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
180
    val = (val & 0x00ff00ff) + ((val >>  8) & 0x00ff00ff);
181
    val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
182
    return val;
183
}
184
#endif
185

    
186
/*****************************************************************************/
187
/* PowerPC 601 specific instructions (POWER bridge) */
188
target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2)
189
{
190
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
191

    
192
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
193
        (int32_t)arg2 == 0) {
194
        env->spr[SPR_MQ] = 0;
195
        return INT32_MIN;
196
    } else {
197
        env->spr[SPR_MQ] = tmp % arg2;
198
        return  tmp / (int32_t)arg2;
199
    }
200
}
201

    
202
target_ulong helper_divo(CPUPPCState *env, target_ulong arg1,
203
                         target_ulong arg2)
204
{
205
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
206

    
207
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
208
        (int32_t)arg2 == 0) {
209
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
210
        env->spr[SPR_MQ] = 0;
211
        return INT32_MIN;
212
    } else {
213
        env->spr[SPR_MQ] = tmp % arg2;
214
        tmp /= (int32_t)arg2;
215
        if ((int32_t)tmp != tmp) {
216
            env->xer |= (1 << XER_OV) | (1 << XER_SO);
217
        } else {
218
            env->xer &= ~(1 << XER_OV);
219
        }
220
        return tmp;
221
    }
222
}
223

    
224
target_ulong helper_divs(CPUPPCState *env, target_ulong arg1,
225
                         target_ulong arg2)
226
{
227
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
228
        (int32_t)arg2 == 0) {
229
        env->spr[SPR_MQ] = 0;
230
        return INT32_MIN;
231
    } else {
232
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
233
        return (int32_t)arg1 / (int32_t)arg2;
234
    }
235
}
236

    
237
target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
238
                          target_ulong arg2)
239
{
240
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
241
        (int32_t)arg2 == 0) {
242
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
243
        env->spr[SPR_MQ] = 0;
244
        return INT32_MIN;
245
    } else {
246
        env->xer &= ~(1 << XER_OV);
247
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
248
        return (int32_t)arg1 / (int32_t)arg2;
249
    }
250
}
251

    
252
/*****************************************************************************/
253
/* 602 specific instructions */
254
/* mfrom is the most crazy instruction ever seen, imho ! */
255
/* Real implementation uses a ROM table. Do the same */
256
/* Extremely decomposed:
257
 *                      -arg / 256
258
 * return 256 * log10(10           + 1.0) + 0.5
259
 */
260
#if !defined(CONFIG_USER_ONLY)
261
target_ulong helper_602_mfrom(target_ulong arg)
262
{
263
    if (likely(arg < 602)) {
264
#include "mfrom_table.c"
265
        return mfrom_ROM_table[arg];
266
    } else {
267
        return 0;
268
    }
269
}
270
#endif
271

    
272
/*****************************************************************************/
273
/* Altivec extension helpers */
274
#if defined(HOST_WORDS_BIGENDIAN)
275
#define HI_IDX 0
276
#define LO_IDX 1
277
#else
278
#define HI_IDX 1
279
#define LO_IDX 0
280
#endif
281

    
282
#if defined(HOST_WORDS_BIGENDIAN)
283
#define VECTOR_FOR_INORDER_I(index, element)                    \
284
    for (index = 0; index < ARRAY_SIZE(r->element); index++)
285
#else
286
#define VECTOR_FOR_INORDER_I(index, element)                    \
287
    for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
288
#endif
289

    
290
/* Saturating arithmetic helpers.  */
291
#define SATCVT(from, to, from_type, to_type, min, max)          \
292
    static inline to_type cvt##from##to(from_type x, int *sat)  \
293
    {                                                           \
294
        to_type r;                                              \
295
                                                                \
296
        if (x < (from_type)min) {                               \
297
            r = min;                                            \
298
            *sat = 1;                                           \
299
        } else if (x > (from_type)max) {                        \
300
            r = max;                                            \
301
            *sat = 1;                                           \
302
        } else {                                                \
303
            r = x;                                              \
304
        }                                                       \
305
        return r;                                               \
306
    }
307
#define SATCVTU(from, to, from_type, to_type, min, max)         \
308
    static inline to_type cvt##from##to(from_type x, int *sat)  \
309
    {                                                           \
310
        to_type r;                                              \
311
                                                                \
312
        if (x > (from_type)max) {                               \
313
            r = max;                                            \
314
            *sat = 1;                                           \
315
        } else {                                                \
316
            r = x;                                              \
317
        }                                                       \
318
        return r;                                               \
319
    }
320
SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX)
321
SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX)
322
SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX)
323

    
324
SATCVTU(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX)
325
SATCVTU(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX)
326
SATCVTU(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX)
327
SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX)
328
SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX)
329
SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX)
330
#undef SATCVT
331
#undef SATCVTU
332

    
333
void helper_lvsl(ppc_avr_t *r, target_ulong sh)
334
{
335
    int i, j = (sh & 0xf);
336

    
337
    VECTOR_FOR_INORDER_I(i, u8) {
338
        r->u8[i] = j++;
339
    }
340
}
341

    
342
void helper_lvsr(ppc_avr_t *r, target_ulong sh)
343
{
344
    int i, j = 0x10 - (sh & 0xf);
345

    
346
    VECTOR_FOR_INORDER_I(i, u8) {
347
        r->u8[i] = j++;
348
    }
349
}
350

    
351
void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
352
{
353
#if defined(HOST_WORDS_BIGENDIAN)
354
    env->vscr = r->u32[3];
355
#else
356
    env->vscr = r->u32[0];
357
#endif
358
    set_flush_to_zero(vscr_nj, &env->vec_status);
359
}
360

    
361
void helper_vaddcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
362
{
363
    int i;
364

    
365
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
366
        r->u32[i] = ~a->u32[i] < b->u32[i];
367
    }
368
}
369

    
370
#define VARITH_DO(name, op, element)                                    \
371
    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
372
    {                                                                   \
373
        int i;                                                          \
374
                                                                        \
375
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
376
            r->element[i] = a->element[i] op b->element[i];             \
377
        }                                                               \
378
    }
379
#define VARITH(suffix, element)                 \
380
    VARITH_DO(add##suffix, +, element)          \
381
    VARITH_DO(sub##suffix, -, element)
382
VARITH(ubm, u8)
383
VARITH(uhm, u16)
384
VARITH(uwm, u32)
385
#undef VARITH_DO
386
#undef VARITH
387

    
388
#define VARITHFP(suffix, func)                                          \
389
    void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
390
                          ppc_avr_t *b)                                 \
391
    {                                                                   \
392
        int i;                                                          \
393
                                                                        \
394
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
395
            r->f[i] = func(a->f[i], b->f[i], &env->vec_status);         \
396
        }                                                               \
397
    }
398
VARITHFP(addfp, float32_add)
399
VARITHFP(subfp, float32_sub)
400
VARITHFP(minfp, float32_min)
401
VARITHFP(maxfp, float32_max)
402
#undef VARITHFP
403

    
404
#define VARITHFPFMA(suffix, type)                                       \
405
    void helper_v##suffix(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, \
406
                           ppc_avr_t *b, ppc_avr_t *c)                  \
407
    {                                                                   \
408
        int i;                                                          \
409
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
410
            r->f[i] = float32_muladd(a->f[i], c->f[i], b->f[i],         \
411
                                     type, &env->vec_status);           \
412
        }                                                               \
413
    }
414
VARITHFPFMA(maddfp, 0);
415
VARITHFPFMA(nmsubfp, float_muladd_negate_result | float_muladd_negate_c);
416
#undef VARITHFPFMA
417

    
418
#define VARITHSAT_CASE(type, op, cvt, element)                          \
419
    {                                                                   \
420
        type result = (type)a->element[i] op (type)b->element[i];       \
421
        r->element[i] = cvt(result, &sat);                              \
422
    }
423

    
424
#define VARITHSAT_DO(name, op, optype, cvt, element)                    \
425
    void helper_v##name(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,   \
426
                        ppc_avr_t *b)                                   \
427
    {                                                                   \
428
        int sat = 0;                                                    \
429
        int i;                                                          \
430
                                                                        \
431
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
432
            switch (sizeof(r->element[0])) {                            \
433
            case 1:                                                     \
434
                VARITHSAT_CASE(optype, op, cvt, element);               \
435
                break;                                                  \
436
            case 2:                                                     \
437
                VARITHSAT_CASE(optype, op, cvt, element);               \
438
                break;                                                  \
439
            case 4:                                                     \
440
                VARITHSAT_CASE(optype, op, cvt, element);               \
441
                break;                                                  \
442
            }                                                           \
443
        }                                                               \
444
        if (sat) {                                                      \
445
            env->vscr |= (1 << VSCR_SAT);                               \
446
        }                                                               \
447
    }
448
#define VARITHSAT_SIGNED(suffix, element, optype, cvt)          \
449
    VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element)      \
450
    VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
451
#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt)        \
452
    VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element)      \
453
    VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
454
VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
455
VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
456
VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
457
VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
458
VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
459
VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
460
#undef VARITHSAT_CASE
461
#undef VARITHSAT_DO
462
#undef VARITHSAT_SIGNED
463
#undef VARITHSAT_UNSIGNED
464

    
465
#define VAVG_DO(name, element, etype)                                   \
466
    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
467
    {                                                                   \
468
        int i;                                                          \
469
                                                                        \
470
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
471
            etype x = (etype)a->element[i] + (etype)b->element[i] + 1;  \
472
            r->element[i] = x >> 1;                                     \
473
        }                                                               \
474
    }
475

    
476
#define VAVG(type, signed_element, signed_type, unsigned_element,       \
477
             unsigned_type)                                             \
478
    VAVG_DO(avgs##type, signed_element, signed_type)                    \
479
    VAVG_DO(avgu##type, unsigned_element, unsigned_type)
480
VAVG(b, s8, int16_t, u8, uint16_t)
481
VAVG(h, s16, int32_t, u16, uint32_t)
482
VAVG(w, s32, int64_t, u32, uint64_t)
483
#undef VAVG_DO
484
#undef VAVG
485

    
486
#define VCF(suffix, cvt, element)                                       \
487
    void helper_vcf##suffix(CPUPPCState *env, ppc_avr_t *r,             \
488
                            ppc_avr_t *b, uint32_t uim)                 \
489
    {                                                                   \
490
        int i;                                                          \
491
                                                                        \
492
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
493
            float32 t = cvt(b->element[i], &env->vec_status);           \
494
            r->f[i] = float32_scalbn(t, -uim, &env->vec_status);        \
495
        }                                                               \
496
    }
497
VCF(ux, uint32_to_float32, u32)
498
VCF(sx, int32_to_float32, s32)
499
#undef VCF
500

    
501
#define VCMP_DO(suffix, compare, element, record)                       \
502
    void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r,            \
503
                             ppc_avr_t *a, ppc_avr_t *b)                \
504
    {                                                                   \
505
        uint32_t ones = (uint32_t)-1;                                   \
506
        uint32_t all = ones;                                            \
507
        uint32_t none = 0;                                              \
508
        int i;                                                          \
509
                                                                        \
510
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
511
            uint32_t result = (a->element[i] compare b->element[i] ?    \
512
                               ones : 0x0);                             \
513
            switch (sizeof(a->element[0])) {                            \
514
            case 4:                                                     \
515
                r->u32[i] = result;                                     \
516
                break;                                                  \
517
            case 2:                                                     \
518
                r->u16[i] = result;                                     \
519
                break;                                                  \
520
            case 1:                                                     \
521
                r->u8[i] = result;                                      \
522
                break;                                                  \
523
            }                                                           \
524
            all &= result;                                              \
525
            none |= result;                                             \
526
        }                                                               \
527
        if (record) {                                                   \
528
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
529
        }                                                               \
530
    }
531
#define VCMP(suffix, compare, element)          \
532
    VCMP_DO(suffix, compare, element, 0)        \
533
    VCMP_DO(suffix##_dot, compare, element, 1)
534
VCMP(equb, ==, u8)
535
VCMP(equh, ==, u16)
536
VCMP(equw, ==, u32)
537
VCMP(gtub, >, u8)
538
VCMP(gtuh, >, u16)
539
VCMP(gtuw, >, u32)
540
VCMP(gtsb, >, s8)
541
VCMP(gtsh, >, s16)
542
VCMP(gtsw, >, s32)
543
#undef VCMP_DO
544
#undef VCMP
545

    
546
#define VCMPFP_DO(suffix, compare, order, record)                       \
547
    void helper_vcmp##suffix(CPUPPCState *env, ppc_avr_t *r,            \
548
                             ppc_avr_t *a, ppc_avr_t *b)                \
549
    {                                                                   \
550
        uint32_t ones = (uint32_t)-1;                                   \
551
        uint32_t all = ones;                                            \
552
        uint32_t none = 0;                                              \
553
        int i;                                                          \
554
                                                                        \
555
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
556
            uint32_t result;                                            \
557
            int rel = float32_compare_quiet(a->f[i], b->f[i],           \
558
                                            &env->vec_status);          \
559
            if (rel == float_relation_unordered) {                      \
560
                result = 0;                                             \
561
            } else if (rel compare order) {                             \
562
                result = ones;                                          \
563
            } else {                                                    \
564
                result = 0;                                             \
565
            }                                                           \
566
            r->u32[i] = result;                                         \
567
            all &= result;                                              \
568
            none |= result;                                             \
569
        }                                                               \
570
        if (record) {                                                   \
571
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
572
        }                                                               \
573
    }
574
#define VCMPFP(suffix, compare, order)          \
575
    VCMPFP_DO(suffix, compare, order, 0)        \
576
    VCMPFP_DO(suffix##_dot, compare, order, 1)
577
VCMPFP(eqfp, ==, float_relation_equal)
578
VCMPFP(gefp, !=, float_relation_less)
579
VCMPFP(gtfp, ==, float_relation_greater)
580
#undef VCMPFP_DO
581
#undef VCMPFP
582

    
583
static inline void vcmpbfp_internal(CPUPPCState *env, ppc_avr_t *r,
584
                                    ppc_avr_t *a, ppc_avr_t *b, int record)
585
{
586
    int i;
587
    int all_in = 0;
588

    
589
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
590
        int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
591
        if (le_rel == float_relation_unordered) {
592
            r->u32[i] = 0xc0000000;
593
            /* ALL_IN does not need to be updated here.  */
594
        } else {
595
            float32 bneg = float32_chs(b->f[i]);
596
            int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
597
            int le = le_rel != float_relation_greater;
598
            int ge = ge_rel != float_relation_less;
599

    
600
            r->u32[i] = ((!le) << 31) | ((!ge) << 30);
601
            all_in |= (!le | !ge);
602
        }
603
    }
604
    if (record) {
605
        env->crf[6] = (all_in == 0) << 1;
606
    }
607
}
608

    
609
void helper_vcmpbfp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
610
{
611
    vcmpbfp_internal(env, r, a, b, 0);
612
}
613

    
614
void helper_vcmpbfp_dot(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
615
                        ppc_avr_t *b)
616
{
617
    vcmpbfp_internal(env, r, a, b, 1);
618
}
619

    
620
#define VCT(suffix, satcvt, element)                                    \
621
    void helper_vct##suffix(CPUPPCState *env, ppc_avr_t *r,             \
622
                            ppc_avr_t *b, uint32_t uim)                 \
623
    {                                                                   \
624
        int i;                                                          \
625
        int sat = 0;                                                    \
626
        float_status s = env->vec_status;                               \
627
                                                                        \
628
        set_float_rounding_mode(float_round_to_zero, &s);               \
629
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
630
            if (float32_is_any_nan(b->f[i])) {                          \
631
                r->element[i] = 0;                                      \
632
            } else {                                                    \
633
                float64 t = float32_to_float64(b->f[i], &s);            \
634
                int64_t j;                                              \
635
                                                                        \
636
                t = float64_scalbn(t, uim, &s);                         \
637
                j = float64_to_int64(t, &s);                            \
638
                r->element[i] = satcvt(j, &sat);                        \
639
            }                                                           \
640
        }                                                               \
641
        if (sat) {                                                      \
642
            env->vscr |= (1 << VSCR_SAT);                               \
643
        }                                                               \
644
    }
645
VCT(uxs, cvtsduw, u32)
646
VCT(sxs, cvtsdsw, s32)
647
#undef VCT
648

    
649
void helper_vmhaddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
650
                      ppc_avr_t *b, ppc_avr_t *c)
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];
657
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
658

    
659
        r->s16[i] = cvtswsh(t, &sat);
660
    }
661

    
662
    if (sat) {
663
        env->vscr |= (1 << VSCR_SAT);
664
    }
665
}
666

    
667
void helper_vmhraddshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
668
                       ppc_avr_t *b, ppc_avr_t *c)
669
{
670
    int sat = 0;
671
    int i;
672

    
673
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
674
        int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
675
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
676
        r->s16[i] = cvtswsh(t, &sat);
677
    }
678

    
679
    if (sat) {
680
        env->vscr |= (1 << VSCR_SAT);
681
    }
682
}
683

    
684
#define VMINMAX_DO(name, compare, element)                              \
685
    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
686
    {                                                                   \
687
        int i;                                                          \
688
                                                                        \
689
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
690
            if (a->element[i] compare b->element[i]) {                  \
691
                r->element[i] = b->element[i];                          \
692
            } else {                                                    \
693
                r->element[i] = a->element[i];                          \
694
            }                                                           \
695
        }                                                               \
696
    }
697
#define VMINMAX(suffix, element)                \
698
    VMINMAX_DO(min##suffix, >, element)         \
699
    VMINMAX_DO(max##suffix, <, element)
700
VMINMAX(sb, s8)
701
VMINMAX(sh, s16)
702
VMINMAX(sw, s32)
703
VMINMAX(ub, u8)
704
VMINMAX(uh, u16)
705
VMINMAX(uw, u32)
706
#undef VMINMAX_DO
707
#undef VMINMAX
708

    
709
void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
710
{
711
    int i;
712

    
713
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
714
        int32_t prod = a->s16[i] * b->s16[i];
715
        r->s16[i] = (int16_t) (prod + c->s16[i]);
716
    }
717
}
718

    
719
#define VMRG_DO(name, element, highp)                                   \
720
    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
721
    {                                                                   \
722
        ppc_avr_t result;                                               \
723
        int i;                                                          \
724
        size_t n_elems = ARRAY_SIZE(r->element);                        \
725
                                                                        \
726
        for (i = 0; i < n_elems / 2; i++) {                             \
727
            if (highp) {                                                \
728
                result.element[i*2+HI_IDX] = a->element[i];             \
729
                result.element[i*2+LO_IDX] = b->element[i];             \
730
            } else {                                                    \
731
                result.element[n_elems - i * 2 - (1 + HI_IDX)] =        \
732
                    b->element[n_elems - i - 1];                        \
733
                result.element[n_elems - i * 2 - (1 + LO_IDX)] =        \
734
                    a->element[n_elems - i - 1];                        \
735
            }                                                           \
736
        }                                                               \
737
        *r = result;                                                    \
738
    }
739
#if defined(HOST_WORDS_BIGENDIAN)
740
#define MRGHI 0
741
#define MRGLO 1
742
#else
743
#define MRGHI 1
744
#define MRGLO 0
745
#endif
746
#define VMRG(suffix, element)                   \
747
    VMRG_DO(mrgl##suffix, element, MRGHI)       \
748
    VMRG_DO(mrgh##suffix, element, MRGLO)
749
VMRG(b, u8)
750
VMRG(h, u16)
751
VMRG(w, u32)
752
#undef VMRG_DO
753
#undef VMRG
754
#undef MRGHI
755
#undef MRGLO
756

    
757
void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
758
                     ppc_avr_t *b, ppc_avr_t *c)
759
{
760
    int32_t prod[16];
761
    int i;
762

    
763
    for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
764
        prod[i] = (int32_t)a->s8[i] * b->u8[i];
765
    }
766

    
767
    VECTOR_FOR_INORDER_I(i, s32) {
768
        r->s32[i] = c->s32[i] + prod[4 * i] + prod[4 * i + 1] +
769
            prod[4 * i + 2] + prod[4 * i + 3];
770
    }
771
}
772

    
773
void helper_vmsumshm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
774
                     ppc_avr_t *b, ppc_avr_t *c)
775
{
776
    int32_t prod[8];
777
    int i;
778

    
779
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
780
        prod[i] = a->s16[i] * b->s16[i];
781
    }
782

    
783
    VECTOR_FOR_INORDER_I(i, s32) {
784
        r->s32[i] = c->s32[i] + prod[2 * i] + prod[2 * i + 1];
785
    }
786
}
787

    
788
void helper_vmsumshs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
789
                     ppc_avr_t *b, ppc_avr_t *c)
790
{
791
    int32_t prod[8];
792
    int i;
793
    int sat = 0;
794

    
795
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
796
        prod[i] = (int32_t)a->s16[i] * b->s16[i];
797
    }
798

    
799
    VECTOR_FOR_INORDER_I(i, s32) {
800
        int64_t t = (int64_t)c->s32[i] + prod[2 * i] + prod[2 * i + 1];
801

    
802
        r->u32[i] = cvtsdsw(t, &sat);
803
    }
804

    
805
    if (sat) {
806
        env->vscr |= (1 << VSCR_SAT);
807
    }
808
}
809

    
810
void helper_vmsumubm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
811
                     ppc_avr_t *b, ppc_avr_t *c)
812
{
813
    uint16_t prod[16];
814
    int i;
815

    
816
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
817
        prod[i] = a->u8[i] * b->u8[i];
818
    }
819

    
820
    VECTOR_FOR_INORDER_I(i, u32) {
821
        r->u32[i] = c->u32[i] + prod[4 * i] + prod[4 * i + 1] +
822
            prod[4 * i + 2] + prod[4 * i + 3];
823
    }
824
}
825

    
826
void helper_vmsumuhm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
827
                     ppc_avr_t *b, ppc_avr_t *c)
828
{
829
    uint32_t prod[8];
830
    int i;
831

    
832
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
833
        prod[i] = a->u16[i] * b->u16[i];
834
    }
835

    
836
    VECTOR_FOR_INORDER_I(i, u32) {
837
        r->u32[i] = c->u32[i] + prod[2 * i] + prod[2 * i + 1];
838
    }
839
}
840

    
841
void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
842
                     ppc_avr_t *b, ppc_avr_t *c)
843
{
844
    uint32_t prod[8];
845
    int i;
846
    int sat = 0;
847

    
848
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
849
        prod[i] = a->u16[i] * b->u16[i];
850
    }
851

    
852
    VECTOR_FOR_INORDER_I(i, s32) {
853
        uint64_t t = (uint64_t)c->u32[i] + prod[2 * i] + prod[2 * i + 1];
854

    
855
        r->u32[i] = cvtuduw(t, &sat);
856
    }
857

    
858
    if (sat) {
859
        env->vscr |= (1 << VSCR_SAT);
860
    }
861
}
862

    
863
#define VMUL_DO(name, mul_element, prod_element, evenp)                 \
864
    void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)       \
865
    {                                                                   \
866
        int i;                                                          \
867
                                                                        \
868
        VECTOR_FOR_INORDER_I(i, prod_element) {                         \
869
            if (evenp) {                                                \
870
                r->prod_element[i] = a->mul_element[i * 2 + HI_IDX] *   \
871
                    b->mul_element[i * 2 + HI_IDX];                     \
872
            } else {                                                    \
873
                r->prod_element[i] = a->mul_element[i * 2 + LO_IDX] *   \
874
                    b->mul_element[i * 2 + LO_IDX];                     \
875
            }                                                           \
876
        }                                                               \
877
    }
878
#define VMUL(suffix, mul_element, prod_element)         \
879
    VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
880
    VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
881
VMUL(sb, s8, s16)
882
VMUL(sh, s16, s32)
883
VMUL(ub, u8, u16)
884
VMUL(uh, u16, u32)
885
#undef VMUL_DO
886
#undef VMUL
887

    
888
void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
889
                  ppc_avr_t *c)
890
{
891
    ppc_avr_t result;
892
    int i;
893

    
894
    VECTOR_FOR_INORDER_I(i, u8) {
895
        int s = c->u8[i] & 0x1f;
896
#if defined(HOST_WORDS_BIGENDIAN)
897
        int index = s & 0xf;
898
#else
899
        int index = 15 - (s & 0xf);
900
#endif
901

    
902
        if (s & 0x10) {
903
            result.u8[i] = b->u8[index];
904
        } else {
905
            result.u8[i] = a->u8[index];
906
        }
907
    }
908
    *r = result;
909
}
910

    
911
#if defined(HOST_WORDS_BIGENDIAN)
912
#define PKBIG 1
913
#else
914
#define PKBIG 0
915
#endif
916
void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
917
{
918
    int i, j;
919
    ppc_avr_t result;
920
#if defined(HOST_WORDS_BIGENDIAN)
921
    const ppc_avr_t *x[2] = { a, b };
922
#else
923
    const ppc_avr_t *x[2] = { b, a };
924
#endif
925

    
926
    VECTOR_FOR_INORDER_I(i, u64) {
927
        VECTOR_FOR_INORDER_I(j, u32) {
928
            uint32_t e = x[i]->u32[j];
929

    
930
            result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
931
                                 ((e >> 6) & 0x3e0) |
932
                                 ((e >> 3) & 0x1f));
933
        }
934
    }
935
    *r = result;
936
}
937

    
938
#define VPK(suffix, from, to, cvt, dosat)                               \
939
    void helper_vpk##suffix(CPUPPCState *env, ppc_avr_t *r,             \
940
                            ppc_avr_t *a, ppc_avr_t *b)                 \
941
    {                                                                   \
942
        int i;                                                          \
943
        int sat = 0;                                                    \
944
        ppc_avr_t result;                                               \
945
        ppc_avr_t *a0 = PKBIG ? a : b;                                  \
946
        ppc_avr_t *a1 = PKBIG ? b : a;                                  \
947
                                                                        \
948
        VECTOR_FOR_INORDER_I(i, from) {                                 \
949
            result.to[i] = cvt(a0->from[i], &sat);                      \
950
            result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);  \
951
        }                                                               \
952
        *r = result;                                                    \
953
        if (dosat && sat) {                                             \
954
            env->vscr |= (1 << VSCR_SAT);                               \
955
        }                                                               \
956
    }
957
#define I(x, y) (x)
958
VPK(shss, s16, s8, cvtshsb, 1)
959
VPK(shus, s16, u8, cvtshub, 1)
960
VPK(swss, s32, s16, cvtswsh, 1)
961
VPK(swus, s32, u16, cvtswuh, 1)
962
VPK(uhus, u16, u8, cvtuhub, 1)
963
VPK(uwus, u32, u16, cvtuwuh, 1)
964
VPK(uhum, u16, u8, I, 0)
965
VPK(uwum, u32, u16, I, 0)
966
#undef I
967
#undef VPK
968
#undef PKBIG
969

    
970
void helper_vrefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
971
{
972
    int i;
973

    
974
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
975
        r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
976
    }
977
}
978

    
979
#define VRFI(suffix, rounding)                                  \
980
    void helper_vrfi##suffix(CPUPPCState *env, ppc_avr_t *r,    \
981
                             ppc_avr_t *b)                      \
982
    {                                                           \
983
        int i;                                                  \
984
        float_status s = env->vec_status;                       \
985
                                                                \
986
        set_float_rounding_mode(rounding, &s);                  \
987
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                \
988
            r->f[i] = float32_round_to_int (b->f[i], &s);       \
989
        }                                                       \
990
    }
991
VRFI(n, float_round_nearest_even)
992
VRFI(m, float_round_down)
993
VRFI(p, float_round_up)
994
VRFI(z, float_round_to_zero)
995
#undef VRFI
996

    
997
#define VROTATE(suffix, element)                                        \
998
    void helper_vrl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
999
    {                                                                   \
1000
        int i;                                                          \
1001
                                                                        \
1002
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1003
            unsigned int mask = ((1 <<                                  \
1004
                                  (3 + (sizeof(a->element[0]) >> 1)))   \
1005
                                 - 1);                                  \
1006
            unsigned int shift = b->element[i] & mask;                  \
1007
            r->element[i] = (a->element[i] << shift) |                  \
1008
                (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
1009
        }                                                               \
1010
    }
1011
VROTATE(b, u8)
1012
VROTATE(h, u16)
1013
VROTATE(w, u32)
1014
#undef VROTATE
1015

    
1016
void helper_vrsqrtefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1017
{
1018
    int i;
1019

    
1020
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1021
        float32 t = float32_sqrt(b->f[i], &env->vec_status);
1022

    
1023
        r->f[i] = float32_div(float32_one, t, &env->vec_status);
1024
    }
1025
}
1026

    
1027
void helper_vsel(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
1028
                 ppc_avr_t *c)
1029
{
1030
    r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
1031
    r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
1032
}
1033

    
1034
void helper_vexptefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1035
{
1036
    int i;
1037

    
1038
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1039
        r->f[i] = float32_exp2(b->f[i], &env->vec_status);
1040
    }
1041
}
1042

    
1043
void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
1044
{
1045
    int i;
1046

    
1047
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
1048
        r->f[i] = float32_log2(b->f[i], &env->vec_status);
1049
    }
1050
}
1051

    
1052
#if defined(HOST_WORDS_BIGENDIAN)
1053
#define LEFT 0
1054
#define RIGHT 1
1055
#else
1056
#define LEFT 1
1057
#define RIGHT 0
1058
#endif
1059
/* The specification says that the results are undefined if all of the
1060
 * shift counts are not identical.  We check to make sure that they are
1061
 * to conform to what real hardware appears to do.  */
1062
#define VSHIFT(suffix, leftp)                                           \
1063
    void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
1064
    {                                                                   \
1065
        int shift = b->u8[LO_IDX*15] & 0x7;                             \
1066
        int doit = 1;                                                   \
1067
        int i;                                                          \
1068
                                                                        \
1069
        for (i = 0; i < ARRAY_SIZE(r->u8); i++) {                       \
1070
            doit = doit && ((b->u8[i] & 0x7) == shift);                 \
1071
        }                                                               \
1072
        if (doit) {                                                     \
1073
            if (shift == 0) {                                           \
1074
                *r = *a;                                                \
1075
            } else if (leftp) {                                         \
1076
                uint64_t carry = a->u64[LO_IDX] >> (64 - shift);        \
1077
                                                                        \
1078
                r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry;     \
1079
                r->u64[LO_IDX] = a->u64[LO_IDX] << shift;               \
1080
            } else {                                                    \
1081
                uint64_t carry = a->u64[HI_IDX] << (64 - shift);        \
1082
                                                                        \
1083
                r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry;     \
1084
                r->u64[HI_IDX] = a->u64[HI_IDX] >> shift;               \
1085
            }                                                           \
1086
        }                                                               \
1087
    }
1088
VSHIFT(l, LEFT)
1089
VSHIFT(r, RIGHT)
1090
#undef VSHIFT
1091
#undef LEFT
1092
#undef RIGHT
1093

    
1094
#define VSL(suffix, element)                                            \
1095
    void helper_vsl##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
1096
    {                                                                   \
1097
        int i;                                                          \
1098
                                                                        \
1099
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1100
            unsigned int mask = ((1 <<                                  \
1101
                                  (3 + (sizeof(a->element[0]) >> 1)))   \
1102
                                 - 1);                                  \
1103
            unsigned int shift = b->element[i] & mask;                  \
1104
                                                                        \
1105
            r->element[i] = a->element[i] << shift;                     \
1106
        }                                                               \
1107
    }
1108
VSL(b, u8)
1109
VSL(h, u16)
1110
VSL(w, u32)
1111
#undef VSL
1112

    
1113
void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
1114
{
1115
    int sh = shift & 0xf;
1116
    int i;
1117
    ppc_avr_t result;
1118

    
1119
#if defined(HOST_WORDS_BIGENDIAN)
1120
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1121
        int index = sh + i;
1122
        if (index > 0xf) {
1123
            result.u8[i] = b->u8[index - 0x10];
1124
        } else {
1125
            result.u8[i] = a->u8[index];
1126
        }
1127
    }
1128
#else
1129
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
1130
        int index = (16 - sh) + i;
1131
        if (index > 0xf) {
1132
            result.u8[i] = a->u8[index - 0x10];
1133
        } else {
1134
            result.u8[i] = b->u8[index];
1135
        }
1136
    }
1137
#endif
1138
    *r = result;
1139
}
1140

    
1141
void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1142
{
1143
    int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
1144

    
1145
#if defined(HOST_WORDS_BIGENDIAN)
1146
    memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1147
    memset(&r->u8[16-sh], 0, sh);
1148
#else
1149
    memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1150
    memset(&r->u8[0], 0, sh);
1151
#endif
1152
}
1153

    
1154
/* Experimental testing shows that hardware masks the immediate.  */
1155
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
1156
#if defined(HOST_WORDS_BIGENDIAN)
1157
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
1158
#else
1159
#define SPLAT_ELEMENT(element)                                  \
1160
    (ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element))
1161
#endif
1162
#define VSPLT(suffix, element)                                          \
1163
    void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
1164
    {                                                                   \
1165
        uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
1166
        int i;                                                          \
1167
                                                                        \
1168
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1169
            r->element[i] = s;                                          \
1170
        }                                                               \
1171
    }
1172
VSPLT(b, u8)
1173
VSPLT(h, u16)
1174
VSPLT(w, u32)
1175
#undef VSPLT
1176
#undef SPLAT_ELEMENT
1177
#undef _SPLAT_MASKED
1178

    
1179
#define VSPLTI(suffix, element, splat_type)                     \
1180
    void helper_vspltis##suffix(ppc_avr_t *r, uint32_t splat)   \
1181
    {                                                           \
1182
        splat_type x = (int8_t)(splat << 3) >> 3;               \
1183
        int i;                                                  \
1184
                                                                \
1185
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {          \
1186
            r->element[i] = x;                                  \
1187
        }                                                       \
1188
    }
1189
VSPLTI(b, s8, int8_t)
1190
VSPLTI(h, s16, int16_t)
1191
VSPLTI(w, s32, int32_t)
1192
#undef VSPLTI
1193

    
1194
#define VSR(suffix, element)                                            \
1195
    void helper_vsr##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
1196
    {                                                                   \
1197
        int i;                                                          \
1198
                                                                        \
1199
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
1200
            unsigned int mask = ((1 <<                                  \
1201
                                  (3 + (sizeof(a->element[0]) >> 1)))   \
1202
                                 - 1);                                  \
1203
            unsigned int shift = b->element[i] & mask;                  \
1204
                                                                        \
1205
            r->element[i] = a->element[i] >> shift;                     \
1206
        }                                                               \
1207
    }
1208
VSR(ab, s8)
1209
VSR(ah, s16)
1210
VSR(aw, s32)
1211
VSR(b, u8)
1212
VSR(h, u16)
1213
VSR(w, u32)
1214
#undef VSR
1215

    
1216
void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1217
{
1218
    int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf;
1219

    
1220
#if defined(HOST_WORDS_BIGENDIAN)
1221
    memmove(&r->u8[sh], &a->u8[0], 16 - sh);
1222
    memset(&r->u8[0], 0, sh);
1223
#else
1224
    memmove(&r->u8[0], &a->u8[sh], 16 - sh);
1225
    memset(&r->u8[16 - sh], 0, sh);
1226
#endif
1227
}
1228

    
1229
void helper_vsubcuw(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1230
{
1231
    int i;
1232

    
1233
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1234
        r->u32[i] = a->u32[i] >= b->u32[i];
1235
    }
1236
}
1237

    
1238
void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1239
{
1240
    int64_t t;
1241
    int i, upper;
1242
    ppc_avr_t result;
1243
    int sat = 0;
1244

    
1245
#if defined(HOST_WORDS_BIGENDIAN)
1246
    upper = ARRAY_SIZE(r->s32)-1;
1247
#else
1248
    upper = 0;
1249
#endif
1250
    t = (int64_t)b->s32[upper];
1251
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1252
        t += a->s32[i];
1253
        result.s32[i] = 0;
1254
    }
1255
    result.s32[upper] = cvtsdsw(t, &sat);
1256
    *r = result;
1257

    
1258
    if (sat) {
1259
        env->vscr |= (1 << VSCR_SAT);
1260
    }
1261
}
1262

    
1263
void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1264
{
1265
    int i, j, upper;
1266
    ppc_avr_t result;
1267
    int sat = 0;
1268

    
1269
#if defined(HOST_WORDS_BIGENDIAN)
1270
    upper = 1;
1271
#else
1272
    upper = 0;
1273
#endif
1274
    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
1275
        int64_t t = (int64_t)b->s32[upper + i * 2];
1276

    
1277
        result.u64[i] = 0;
1278
        for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
1279
            t += a->s32[2 * i + j];
1280
        }
1281
        result.s32[upper + i * 2] = cvtsdsw(t, &sat);
1282
    }
1283

    
1284
    *r = result;
1285
    if (sat) {
1286
        env->vscr |= (1 << VSCR_SAT);
1287
    }
1288
}
1289

    
1290
void helper_vsum4sbs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1291
{
1292
    int i, j;
1293
    int sat = 0;
1294

    
1295
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1296
        int64_t t = (int64_t)b->s32[i];
1297

    
1298
        for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
1299
            t += a->s8[4 * i + j];
1300
        }
1301
        r->s32[i] = cvtsdsw(t, &sat);
1302
    }
1303

    
1304
    if (sat) {
1305
        env->vscr |= (1 << VSCR_SAT);
1306
    }
1307
}
1308

    
1309
void helper_vsum4shs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1310
{
1311
    int sat = 0;
1312
    int i;
1313

    
1314
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
1315
        int64_t t = (int64_t)b->s32[i];
1316

    
1317
        t += a->s16[2 * i] + a->s16[2 * i + 1];
1318
        r->s32[i] = cvtsdsw(t, &sat);
1319
    }
1320

    
1321
    if (sat) {
1322
        env->vscr |= (1 << VSCR_SAT);
1323
    }
1324
}
1325

    
1326
void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
1327
{
1328
    int i, j;
1329
    int sat = 0;
1330

    
1331
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
1332
        uint64_t t = (uint64_t)b->u32[i];
1333

    
1334
        for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
1335
            t += a->u8[4 * i + j];
1336
        }
1337
        r->u32[i] = cvtuduw(t, &sat);
1338
    }
1339

    
1340
    if (sat) {
1341
        env->vscr |= (1 << VSCR_SAT);
1342
    }
1343
}
1344

    
1345
#if defined(HOST_WORDS_BIGENDIAN)
1346
#define UPKHI 1
1347
#define UPKLO 0
1348
#else
1349
#define UPKHI 0
1350
#define UPKLO 1
1351
#endif
1352
#define VUPKPX(suffix, hi)                                              \
1353
    void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
1354
    {                                                                   \
1355
        int i;                                                          \
1356
        ppc_avr_t result;                                               \
1357
                                                                        \
1358
        for (i = 0; i < ARRAY_SIZE(r->u32); i++) {                      \
1359
            uint16_t e = b->u16[hi ? i : i+4];                          \
1360
            uint8_t a = (e >> 15) ? 0xff : 0;                           \
1361
            uint8_t r = (e >> 10) & 0x1f;                               \
1362
            uint8_t g = (e >> 5) & 0x1f;                                \
1363
            uint8_t b = e & 0x1f;                                       \
1364
                                                                        \
1365
            result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
1366
        }                                                               \
1367
        *r = result;                                                    \
1368
    }
1369
VUPKPX(lpx, UPKLO)
1370
VUPKPX(hpx, UPKHI)
1371
#undef VUPKPX
1372

    
1373
#define VUPK(suffix, unpacked, packee, hi)                              \
1374
    void helper_vupk##suffix(ppc_avr_t *r, ppc_avr_t *b)                \
1375
    {                                                                   \
1376
        int i;                                                          \
1377
        ppc_avr_t result;                                               \
1378
                                                                        \
1379
        if (hi) {                                                       \
1380
            for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
1381
                result.unpacked[i] = b->packee[i];                      \
1382
            }                                                           \
1383
        } else {                                                        \
1384
            for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); \
1385
                 i++) {                                                 \
1386
                result.unpacked[i - ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
1387
            }                                                           \
1388
        }                                                               \
1389
        *r = result;                                                    \
1390
    }
1391
VUPK(hsb, s16, s8, UPKHI)
1392
VUPK(hsh, s32, s16, UPKHI)
1393
VUPK(lsb, s16, s8, UPKLO)
1394
VUPK(lsh, s32, s16, UPKLO)
1395
#undef VUPK
1396
#undef UPKHI
1397
#undef UPKLO
1398

    
1399
#undef VECTOR_FOR_INORDER_I
1400
#undef HI_IDX
1401
#undef LO_IDX
1402

    
1403
/*****************************************************************************/
1404
/* SPE extension helpers */
1405
/* Use a table to make this quicker */
1406
static const uint8_t hbrev[16] = {
1407
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1408
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1409
};
1410

    
1411
static inline uint8_t byte_reverse(uint8_t val)
1412
{
1413
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1414
}
1415

    
1416
static inline uint32_t word_reverse(uint32_t val)
1417
{
1418
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1419
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1420
}
1421

    
1422
#define MASKBITS 16 /* Random value - to be fixed (implementation dependent) */
1423
target_ulong helper_brinc(target_ulong arg1, target_ulong arg2)
1424
{
1425
    uint32_t a, b, d, mask;
1426

    
1427
    mask = UINT32_MAX >> (32 - MASKBITS);
1428
    a = arg1 & mask;
1429
    b = arg2 & mask;
1430
    d = word_reverse(1 + word_reverse(a | ~b));
1431
    return (arg1 & ~mask) | (d & b);
1432
}
1433

    
1434
uint32_t helper_cntlsw32(uint32_t val)
1435
{
1436
    if (val & 0x80000000) {
1437
        return clz32(~val);
1438
    } else {
1439
        return clz32(val);
1440
    }
1441
}
1442

    
1443
uint32_t helper_cntlzw32(uint32_t val)
1444
{
1445
    return clz32(val);
1446
}
1447

    
1448
/* 440 specific */
1449
target_ulong helper_dlmzb(CPUPPCState *env, target_ulong high,
1450
                          target_ulong low, uint32_t update_Rc)
1451
{
1452
    target_ulong mask;
1453
    int i;
1454

    
1455
    i = 1;
1456
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1457
        if ((high & mask) == 0) {
1458
            if (update_Rc) {
1459
                env->crf[0] = 0x4;
1460
            }
1461
            goto done;
1462
        }
1463
        i++;
1464
    }
1465
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1466
        if ((low & mask) == 0) {
1467
            if (update_Rc) {
1468
                env->crf[0] = 0x8;
1469
            }
1470
            goto done;
1471
        }
1472
        i++;
1473
    }
1474
    if (update_Rc) {
1475
        env->crf[0] = 0x2;
1476
    }
1477
 done:
1478
    env->xer = (env->xer & ~0x7F) | i;
1479
    if (update_Rc) {
1480
        env->crf[0] |= xer_so;
1481
    }
1482
    return i;
1483
}