Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 35cf7c7e

History | View | Annotate | Download (119 kB)

1
/*
2
 *  PowerPC 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, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19
 */
20
#include <string.h>
21
#include "exec.h"
22
#include "host-utils.h"
23
#include "helper.h"
24

    
25
#include "helper_regs.h"
26

    
27
//#define DEBUG_OP
28
//#define DEBUG_EXCEPTIONS
29
//#define DEBUG_SOFTWARE_TLB
30

    
31
#ifdef DEBUG_SOFTWARE_TLB
32
#  define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
33
#else
34
#  define LOG_SWTLB(...) do { } while (0)
35
#endif
36

    
37

    
38
/*****************************************************************************/
39
/* Exceptions processing helpers */
40

    
41
void helper_raise_exception_err (uint32_t exception, uint32_t error_code)
42
{
43
#if 0
44
    printf("Raise exception %3x code : %d\n", exception, error_code);
45
#endif
46
    env->exception_index = exception;
47
    env->error_code = error_code;
48
    cpu_loop_exit();
49
}
50

    
51
void helper_raise_exception (uint32_t exception)
52
{
53
    helper_raise_exception_err(exception, 0);
54
}
55

    
56
/*****************************************************************************/
57
/* Registers load and stores */
58
target_ulong helper_load_cr (void)
59
{
60
    return (env->crf[0] << 28) |
61
           (env->crf[1] << 24) |
62
           (env->crf[2] << 20) |
63
           (env->crf[3] << 16) |
64
           (env->crf[4] << 12) |
65
           (env->crf[5] << 8) |
66
           (env->crf[6] << 4) |
67
           (env->crf[7] << 0);
68
}
69

    
70
void helper_store_cr (target_ulong val, uint32_t mask)
71
{
72
    int i, sh;
73

    
74
    for (i = 0, sh = 7; i < 8; i++, sh--) {
75
        if (mask & (1 << sh))
76
            env->crf[i] = (val >> (sh * 4)) & 0xFUL;
77
    }
78
}
79

    
80
/*****************************************************************************/
81
/* SPR accesses */
82
void helper_load_dump_spr (uint32_t sprn)
83
{
84
    qemu_log("Read SPR %d %03x => " ADDRX "\n",
85
                sprn, sprn, env->spr[sprn]);
86
}
87

    
88
void helper_store_dump_spr (uint32_t sprn)
89
{
90
    qemu_log("Write SPR %d %03x <= " ADDRX "\n",
91
                sprn, sprn, env->spr[sprn]);
92
}
93

    
94
target_ulong helper_load_tbl (void)
95
{
96
    return cpu_ppc_load_tbl(env);
97
}
98

    
99
target_ulong helper_load_tbu (void)
100
{
101
    return cpu_ppc_load_tbu(env);
102
}
103

    
104
target_ulong helper_load_atbl (void)
105
{
106
    return cpu_ppc_load_atbl(env);
107
}
108

    
109
target_ulong helper_load_atbu (void)
110
{
111
    return cpu_ppc_load_atbu(env);
112
}
113

    
114
target_ulong helper_load_601_rtcl (void)
115
{
116
    return cpu_ppc601_load_rtcl(env);
117
}
118

    
119
target_ulong helper_load_601_rtcu (void)
120
{
121
    return cpu_ppc601_load_rtcu(env);
122
}
123

    
124
#if !defined(CONFIG_USER_ONLY)
125
#if defined (TARGET_PPC64)
126
void helper_store_asr (target_ulong val)
127
{
128
    ppc_store_asr(env, val);
129
}
130
#endif
131

    
132
void helper_store_sdr1 (target_ulong val)
133
{
134
    ppc_store_sdr1(env, val);
135
}
136

    
137
void helper_store_tbl (target_ulong val)
138
{
139
    cpu_ppc_store_tbl(env, val);
140
}
141

    
142
void helper_store_tbu (target_ulong val)
143
{
144
    cpu_ppc_store_tbu(env, val);
145
}
146

    
147
void helper_store_atbl (target_ulong val)
148
{
149
    cpu_ppc_store_atbl(env, val);
150
}
151

    
152
void helper_store_atbu (target_ulong val)
153
{
154
    cpu_ppc_store_atbu(env, val);
155
}
156

    
157
void helper_store_601_rtcl (target_ulong val)
158
{
159
    cpu_ppc601_store_rtcl(env, val);
160
}
161

    
162
void helper_store_601_rtcu (target_ulong val)
163
{
164
    cpu_ppc601_store_rtcu(env, val);
165
}
166

    
167
target_ulong helper_load_decr (void)
168
{
169
    return cpu_ppc_load_decr(env);
170
}
171

    
172
void helper_store_decr (target_ulong val)
173
{
174
    cpu_ppc_store_decr(env, val);
175
}
176

    
177
void helper_store_hid0_601 (target_ulong val)
178
{
179
    target_ulong hid0;
180

    
181
    hid0 = env->spr[SPR_HID0];
182
    if ((val ^ hid0) & 0x00000008) {
183
        /* Change current endianness */
184
        env->hflags &= ~(1 << MSR_LE);
185
        env->hflags_nmsr &= ~(1 << MSR_LE);
186
        env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
187
        env->hflags |= env->hflags_nmsr;
188
        qemu_log("%s: set endianness to %c => " ADDRX "\n",
189
                    __func__, val & 0x8 ? 'l' : 'b', env->hflags);
190
    }
191
    env->spr[SPR_HID0] = (uint32_t)val;
192
}
193

    
194
void helper_store_403_pbr (uint32_t num, target_ulong value)
195
{
196
    if (likely(env->pb[num] != value)) {
197
        env->pb[num] = value;
198
        /* Should be optimized */
199
        tlb_flush(env, 1);
200
    }
201
}
202

    
203
target_ulong helper_load_40x_pit (void)
204
{
205
    return load_40x_pit(env);
206
}
207

    
208
void helper_store_40x_pit (target_ulong val)
209
{
210
    store_40x_pit(env, val);
211
}
212

    
213
void helper_store_40x_dbcr0 (target_ulong val)
214
{
215
    store_40x_dbcr0(env, val);
216
}
217

    
218
void helper_store_40x_sler (target_ulong val)
219
{
220
    store_40x_sler(env, val);
221
}
222

    
223
void helper_store_booke_tcr (target_ulong val)
224
{
225
    store_booke_tcr(env, val);
226
}
227

    
228
void helper_store_booke_tsr (target_ulong val)
229
{
230
    store_booke_tsr(env, val);
231
}
232

    
233
void helper_store_ibatu (uint32_t nr, target_ulong val)
234
{
235
    ppc_store_ibatu(env, nr, val);
236
}
237

    
238
void helper_store_ibatl (uint32_t nr, target_ulong val)
239
{
240
    ppc_store_ibatl(env, nr, val);
241
}
242

    
243
void helper_store_dbatu (uint32_t nr, target_ulong val)
244
{
245
    ppc_store_dbatu(env, nr, val);
246
}
247

    
248
void helper_store_dbatl (uint32_t nr, target_ulong val)
249
{
250
    ppc_store_dbatl(env, nr, val);
251
}
252

    
253
void helper_store_601_batl (uint32_t nr, target_ulong val)
254
{
255
    ppc_store_ibatl_601(env, nr, val);
256
}
257

    
258
void helper_store_601_batu (uint32_t nr, target_ulong val)
259
{
260
    ppc_store_ibatu_601(env, nr, val);
261
}
262
#endif
263

    
264
/*****************************************************************************/
265
/* Memory load and stores */
266

    
267
static always_inline target_ulong addr_add(target_ulong addr, target_long arg)
268
{
269
#if defined(TARGET_PPC64)
270
        if (!msr_sf)
271
            return (uint32_t)(addr + arg);
272
        else
273
#endif
274
            return addr + arg;
275
}
276

    
277
void helper_lmw (target_ulong addr, uint32_t reg)
278
{
279
    for (; reg < 32; reg++) {
280
        if (msr_le)
281
            env->gpr[reg] = bswap32(ldl(addr));
282
        else
283
            env->gpr[reg] = ldl(addr);
284
        addr = addr_add(addr, 4);
285
    }
286
}
287

    
288
void helper_stmw (target_ulong addr, uint32_t reg)
289
{
290
    for (; reg < 32; reg++) {
291
        if (msr_le)
292
            stl(addr, bswap32((uint32_t)env->gpr[reg]));
293
        else
294
            stl(addr, (uint32_t)env->gpr[reg]);
295
        addr = addr_add(addr, 4);
296
    }
297
}
298

    
299
void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
300
{
301
    int sh;
302
    for (; nb > 3; nb -= 4) {
303
        env->gpr[reg] = ldl(addr);
304
        reg = (reg + 1) % 32;
305
        addr = addr_add(addr, 4);
306
    }
307
    if (unlikely(nb > 0)) {
308
        env->gpr[reg] = 0;
309
        for (sh = 24; nb > 0; nb--, sh -= 8) {
310
            env->gpr[reg] |= ldub(addr) << sh;
311
            addr = addr_add(addr, 1);
312
        }
313
    }
314
}
315
/* PPC32 specification says we must generate an exception if
316
 * rA is in the range of registers to be loaded.
317
 * In an other hand, IBM says this is valid, but rA won't be loaded.
318
 * For now, I'll follow the spec...
319
 */
320
void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
321
{
322
    if (likely(xer_bc != 0)) {
323
        if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
324
                     (reg < rb && (reg + xer_bc) > rb))) {
325
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
326
                                       POWERPC_EXCP_INVAL |
327
                                       POWERPC_EXCP_INVAL_LSWX);
328
        } else {
329
            helper_lsw(addr, xer_bc, reg);
330
        }
331
    }
332
}
333

    
334
void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg)
335
{
336
    int sh;
337
    for (; nb > 3; nb -= 4) {
338
        stl(addr, env->gpr[reg]);
339
        reg = (reg + 1) % 32;
340
        addr = addr_add(addr, 4);
341
    }
342
    if (unlikely(nb > 0)) {
343
        for (sh = 24; nb > 0; nb--, sh -= 8) {
344
            stb(addr, (env->gpr[reg] >> sh) & 0xFF);
345
            addr = addr_add(addr, 1);
346
        }
347
    }
348
}
349

    
350
static void do_dcbz(target_ulong addr, int dcache_line_size)
351
{
352
    addr &= ~(dcache_line_size - 1);
353
    int i;
354
    for (i = 0 ; i < dcache_line_size ; i += 4) {
355
        stl(addr + i , 0);
356
    }
357
    if (env->reserve == addr)
358
        env->reserve = (target_ulong)-1ULL;
359
}
360

    
361
void helper_dcbz(target_ulong addr)
362
{
363
    do_dcbz(addr, env->dcache_line_size);
364
}
365

    
366
void helper_dcbz_970(target_ulong addr)
367
{
368
    if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
369
        do_dcbz(addr, 32);
370
    else
371
        do_dcbz(addr, env->dcache_line_size);
372
}
373

    
374
void helper_icbi(target_ulong addr)
375
{
376
    uint32_t tmp;
377

    
378
    addr &= ~(env->dcache_line_size - 1);
379
    /* Invalidate one cache line :
380
     * PowerPC specification says this is to be treated like a load
381
     * (not a fetch) by the MMU. To be sure it will be so,
382
     * do the load "by hand".
383
     */
384
    tmp = ldl(addr);
385
    tb_invalidate_page_range(addr, addr + env->icache_line_size);
386
}
387

    
388
// XXX: to be tested
389
target_ulong helper_lscbx (target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
390
{
391
    int i, c, d;
392
    d = 24;
393
    for (i = 0; i < xer_bc; i++) {
394
        c = ldub(addr);
395
        addr = addr_add(addr, 1);
396
        /* ra (if not 0) and rb are never modified */
397
        if (likely(reg != rb && (ra == 0 || reg != ra))) {
398
            env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
399
        }
400
        if (unlikely(c == xer_cmp))
401
            break;
402
        if (likely(d != 0)) {
403
            d -= 8;
404
        } else {
405
            d = 24;
406
            reg++;
407
            reg = reg & 0x1F;
408
        }
409
    }
410
    return i;
411
}
412

    
413
/*****************************************************************************/
414
/* Fixed point operations helpers */
415
#if defined(TARGET_PPC64)
416

    
417
/* multiply high word */
418
uint64_t helper_mulhd (uint64_t arg1, uint64_t arg2)
419
{
420
    uint64_t tl, th;
421

    
422
    muls64(&tl, &th, arg1, arg2);
423
    return th;
424
}
425

    
426
/* multiply high word unsigned */
427
uint64_t helper_mulhdu (uint64_t arg1, uint64_t arg2)
428
{
429
    uint64_t tl, th;
430

    
431
    mulu64(&tl, &th, arg1, arg2);
432
    return th;
433
}
434

    
435
uint64_t helper_mulldo (uint64_t arg1, uint64_t arg2)
436
{
437
    int64_t th;
438
    uint64_t tl;
439

    
440
    muls64(&tl, (uint64_t *)&th, arg1, arg2);
441
    /* If th != 0 && th != -1, then we had an overflow */
442
    if (likely((uint64_t)(th + 1) <= 1)) {
443
        env->xer &= ~(1 << XER_OV);
444
    } else {
445
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
446
    }
447
    return (int64_t)tl;
448
}
449
#endif
450

    
451
target_ulong helper_cntlzw (target_ulong t)
452
{
453
    return clz32(t);
454
}
455

    
456
#if defined(TARGET_PPC64)
457
target_ulong helper_cntlzd (target_ulong t)
458
{
459
    return clz64(t);
460
}
461
#endif
462

    
463
/* shift right arithmetic helper */
464
target_ulong helper_sraw (target_ulong value, target_ulong shift)
465
{
466
    int32_t ret;
467

    
468
    if (likely(!(shift & 0x20))) {
469
        if (likely((uint32_t)shift != 0)) {
470
            shift &= 0x1f;
471
            ret = (int32_t)value >> shift;
472
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
473
                env->xer &= ~(1 << XER_CA);
474
            } else {
475
                env->xer |= (1 << XER_CA);
476
            }
477
        } else {
478
            ret = (int32_t)value;
479
            env->xer &= ~(1 << XER_CA);
480
        }
481
    } else {
482
        ret = (int32_t)value >> 31;
483
        if (ret) {
484
            env->xer |= (1 << XER_CA);
485
        } else {
486
            env->xer &= ~(1 << XER_CA);
487
        }
488
    }
489
    return (target_long)ret;
490
}
491

    
492
#if defined(TARGET_PPC64)
493
target_ulong helper_srad (target_ulong value, target_ulong shift)
494
{
495
    int64_t ret;
496

    
497
    if (likely(!(shift & 0x40))) {
498
        if (likely((uint64_t)shift != 0)) {
499
            shift &= 0x3f;
500
            ret = (int64_t)value >> shift;
501
            if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
502
                env->xer &= ~(1 << XER_CA);
503
            } else {
504
                env->xer |= (1 << XER_CA);
505
            }
506
        } else {
507
            ret = (int64_t)value;
508
            env->xer &= ~(1 << XER_CA);
509
        }
510
    } else {
511
        ret = (int64_t)value >> 63;
512
        if (ret) {
513
            env->xer |= (1 << XER_CA);
514
        } else {
515
            env->xer &= ~(1 << XER_CA);
516
        }
517
    }
518
    return ret;
519
}
520
#endif
521

    
522
target_ulong helper_popcntb (target_ulong val)
523
{
524
    val = (val & 0x55555555) + ((val >>  1) & 0x55555555);
525
    val = (val & 0x33333333) + ((val >>  2) & 0x33333333);
526
    val = (val & 0x0f0f0f0f) + ((val >>  4) & 0x0f0f0f0f);
527
    return val;
528
}
529

    
530
#if defined(TARGET_PPC64)
531
target_ulong helper_popcntb_64 (target_ulong val)
532
{
533
    val = (val & 0x5555555555555555ULL) + ((val >>  1) & 0x5555555555555555ULL);
534
    val = (val & 0x3333333333333333ULL) + ((val >>  2) & 0x3333333333333333ULL);
535
    val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >>  4) & 0x0f0f0f0f0f0f0f0fULL);
536
    return val;
537
}
538
#endif
539

    
540
/*****************************************************************************/
541
/* Floating point operations helpers */
542
uint64_t helper_float32_to_float64(uint32_t arg)
543
{
544
    CPU_FloatU f;
545
    CPU_DoubleU d;
546
    f.l = arg;
547
    d.d = float32_to_float64(f.f, &env->fp_status);
548
    return d.ll;
549
}
550

    
551
uint32_t helper_float64_to_float32(uint64_t arg)
552
{
553
    CPU_FloatU f;
554
    CPU_DoubleU d;
555
    d.ll = arg;
556
    f.f = float64_to_float32(d.d, &env->fp_status);
557
    return f.l;
558
}
559

    
560
static always_inline int isden (float64 d)
561
{
562
    CPU_DoubleU u;
563

    
564
    u.d = d;
565

    
566
    return ((u.ll >> 52) & 0x7FF) == 0;
567
}
568

    
569
uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
570
{
571
    CPU_DoubleU farg;
572
    int isneg;
573
    int ret;
574
    farg.ll = arg;
575
    isneg = float64_is_neg(farg.d);
576
    if (unlikely(float64_is_nan(farg.d))) {
577
        if (float64_is_signaling_nan(farg.d)) {
578
            /* Signaling NaN: flags are undefined */
579
            ret = 0x00;
580
        } else {
581
            /* Quiet NaN */
582
            ret = 0x11;
583
        }
584
    } else if (unlikely(float64_is_infinity(farg.d))) {
585
        /* +/- infinity */
586
        if (isneg)
587
            ret = 0x09;
588
        else
589
            ret = 0x05;
590
    } else {
591
        if (float64_is_zero(farg.d)) {
592
            /* +/- zero */
593
            if (isneg)
594
                ret = 0x12;
595
            else
596
                ret = 0x02;
597
        } else {
598
            if (isden(farg.d)) {
599
                /* Denormalized numbers */
600
                ret = 0x10;
601
            } else {
602
                /* Normalized numbers */
603
                ret = 0x00;
604
            }
605
            if (isneg) {
606
                ret |= 0x08;
607
            } else {
608
                ret |= 0x04;
609
            }
610
        }
611
    }
612
    if (set_fprf) {
613
        /* We update FPSCR_FPRF */
614
        env->fpscr &= ~(0x1F << FPSCR_FPRF);
615
        env->fpscr |= ret << FPSCR_FPRF;
616
    }
617
    /* We just need fpcc to update Rc1 */
618
    return ret & 0xF;
619
}
620

    
621
/* Floating-point invalid operations exception */
622
static always_inline uint64_t fload_invalid_op_excp (int op)
623
{
624
    uint64_t ret = 0;
625
    int ve;
626

    
627
    ve = fpscr_ve;
628
    switch (op) {
629
    case POWERPC_EXCP_FP_VXSNAN:
630
        env->fpscr |= 1 << FPSCR_VXSNAN;
631
        break;
632
    case POWERPC_EXCP_FP_VXSOFT:
633
        env->fpscr |= 1 << FPSCR_VXSOFT;
634
        break;
635
    case POWERPC_EXCP_FP_VXISI:
636
        /* Magnitude subtraction of infinities */
637
        env->fpscr |= 1 << FPSCR_VXISI;
638
        goto update_arith;
639
    case POWERPC_EXCP_FP_VXIDI:
640
        /* Division of infinity by infinity */
641
        env->fpscr |= 1 << FPSCR_VXIDI;
642
        goto update_arith;
643
    case POWERPC_EXCP_FP_VXZDZ:
644
        /* Division of zero by zero */
645
        env->fpscr |= 1 << FPSCR_VXZDZ;
646
        goto update_arith;
647
    case POWERPC_EXCP_FP_VXIMZ:
648
        /* Multiplication of zero by infinity */
649
        env->fpscr |= 1 << FPSCR_VXIMZ;
650
        goto update_arith;
651
    case POWERPC_EXCP_FP_VXVC:
652
        /* Ordered comparison of NaN */
653
        env->fpscr |= 1 << FPSCR_VXVC;
654
        env->fpscr &= ~(0xF << FPSCR_FPCC);
655
        env->fpscr |= 0x11 << FPSCR_FPCC;
656
        /* We must update the target FPR before raising the exception */
657
        if (ve != 0) {
658
            env->exception_index = POWERPC_EXCP_PROGRAM;
659
            env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_VXVC;
660
            /* Update the floating-point enabled exception summary */
661
            env->fpscr |= 1 << FPSCR_FEX;
662
            /* Exception is differed */
663
            ve = 0;
664
        }
665
        break;
666
    case POWERPC_EXCP_FP_VXSQRT:
667
        /* Square root of a negative number */
668
        env->fpscr |= 1 << FPSCR_VXSQRT;
669
    update_arith:
670
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
671
        if (ve == 0) {
672
            /* Set the result to quiet NaN */
673
            ret = 0xFFF8000000000000ULL;
674
            env->fpscr &= ~(0xF << FPSCR_FPCC);
675
            env->fpscr |= 0x11 << FPSCR_FPCC;
676
        }
677
        break;
678
    case POWERPC_EXCP_FP_VXCVI:
679
        /* Invalid conversion */
680
        env->fpscr |= 1 << FPSCR_VXCVI;
681
        env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
682
        if (ve == 0) {
683
            /* Set the result to quiet NaN */
684
            ret = 0xFFF8000000000000ULL;
685
            env->fpscr &= ~(0xF << FPSCR_FPCC);
686
            env->fpscr |= 0x11 << FPSCR_FPCC;
687
        }
688
        break;
689
    }
690
    /* Update the floating-point invalid operation summary */
691
    env->fpscr |= 1 << FPSCR_VX;
692
    /* Update the floating-point exception summary */
693
    env->fpscr |= 1 << FPSCR_FX;
694
    if (ve != 0) {
695
        /* Update the floating-point enabled exception summary */
696
        env->fpscr |= 1 << FPSCR_FEX;
697
        if (msr_fe0 != 0 || msr_fe1 != 0)
698
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_FP | op);
699
    }
700
    return ret;
701
}
702

    
703
static always_inline void float_zero_divide_excp (void)
704
{
705
    env->fpscr |= 1 << FPSCR_ZX;
706
    env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
707
    /* Update the floating-point exception summary */
708
    env->fpscr |= 1 << FPSCR_FX;
709
    if (fpscr_ze != 0) {
710
        /* Update the floating-point enabled exception summary */
711
        env->fpscr |= 1 << FPSCR_FEX;
712
        if (msr_fe0 != 0 || msr_fe1 != 0) {
713
            helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
714
                                       POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX);
715
        }
716
    }
717
}
718

    
719
static always_inline void float_overflow_excp (void)
720
{
721
    env->fpscr |= 1 << FPSCR_OX;
722
    /* Update the floating-point exception summary */
723
    env->fpscr |= 1 << FPSCR_FX;
724
    if (fpscr_oe != 0) {
725
        /* XXX: should adjust the result */
726
        /* Update the floating-point enabled exception summary */
727
        env->fpscr |= 1 << FPSCR_FEX;
728
        /* We must update the target FPR before raising the exception */
729
        env->exception_index = POWERPC_EXCP_PROGRAM;
730
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
731
    } else {
732
        env->fpscr |= 1 << FPSCR_XX;
733
        env->fpscr |= 1 << FPSCR_FI;
734
    }
735
}
736

    
737
static always_inline void float_underflow_excp (void)
738
{
739
    env->fpscr |= 1 << FPSCR_UX;
740
    /* Update the floating-point exception summary */
741
    env->fpscr |= 1 << FPSCR_FX;
742
    if (fpscr_ue != 0) {
743
        /* XXX: should adjust the result */
744
        /* Update the floating-point enabled exception summary */
745
        env->fpscr |= 1 << FPSCR_FEX;
746
        /* We must update the target FPR before raising the exception */
747
        env->exception_index = POWERPC_EXCP_PROGRAM;
748
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
749
    }
750
}
751

    
752
static always_inline void float_inexact_excp (void)
753
{
754
    env->fpscr |= 1 << FPSCR_XX;
755
    /* Update the floating-point exception summary */
756
    env->fpscr |= 1 << FPSCR_FX;
757
    if (fpscr_xe != 0) {
758
        /* Update the floating-point enabled exception summary */
759
        env->fpscr |= 1 << FPSCR_FEX;
760
        /* We must update the target FPR before raising the exception */
761
        env->exception_index = POWERPC_EXCP_PROGRAM;
762
        env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
763
    }
764
}
765

    
766
static always_inline void fpscr_set_rounding_mode (void)
767
{
768
    int rnd_type;
769

    
770
    /* Set rounding mode */
771
    switch (fpscr_rn) {
772
    case 0:
773
        /* Best approximation (round to nearest) */
774
        rnd_type = float_round_nearest_even;
775
        break;
776
    case 1:
777
        /* Smaller magnitude (round toward zero) */
778
        rnd_type = float_round_to_zero;
779
        break;
780
    case 2:
781
        /* Round toward +infinite */
782
        rnd_type = float_round_up;
783
        break;
784
    default:
785
    case 3:
786
        /* Round toward -infinite */
787
        rnd_type = float_round_down;
788
        break;
789
    }
790
    set_float_rounding_mode(rnd_type, &env->fp_status);
791
}
792

    
793
void helper_fpscr_clrbit (uint32_t bit)
794
{
795
    int prev;
796

    
797
    prev = (env->fpscr >> bit) & 1;
798
    env->fpscr &= ~(1 << bit);
799
    if (prev == 1) {
800
        switch (bit) {
801
        case FPSCR_RN1:
802
        case FPSCR_RN:
803
            fpscr_set_rounding_mode();
804
            break;
805
        default:
806
            break;
807
        }
808
    }
809
}
810

    
811
void helper_fpscr_setbit (uint32_t bit)
812
{
813
    int prev;
814

    
815
    prev = (env->fpscr >> bit) & 1;
816
    env->fpscr |= 1 << bit;
817
    if (prev == 0) {
818
        switch (bit) {
819
        case FPSCR_VX:
820
            env->fpscr |= 1 << FPSCR_FX;
821
            if (fpscr_ve)
822
                goto raise_ve;
823
        case FPSCR_OX:
824
            env->fpscr |= 1 << FPSCR_FX;
825
            if (fpscr_oe)
826
                goto raise_oe;
827
            break;
828
        case FPSCR_UX:
829
            env->fpscr |= 1 << FPSCR_FX;
830
            if (fpscr_ue)
831
                goto raise_ue;
832
            break;
833
        case FPSCR_ZX:
834
            env->fpscr |= 1 << FPSCR_FX;
835
            if (fpscr_ze)
836
                goto raise_ze;
837
            break;
838
        case FPSCR_XX:
839
            env->fpscr |= 1 << FPSCR_FX;
840
            if (fpscr_xe)
841
                goto raise_xe;
842
            break;
843
        case FPSCR_VXSNAN:
844
        case FPSCR_VXISI:
845
        case FPSCR_VXIDI:
846
        case FPSCR_VXZDZ:
847
        case FPSCR_VXIMZ:
848
        case FPSCR_VXVC:
849
        case FPSCR_VXSOFT:
850
        case FPSCR_VXSQRT:
851
        case FPSCR_VXCVI:
852
            env->fpscr |= 1 << FPSCR_VX;
853
            env->fpscr |= 1 << FPSCR_FX;
854
            if (fpscr_ve != 0)
855
                goto raise_ve;
856
            break;
857
        case FPSCR_VE:
858
            if (fpscr_vx != 0) {
859
            raise_ve:
860
                env->error_code = POWERPC_EXCP_FP;
861
                if (fpscr_vxsnan)
862
                    env->error_code |= POWERPC_EXCP_FP_VXSNAN;
863
                if (fpscr_vxisi)
864
                    env->error_code |= POWERPC_EXCP_FP_VXISI;
865
                if (fpscr_vxidi)
866
                    env->error_code |= POWERPC_EXCP_FP_VXIDI;
867
                if (fpscr_vxzdz)
868
                    env->error_code |= POWERPC_EXCP_FP_VXZDZ;
869
                if (fpscr_vximz)
870
                    env->error_code |= POWERPC_EXCP_FP_VXIMZ;
871
                if (fpscr_vxvc)
872
                    env->error_code |= POWERPC_EXCP_FP_VXVC;
873
                if (fpscr_vxsoft)
874
                    env->error_code |= POWERPC_EXCP_FP_VXSOFT;
875
                if (fpscr_vxsqrt)
876
                    env->error_code |= POWERPC_EXCP_FP_VXSQRT;
877
                if (fpscr_vxcvi)
878
                    env->error_code |= POWERPC_EXCP_FP_VXCVI;
879
                goto raise_excp;
880
            }
881
            break;
882
        case FPSCR_OE:
883
            if (fpscr_ox != 0) {
884
            raise_oe:
885
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_OX;
886
                goto raise_excp;
887
            }
888
            break;
889
        case FPSCR_UE:
890
            if (fpscr_ux != 0) {
891
            raise_ue:
892
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_UX;
893
                goto raise_excp;
894
            }
895
            break;
896
        case FPSCR_ZE:
897
            if (fpscr_zx != 0) {
898
            raise_ze:
899
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX;
900
                goto raise_excp;
901
            }
902
            break;
903
        case FPSCR_XE:
904
            if (fpscr_xx != 0) {
905
            raise_xe:
906
                env->error_code = POWERPC_EXCP_FP | POWERPC_EXCP_FP_XX;
907
                goto raise_excp;
908
            }
909
            break;
910
        case FPSCR_RN1:
911
        case FPSCR_RN:
912
            fpscr_set_rounding_mode();
913
            break;
914
        default:
915
            break;
916
        raise_excp:
917
            /* Update the floating-point enabled exception summary */
918
            env->fpscr |= 1 << FPSCR_FEX;
919
                /* We have to update Rc1 before raising the exception */
920
            env->exception_index = POWERPC_EXCP_PROGRAM;
921
            break;
922
        }
923
    }
924
}
925

    
926
void helper_store_fpscr (uint64_t arg, uint32_t mask)
927
{
928
    /*
929
     * We use only the 32 LSB of the incoming fpr
930
     */
931
    uint32_t prev, new;
932
    int i;
933

    
934
    prev = env->fpscr;
935
    new = (uint32_t)arg;
936
    new &= ~0x60000000;
937
    new |= prev & 0x60000000;
938
    for (i = 0; i < 8; i++) {
939
        if (mask & (1 << i)) {
940
            env->fpscr &= ~(0xF << (4 * i));
941
            env->fpscr |= new & (0xF << (4 * i));
942
        }
943
    }
944
    /* Update VX and FEX */
945
    if (fpscr_ix != 0)
946
        env->fpscr |= 1 << FPSCR_VX;
947
    else
948
        env->fpscr &= ~(1 << FPSCR_VX);
949
    if ((fpscr_ex & fpscr_eex) != 0) {
950
        env->fpscr |= 1 << FPSCR_FEX;
951
        env->exception_index = POWERPC_EXCP_PROGRAM;
952
        /* XXX: we should compute it properly */
953
        env->error_code = POWERPC_EXCP_FP;
954
    }
955
    else
956
        env->fpscr &= ~(1 << FPSCR_FEX);
957
    fpscr_set_rounding_mode();
958
}
959

    
960
void helper_float_check_status (void)
961
{
962
#ifdef CONFIG_SOFTFLOAT
963
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
964
        (env->error_code & POWERPC_EXCP_FP)) {
965
        /* Differred floating-point exception after target FPR update */
966
        if (msr_fe0 != 0 || msr_fe1 != 0)
967
            helper_raise_exception_err(env->exception_index, env->error_code);
968
    } else {
969
        int status = get_float_exception_flags(&env->fp_status);
970
        if (status & float_flag_divbyzero) {
971
            float_zero_divide_excp();
972
        } else if (status & float_flag_overflow) {
973
            float_overflow_excp();
974
        } else if (status & float_flag_underflow) {
975
            float_underflow_excp();
976
        } else if (status & float_flag_inexact) {
977
            float_inexact_excp();
978
        }
979
    }
980
#else
981
    if (env->exception_index == POWERPC_EXCP_PROGRAM &&
982
        (env->error_code & POWERPC_EXCP_FP)) {
983
        /* Differred floating-point exception after target FPR update */
984
        if (msr_fe0 != 0 || msr_fe1 != 0)
985
            helper_raise_exception_err(env->exception_index, env->error_code);
986
    }
987
#endif
988
}
989

    
990
#ifdef CONFIG_SOFTFLOAT
991
void helper_reset_fpstatus (void)
992
{
993
    set_float_exception_flags(0, &env->fp_status);
994
}
995
#endif
996

    
997
/* fadd - fadd. */
998
uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
999
{
1000
    CPU_DoubleU farg1, farg2;
1001

    
1002
    farg1.ll = arg1;
1003
    farg2.ll = arg2;
1004
#if USE_PRECISE_EMULATION
1005
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1006
                 float64_is_signaling_nan(farg2.d))) {
1007
        /* sNaN addition */
1008
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1009
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1010
                      float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
1011
        /* Magnitude subtraction of infinities */
1012
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1013
    } else {
1014
        farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
1015
    }
1016
#else
1017
    farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
1018
#endif
1019
    return farg1.ll;
1020
}
1021

    
1022
/* fsub - fsub. */
1023
uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
1024
{
1025
    CPU_DoubleU farg1, farg2;
1026

    
1027
    farg1.ll = arg1;
1028
    farg2.ll = arg2;
1029
#if USE_PRECISE_EMULATION
1030
{
1031
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1032
                 float64_is_signaling_nan(farg2.d))) {
1033
        /* sNaN subtraction */
1034
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1035
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1036
                      float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
1037
        /* Magnitude subtraction of infinities */
1038
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1039
    } else {
1040
        farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1041
    }
1042
}
1043
#else
1044
    farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1045
#endif
1046
    return farg1.ll;
1047
}
1048

    
1049
/* fmul - fmul. */
1050
uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
1051
{
1052
    CPU_DoubleU farg1, farg2;
1053

    
1054
    farg1.ll = arg1;
1055
    farg2.ll = arg2;
1056
#if USE_PRECISE_EMULATION
1057
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1058
                 float64_is_signaling_nan(farg2.d))) {
1059
        /* sNaN multiplication */
1060
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1061
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1062
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1063
        /* Multiplication of zero by infinity */
1064
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1065
    } else {
1066
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1067
    }
1068
#else
1069
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1070
#endif
1071
    return farg1.ll;
1072
}
1073

    
1074
/* fdiv - fdiv. */
1075
uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
1076
{
1077
    CPU_DoubleU farg1, farg2;
1078

    
1079
    farg1.ll = arg1;
1080
    farg2.ll = arg2;
1081
#if USE_PRECISE_EMULATION
1082
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1083
                 float64_is_signaling_nan(farg2.d))) {
1084
        /* sNaN division */
1085
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1086
    } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
1087
        /* Division of infinity by infinity */
1088
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
1089
    } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
1090
        /* Division of zero by zero */
1091
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
1092
    } else {
1093
        farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1094
    }
1095
#else
1096
    farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1097
#endif
1098
    return farg1.ll;
1099
}
1100

    
1101
/* fabs */
1102
uint64_t helper_fabs (uint64_t arg)
1103
{
1104
    CPU_DoubleU farg;
1105

    
1106
    farg.ll = arg;
1107
    farg.d = float64_abs(farg.d);
1108
    return farg.ll;
1109
}
1110

    
1111
/* fnabs */
1112
uint64_t helper_fnabs (uint64_t arg)
1113
{
1114
    CPU_DoubleU farg;
1115

    
1116
    farg.ll = arg;
1117
    farg.d = float64_abs(farg.d);
1118
    farg.d = float64_chs(farg.d);
1119
    return farg.ll;
1120
}
1121

    
1122
/* fneg */
1123
uint64_t helper_fneg (uint64_t arg)
1124
{
1125
    CPU_DoubleU farg;
1126

    
1127
    farg.ll = arg;
1128
    farg.d = float64_chs(farg.d);
1129
    return farg.ll;
1130
}
1131

    
1132
/* fctiw - fctiw. */
1133
uint64_t helper_fctiw (uint64_t arg)
1134
{
1135
    CPU_DoubleU farg;
1136
    farg.ll = arg;
1137

    
1138
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1139
        /* sNaN conversion */
1140
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1141
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1142
        /* qNan / infinity conversion */
1143
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1144
    } else {
1145
        farg.ll = float64_to_int32(farg.d, &env->fp_status);
1146
#if USE_PRECISE_EMULATION
1147
        /* XXX: higher bits are not supposed to be significant.
1148
         *     to make tests easier, return the same as a real PowerPC 750
1149
         */
1150
        farg.ll |= 0xFFF80000ULL << 32;
1151
#endif
1152
    }
1153
    return farg.ll;
1154
}
1155

    
1156
/* fctiwz - fctiwz. */
1157
uint64_t helper_fctiwz (uint64_t arg)
1158
{
1159
    CPU_DoubleU farg;
1160
    farg.ll = arg;
1161

    
1162
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1163
        /* sNaN conversion */
1164
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1165
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1166
        /* qNan / infinity conversion */
1167
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1168
    } else {
1169
        farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
1170
#if USE_PRECISE_EMULATION
1171
        /* XXX: higher bits are not supposed to be significant.
1172
         *     to make tests easier, return the same as a real PowerPC 750
1173
         */
1174
        farg.ll |= 0xFFF80000ULL << 32;
1175
#endif
1176
    }
1177
    return farg.ll;
1178
}
1179

    
1180
#if defined(TARGET_PPC64)
1181
/* fcfid - fcfid. */
1182
uint64_t helper_fcfid (uint64_t arg)
1183
{
1184
    CPU_DoubleU farg;
1185
    farg.d = int64_to_float64(arg, &env->fp_status);
1186
    return farg.ll;
1187
}
1188

    
1189
/* fctid - fctid. */
1190
uint64_t helper_fctid (uint64_t arg)
1191
{
1192
    CPU_DoubleU farg;
1193
    farg.ll = arg;
1194

    
1195
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1196
        /* sNaN conversion */
1197
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1198
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1199
        /* qNan / infinity conversion */
1200
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1201
    } else {
1202
        farg.ll = float64_to_int64(farg.d, &env->fp_status);
1203
    }
1204
    return farg.ll;
1205
}
1206

    
1207
/* fctidz - fctidz. */
1208
uint64_t helper_fctidz (uint64_t arg)
1209
{
1210
    CPU_DoubleU farg;
1211
    farg.ll = arg;
1212

    
1213
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1214
        /* sNaN conversion */
1215
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1216
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1217
        /* qNan / infinity conversion */
1218
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1219
    } else {
1220
        farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
1221
    }
1222
    return farg.ll;
1223
}
1224

    
1225
#endif
1226

    
1227
static always_inline uint64_t do_fri (uint64_t arg, int rounding_mode)
1228
{
1229
    CPU_DoubleU farg;
1230
    farg.ll = arg;
1231

    
1232
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1233
        /* sNaN round */
1234
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1235
    } else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1236
        /* qNan / infinity round */
1237
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1238
    } else {
1239
        set_float_rounding_mode(rounding_mode, &env->fp_status);
1240
        farg.ll = float64_round_to_int(farg.d, &env->fp_status);
1241
        /* Restore rounding mode from FPSCR */
1242
        fpscr_set_rounding_mode();
1243
    }
1244
    return farg.ll;
1245
}
1246

    
1247
uint64_t helper_frin (uint64_t arg)
1248
{
1249
    return do_fri(arg, float_round_nearest_even);
1250
}
1251

    
1252
uint64_t helper_friz (uint64_t arg)
1253
{
1254
    return do_fri(arg, float_round_to_zero);
1255
}
1256

    
1257
uint64_t helper_frip (uint64_t arg)
1258
{
1259
    return do_fri(arg, float_round_up);
1260
}
1261

    
1262
uint64_t helper_frim (uint64_t arg)
1263
{
1264
    return do_fri(arg, float_round_down);
1265
}
1266

    
1267
/* fmadd - fmadd. */
1268
uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1269
{
1270
    CPU_DoubleU farg1, farg2, farg3;
1271

    
1272
    farg1.ll = arg1;
1273
    farg2.ll = arg2;
1274
    farg3.ll = arg3;
1275
#if USE_PRECISE_EMULATION
1276
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1277
                 float64_is_signaling_nan(farg2.d) ||
1278
                 float64_is_signaling_nan(farg3.d))) {
1279
        /* sNaN operation */
1280
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1281
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1282
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1283
        /* Multiplication of zero by infinity */
1284
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1285
    } else {
1286
#ifdef FLOAT128
1287
        /* This is the way the PowerPC specification defines it */
1288
        float128 ft0_128, ft1_128;
1289

    
1290
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1291
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1292
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1293
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1294
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1295
            /* Magnitude subtraction of infinities */
1296
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1297
        } else {
1298
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1299
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1300
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1301
        }
1302
#else
1303
        /* This is OK on x86 hosts */
1304
        farg1.d = (farg1.d * farg2.d) + farg3.d;
1305
#endif
1306
    }
1307
#else
1308
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1309
    farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1310
#endif
1311
    return farg1.ll;
1312
}
1313

    
1314
/* fmsub - fmsub. */
1315
uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1316
{
1317
    CPU_DoubleU farg1, farg2, farg3;
1318

    
1319
    farg1.ll = arg1;
1320
    farg2.ll = arg2;
1321
    farg3.ll = arg3;
1322
#if USE_PRECISE_EMULATION
1323
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1324
                 float64_is_signaling_nan(farg2.d) ||
1325
                 float64_is_signaling_nan(farg3.d))) {
1326
        /* sNaN operation */
1327
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1328
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1329
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1330
        /* Multiplication of zero by infinity */
1331
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1332
    } else {
1333
#ifdef FLOAT128
1334
        /* This is the way the PowerPC specification defines it */
1335
        float128 ft0_128, ft1_128;
1336

    
1337
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1338
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1339
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1340
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1341
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1342
            /* Magnitude subtraction of infinities */
1343
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1344
        } else {
1345
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1346
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1347
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1348
        }
1349
#else
1350
        /* This is OK on x86 hosts */
1351
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1352
#endif
1353
    }
1354
#else
1355
    farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1356
    farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1357
#endif
1358
    return farg1.ll;
1359
}
1360

    
1361
/* fnmadd - fnmadd. */
1362
uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1363
{
1364
    CPU_DoubleU farg1, farg2, farg3;
1365

    
1366
    farg1.ll = arg1;
1367
    farg2.ll = arg2;
1368
    farg3.ll = arg3;
1369

    
1370
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1371
                 float64_is_signaling_nan(farg2.d) ||
1372
                 float64_is_signaling_nan(farg3.d))) {
1373
        /* sNaN operation */
1374
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1375
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1376
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1377
        /* Multiplication of zero by infinity */
1378
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1379
    } else {
1380
#if USE_PRECISE_EMULATION
1381
#ifdef FLOAT128
1382
        /* This is the way the PowerPC specification defines it */
1383
        float128 ft0_128, ft1_128;
1384

    
1385
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1386
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1387
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1388
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1389
                     float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1390
            /* Magnitude subtraction of infinities */
1391
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1392
        } else {
1393
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1394
            ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1395
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1396
        }
1397
#else
1398
        /* This is OK on x86 hosts */
1399
        farg1.d = (farg1.d * farg2.d) + farg3.d;
1400
#endif
1401
#else
1402
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1403
        farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1404
#endif
1405
        if (likely(!float64_is_nan(farg1.d)))
1406
            farg1.d = float64_chs(farg1.d);
1407
    }
1408
    return farg1.ll;
1409
}
1410

    
1411
/* fnmsub - fnmsub. */
1412
uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1413
{
1414
    CPU_DoubleU farg1, farg2, farg3;
1415

    
1416
    farg1.ll = arg1;
1417
    farg2.ll = arg2;
1418
    farg3.ll = arg3;
1419

    
1420
    if (unlikely(float64_is_signaling_nan(farg1.d) ||
1421
                 float64_is_signaling_nan(farg2.d) ||
1422
                 float64_is_signaling_nan(farg3.d))) {
1423
        /* sNaN operation */
1424
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1425
    } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1426
                        (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1427
        /* Multiplication of zero by infinity */
1428
        farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1429
    } else {
1430
#if USE_PRECISE_EMULATION
1431
#ifdef FLOAT128
1432
        /* This is the way the PowerPC specification defines it */
1433
        float128 ft0_128, ft1_128;
1434

    
1435
        ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1436
        ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1437
        ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1438
        if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1439
                     float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1440
            /* Magnitude subtraction of infinities */
1441
            farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1442
        } else {
1443
            ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1444
            ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1445
            farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1446
        }
1447
#else
1448
        /* This is OK on x86 hosts */
1449
        farg1.d = (farg1.d * farg2.d) - farg3.d;
1450
#endif
1451
#else
1452
        farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1453
        farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1454
#endif
1455
        if (likely(!float64_is_nan(farg1.d)))
1456
            farg1.d = float64_chs(farg1.d);
1457
    }
1458
    return farg1.ll;
1459
}
1460

    
1461
/* frsp - frsp. */
1462
uint64_t helper_frsp (uint64_t arg)
1463
{
1464
    CPU_DoubleU farg;
1465
    float32 f32;
1466
    farg.ll = arg;
1467

    
1468
#if USE_PRECISE_EMULATION
1469
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1470
        /* sNaN square root */
1471
       farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1472
    } else {
1473
       f32 = float64_to_float32(farg.d, &env->fp_status);
1474
       farg.d = float32_to_float64(f32, &env->fp_status);
1475
    }
1476
#else
1477
    f32 = float64_to_float32(farg.d, &env->fp_status);
1478
    farg.d = float32_to_float64(f32, &env->fp_status);
1479
#endif
1480
    return farg.ll;
1481
}
1482

    
1483
/* fsqrt - fsqrt. */
1484
uint64_t helper_fsqrt (uint64_t arg)
1485
{
1486
    CPU_DoubleU farg;
1487
    farg.ll = arg;
1488

    
1489
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1490
        /* sNaN square root */
1491
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1492
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1493
        /* Square root of a negative nonzero number */
1494
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1495
    } else {
1496
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1497
    }
1498
    return farg.ll;
1499
}
1500

    
1501
/* fre - fre. */
1502
uint64_t helper_fre (uint64_t arg)
1503
{
1504
    CPU_DoubleU farg;
1505
    farg.ll = arg;
1506

    
1507
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1508
        /* sNaN reciprocal */
1509
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1510
    } else {
1511
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1512
    }
1513
    return farg.d;
1514
}
1515

    
1516
/* fres - fres. */
1517
uint64_t helper_fres (uint64_t arg)
1518
{
1519
    CPU_DoubleU farg;
1520
    float32 f32;
1521
    farg.ll = arg;
1522

    
1523
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1524
        /* sNaN reciprocal */
1525
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1526
    } else {
1527
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1528
        f32 = float64_to_float32(farg.d, &env->fp_status);
1529
        farg.d = float32_to_float64(f32, &env->fp_status);
1530
    }
1531
    return farg.ll;
1532
}
1533

    
1534
/* frsqrte  - frsqrte. */
1535
uint64_t helper_frsqrte (uint64_t arg)
1536
{
1537
    CPU_DoubleU farg;
1538
    float32 f32;
1539
    farg.ll = arg;
1540

    
1541
    if (unlikely(float64_is_signaling_nan(farg.d))) {
1542
        /* sNaN reciprocal square root */
1543
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1544
    } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1545
        /* Reciprocal square root of a negative nonzero number */
1546
        farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1547
    } else {
1548
        farg.d = float64_sqrt(farg.d, &env->fp_status);
1549
        farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1550
        f32 = float64_to_float32(farg.d, &env->fp_status);
1551
        farg.d = float32_to_float64(f32, &env->fp_status);
1552
    }
1553
    return farg.ll;
1554
}
1555

    
1556
/* fsel - fsel. */
1557
uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1558
{
1559
    CPU_DoubleU farg1;
1560

    
1561
    farg1.ll = arg1;
1562

    
1563
    if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_nan(farg1.d))
1564
        return arg2;
1565
    else
1566
        return arg3;
1567
}
1568

    
1569
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1570
{
1571
    CPU_DoubleU farg1, farg2;
1572
    uint32_t ret = 0;
1573
    farg1.ll = arg1;
1574
    farg2.ll = arg2;
1575

    
1576
    if (unlikely(float64_is_nan(farg1.d) ||
1577
                 float64_is_nan(farg2.d))) {
1578
        ret = 0x01UL;
1579
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1580
        ret = 0x08UL;
1581
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1582
        ret = 0x04UL;
1583
    } else {
1584
        ret = 0x02UL;
1585
    }
1586

    
1587
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1588
    env->fpscr |= ret << FPSCR_FPRF;
1589
    env->crf[crfD] = ret;
1590
    if (unlikely(ret == 0x01UL
1591
                 && (float64_is_signaling_nan(farg1.d) ||
1592
                     float64_is_signaling_nan(farg2.d)))) {
1593
        /* sNaN comparison */
1594
        fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1595
    }
1596
}
1597

    
1598
void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1599
{
1600
    CPU_DoubleU farg1, farg2;
1601
    uint32_t ret = 0;
1602
    farg1.ll = arg1;
1603
    farg2.ll = arg2;
1604

    
1605
    if (unlikely(float64_is_nan(farg1.d) ||
1606
                 float64_is_nan(farg2.d))) {
1607
        ret = 0x01UL;
1608
    } else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1609
        ret = 0x08UL;
1610
    } else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1611
        ret = 0x04UL;
1612
    } else {
1613
        ret = 0x02UL;
1614
    }
1615

    
1616
    env->fpscr &= ~(0x0F << FPSCR_FPRF);
1617
    env->fpscr |= ret << FPSCR_FPRF;
1618
    env->crf[crfD] = ret;
1619
    if (unlikely (ret == 0x01UL)) {
1620
        if (float64_is_signaling_nan(farg1.d) ||
1621
            float64_is_signaling_nan(farg2.d)) {
1622
            /* sNaN comparison */
1623
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1624
                                  POWERPC_EXCP_FP_VXVC);
1625
        } else {
1626
            /* qNaN comparison */
1627
            fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC);
1628
        }
1629
    }
1630
}
1631

    
1632
#if !defined (CONFIG_USER_ONLY)
1633
void helper_store_msr (target_ulong val)
1634
{
1635
    val = hreg_store_msr(env, val, 0);
1636
    if (val != 0) {
1637
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1638
        helper_raise_exception(val);
1639
    }
1640
}
1641

    
1642
static always_inline void do_rfi (target_ulong nip, target_ulong msr,
1643
                                    target_ulong msrm, int keep_msrh)
1644
{
1645
#if defined(TARGET_PPC64)
1646
    if (msr & (1ULL << MSR_SF)) {
1647
        nip = (uint64_t)nip;
1648
        msr &= (uint64_t)msrm;
1649
    } else {
1650
        nip = (uint32_t)nip;
1651
        msr = (uint32_t)(msr & msrm);
1652
        if (keep_msrh)
1653
            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
1654
    }
1655
#else
1656
    nip = (uint32_t)nip;
1657
    msr &= (uint32_t)msrm;
1658
#endif
1659
    /* XXX: beware: this is false if VLE is supported */
1660
    env->nip = nip & ~((target_ulong)0x00000003);
1661
    hreg_store_msr(env, msr, 1);
1662
#if defined (DEBUG_OP)
1663
    cpu_dump_rfi(env->nip, env->msr);
1664
#endif
1665
    /* No need to raise an exception here,
1666
     * as rfi is always the last insn of a TB
1667
     */
1668
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1669
}
1670

    
1671
void helper_rfi (void)
1672
{
1673
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1674
           ~((target_ulong)0xFFFF0000), 1);
1675
}
1676

    
1677
#if defined(TARGET_PPC64)
1678
void helper_rfid (void)
1679
{
1680
    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
1681
           ~((target_ulong)0xFFFF0000), 0);
1682
}
1683

    
1684
void helper_hrfid (void)
1685
{
1686
    do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
1687
           ~((target_ulong)0xFFFF0000), 0);
1688
}
1689
#endif
1690
#endif
1691

    
1692
void helper_tw (target_ulong arg1, target_ulong arg2, uint32_t flags)
1693
{
1694
    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1695
                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1696
                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1697
                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1698
                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1699
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1700
    }
1701
}
1702

    
1703
#if defined(TARGET_PPC64)
1704
void helper_td (target_ulong arg1, target_ulong arg2, uint32_t flags)
1705
{
1706
    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1707
                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1708
                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1709
                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1710
                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01)))))
1711
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1712
}
1713
#endif
1714

    
1715
/*****************************************************************************/
1716
/* PowerPC 601 specific instructions (POWER bridge) */
1717

    
1718
target_ulong helper_clcs (uint32_t arg)
1719
{
1720
    switch (arg) {
1721
    case 0x0CUL:
1722
        /* Instruction cache line size */
1723
        return env->icache_line_size;
1724
        break;
1725
    case 0x0DUL:
1726
        /* Data cache line size */
1727
        return env->dcache_line_size;
1728
        break;
1729
    case 0x0EUL:
1730
        /* Minimum cache line size */
1731
        return (env->icache_line_size < env->dcache_line_size) ?
1732
                env->icache_line_size : env->dcache_line_size;
1733
        break;
1734
    case 0x0FUL:
1735
        /* Maximum cache line size */
1736
        return (env->icache_line_size > env->dcache_line_size) ?
1737
                env->icache_line_size : env->dcache_line_size;
1738
        break;
1739
    default:
1740
        /* Undefined */
1741
        return 0;
1742
        break;
1743
    }
1744
}
1745

    
1746
target_ulong helper_div (target_ulong arg1, target_ulong arg2)
1747
{
1748
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1749

    
1750
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1751
        (int32_t)arg2 == 0) {
1752
        env->spr[SPR_MQ] = 0;
1753
        return INT32_MIN;
1754
    } else {
1755
        env->spr[SPR_MQ] = tmp % arg2;
1756
        return  tmp / (int32_t)arg2;
1757
    }
1758
}
1759

    
1760
target_ulong helper_divo (target_ulong arg1, target_ulong arg2)
1761
{
1762
    uint64_t tmp = (uint64_t)arg1 << 32 | env->spr[SPR_MQ];
1763

    
1764
    if (((int32_t)tmp == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1765
        (int32_t)arg2 == 0) {
1766
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
1767
        env->spr[SPR_MQ] = 0;
1768
        return INT32_MIN;
1769
    } else {
1770
        env->spr[SPR_MQ] = tmp % arg2;
1771
        tmp /= (int32_t)arg2;
1772
        if ((int32_t)tmp != tmp) {
1773
            env->xer |= (1 << XER_OV) | (1 << XER_SO);
1774
        } else {
1775
            env->xer &= ~(1 << XER_OV);
1776
        }
1777
        return tmp;
1778
    }
1779
}
1780

    
1781
target_ulong helper_divs (target_ulong arg1, target_ulong arg2)
1782
{
1783
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1784
        (int32_t)arg2 == 0) {
1785
        env->spr[SPR_MQ] = 0;
1786
        return INT32_MIN;
1787
    } else {
1788
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1789
        return (int32_t)arg1 / (int32_t)arg2;
1790
    }
1791
}
1792

    
1793
target_ulong helper_divso (target_ulong arg1, target_ulong arg2)
1794
{
1795
    if (((int32_t)arg1 == INT32_MIN && (int32_t)arg2 == (int32_t)-1) ||
1796
        (int32_t)arg2 == 0) {
1797
        env->xer |= (1 << XER_OV) | (1 << XER_SO);
1798
        env->spr[SPR_MQ] = 0;
1799
        return INT32_MIN;
1800
    } else {
1801
        env->xer &= ~(1 << XER_OV);
1802
        env->spr[SPR_MQ] = (int32_t)arg1 % (int32_t)arg2;
1803
        return (int32_t)arg1 / (int32_t)arg2;
1804
    }
1805
}
1806

    
1807
#if !defined (CONFIG_USER_ONLY)
1808
target_ulong helper_rac (target_ulong addr)
1809
{
1810
    mmu_ctx_t ctx;
1811
    int nb_BATs;
1812
    target_ulong ret = 0;
1813

    
1814
    /* We don't have to generate many instances of this instruction,
1815
     * as rac is supervisor only.
1816
     */
1817
    /* XXX: FIX THIS: Pretend we have no BAT */
1818
    nb_BATs = env->nb_BATs;
1819
    env->nb_BATs = 0;
1820
    if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0)
1821
        ret = ctx.raddr;
1822
    env->nb_BATs = nb_BATs;
1823
    return ret;
1824
}
1825

    
1826
void helper_rfsvc (void)
1827
{
1828
    do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1829
}
1830
#endif
1831

    
1832
/*****************************************************************************/
1833
/* 602 specific instructions */
1834
/* mfrom is the most crazy instruction ever seen, imho ! */
1835
/* Real implementation uses a ROM table. Do the same */
1836
/* Extremly decomposed:
1837
 *                      -arg / 256
1838
 * return 256 * log10(10           + 1.0) + 0.5
1839
 */
1840
#if !defined (CONFIG_USER_ONLY)
1841
target_ulong helper_602_mfrom (target_ulong arg)
1842
{
1843
    if (likely(arg < 602)) {
1844
#include "mfrom_table.c"
1845
        return mfrom_ROM_table[arg];
1846
    } else {
1847
        return 0;
1848
    }
1849
}
1850
#endif
1851

    
1852
/*****************************************************************************/
1853
/* Embedded PowerPC specific helpers */
1854

    
1855
/* XXX: to be improved to check access rights when in user-mode */
1856
target_ulong helper_load_dcr (target_ulong dcrn)
1857
{
1858
    target_ulong val = 0;
1859

    
1860
    if (unlikely(env->dcr_env == NULL)) {
1861
        qemu_log("No DCR environment\n");
1862
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1863
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1864
    } else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) {
1865
        qemu_log("DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
1866
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1867
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1868
    }
1869
    return val;
1870
}
1871

    
1872
void helper_store_dcr (target_ulong dcrn, target_ulong val)
1873
{
1874
    if (unlikely(env->dcr_env == NULL)) {
1875
        qemu_log("No DCR environment\n");
1876
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1877
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1878
    } else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) {
1879
        qemu_log("DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
1880
        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1881
                                   POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1882
    }
1883
}
1884

    
1885
#if !defined(CONFIG_USER_ONLY)
1886
void helper_40x_rfci (void)
1887
{
1888
    do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1889
           ~((target_ulong)0xFFFF0000), 0);
1890
}
1891

    
1892
void helper_rfci (void)
1893
{
1894
    do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1895
           ~((target_ulong)0x3FFF0000), 0);
1896
}
1897

    
1898
void helper_rfdi (void)
1899
{
1900
    do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1901
           ~((target_ulong)0x3FFF0000), 0);
1902
}
1903

    
1904
void helper_rfmci (void)
1905
{
1906
    do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1907
           ~((target_ulong)0x3FFF0000), 0);
1908
}
1909
#endif
1910

    
1911
/* 440 specific */
1912
target_ulong helper_dlmzb (target_ulong high, target_ulong low, uint32_t update_Rc)
1913
{
1914
    target_ulong mask;
1915
    int i;
1916

    
1917
    i = 1;
1918
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1919
        if ((high & mask) == 0) {
1920
            if (update_Rc) {
1921
                env->crf[0] = 0x4;
1922
            }
1923
            goto done;
1924
        }
1925
        i++;
1926
    }
1927
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1928
        if ((low & mask) == 0) {
1929
            if (update_Rc) {
1930
                env->crf[0] = 0x8;
1931
            }
1932
            goto done;
1933
        }
1934
        i++;
1935
    }
1936
    if (update_Rc) {
1937
        env->crf[0] = 0x2;
1938
    }
1939
 done:
1940
    env->xer = (env->xer & ~0x7F) | i;
1941
    if (update_Rc) {
1942
        env->crf[0] |= xer_so;
1943
    }
1944
    return i;
1945
}
1946

    
1947
/*****************************************************************************/
1948
/* Altivec extension helpers */
1949
#if defined(WORDS_BIGENDIAN)
1950
#define HI_IDX 0
1951
#define LO_IDX 1
1952
#else
1953
#define HI_IDX 1
1954
#define LO_IDX 0
1955
#endif
1956

    
1957
#if defined(WORDS_BIGENDIAN)
1958
#define VECTOR_FOR_INORDER_I(index, element)            \
1959
    for (index = 0; index < ARRAY_SIZE(r->element); index++)
1960
#else
1961
#define VECTOR_FOR_INORDER_I(index, element)            \
1962
  for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
1963
#endif
1964

    
1965
/* If X is a NaN, store the corresponding QNaN into RESULT.  Otherwise,
1966
 * execute the following block.  */
1967
#define DO_HANDLE_NAN(result, x)                \
1968
    if (float32_is_nan(x) || float32_is_signaling_nan(x)) {     \
1969
        CPU_FloatU __f;                                         \
1970
        __f.f = x;                                              \
1971
        __f.l = __f.l | (1 << 22);  /* Set QNaN bit. */         \
1972
        result = __f.f;                                         \
1973
    } else
1974

    
1975
#define HANDLE_NAN1(result, x)                  \
1976
    DO_HANDLE_NAN(result, x)
1977
#define HANDLE_NAN2(result, x, y)               \
1978
    DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
1979
#define HANDLE_NAN3(result, x, y, z)            \
1980
    DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
1981

    
1982
/* Saturating arithmetic helpers.  */
1983
#define SATCVT(from, to, from_type, to_type, min, max, use_min, use_max) \
1984
    static always_inline to_type cvt##from##to (from_type x, int *sat)  \
1985
    {                                                                   \
1986
        to_type r;                                                      \
1987
        if (use_min && x < min) {                                       \
1988
            r = min;                                                    \
1989
            *sat = 1;                                                   \
1990
        } else if (use_max && x > max) {                                \
1991
            r = max;                                                    \
1992
            *sat = 1;                                                   \
1993
        } else {                                                        \
1994
            r = x;                                                      \
1995
        }                                                               \
1996
        return r;                                                       \
1997
    }
1998
SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX, 1, 1)
1999
SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX, 1, 1)
2000
SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX, 1, 1)
2001
SATCVT(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX, 0, 1)
2002
SATCVT(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX, 0, 1)
2003
SATCVT(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX, 0, 1)
2004
SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX, 1, 1)
2005
SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX, 1, 1)
2006
SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX, 1, 1)
2007
#undef SATCVT
2008

    
2009
#define LVE(name, access, swap, element)                        \
2010
    void helper_##name (ppc_avr_t *r, target_ulong addr)        \
2011
    {                                                           \
2012
        size_t n_elems = ARRAY_SIZE(r->element);                \
2013
        int adjust = HI_IDX*(n_elems-1);                        \
2014
        int sh = sizeof(r->element[0]) >> 1;                    \
2015
        int index = (addr & 0xf) >> sh;                         \
2016
        if(msr_le) {                                            \
2017
            r->element[LO_IDX ? index : (adjust - index)] = swap(access(addr)); \
2018
        } else {                                                        \
2019
            r->element[LO_IDX ? index : (adjust - index)] = access(addr); \
2020
        }                                                               \
2021
    }
2022
#define I(x) (x)
2023
LVE(lvebx, ldub, I, u8)
2024
LVE(lvehx, lduw, bswap16, u16)
2025
LVE(lvewx, ldl, bswap32, u32)
2026
#undef I
2027
#undef LVE
2028

    
2029
void helper_lvsl (ppc_avr_t *r, target_ulong sh)
2030
{
2031
    int i, j = (sh & 0xf);
2032

    
2033
    VECTOR_FOR_INORDER_I (i, u8) {
2034
        r->u8[i] = j++;
2035
    }
2036
}
2037

    
2038
void helper_lvsr (ppc_avr_t *r, target_ulong sh)
2039
{
2040
    int i, j = 0x10 - (sh & 0xf);
2041

    
2042
    VECTOR_FOR_INORDER_I (i, u8) {
2043
        r->u8[i] = j++;
2044
    }
2045
}
2046

    
2047
#define STVE(name, access, swap, element)                       \
2048
    void helper_##name (ppc_avr_t *r, target_ulong addr)        \
2049
    {                                                           \
2050
        size_t n_elems = ARRAY_SIZE(r->element);                \
2051
        int adjust = HI_IDX*(n_elems-1);                        \
2052
        int sh = sizeof(r->element[0]) >> 1;                    \
2053
        int index = (addr & 0xf) >> sh;                         \
2054
        if(msr_le) {                                            \
2055
            access(addr, swap(r->element[LO_IDX ? index : (adjust - index)])); \
2056
        } else {                                                        \
2057
            access(addr, r->element[LO_IDX ? index : (adjust - index)]); \
2058
        }                                                               \
2059
    }
2060
#define I(x) (x)
2061
STVE(stvebx, stb, I, u8)
2062
STVE(stvehx, stw, bswap16, u16)
2063
STVE(stvewx, stl, bswap32, u32)
2064
#undef I
2065
#undef LVE
2066

    
2067
void helper_mtvscr (ppc_avr_t *r)
2068
{
2069
#if defined(WORDS_BIGENDIAN)
2070
    env->vscr = r->u32[3];
2071
#else
2072
    env->vscr = r->u32[0];
2073
#endif
2074
    set_flush_to_zero(vscr_nj, &env->vec_status);
2075
}
2076

    
2077
void helper_vaddcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2078
{
2079
    int i;
2080
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2081
        r->u32[i] = ~a->u32[i] < b->u32[i];
2082
    }
2083
}
2084

    
2085
#define VARITH_DO(name, op, element)        \
2086
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)          \
2087
{                                                                       \
2088
    int i;                                                              \
2089
    for (i = 0; i < ARRAY_SIZE(r->element); i++) {                      \
2090
        r->element[i] = a->element[i] op b->element[i];                 \
2091
    }                                                                   \
2092
}
2093
#define VARITH(suffix, element)                  \
2094
  VARITH_DO(add##suffix, +, element)             \
2095
  VARITH_DO(sub##suffix, -, element)
2096
VARITH(ubm, u8)
2097
VARITH(uhm, u16)
2098
VARITH(uwm, u32)
2099
#undef VARITH_DO
2100
#undef VARITH
2101

    
2102
#define VARITHFP(suffix, func)                                          \
2103
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
2104
    {                                                                   \
2105
        int i;                                                          \
2106
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2107
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2108
                r->f[i] = func(a->f[i], b->f[i], &env->vec_status);     \
2109
            }                                                           \
2110
        }                                                               \
2111
    }
2112
VARITHFP(addfp, float32_add)
2113
VARITHFP(subfp, float32_sub)
2114
#undef VARITHFP
2115

    
2116
#define VARITHSAT_CASE(type, op, cvt, element)                          \
2117
    {                                                                   \
2118
        type result = (type)a->element[i] op (type)b->element[i];       \
2119
        r->element[i] = cvt(result, &sat);                              \
2120
    }
2121

    
2122
#define VARITHSAT_DO(name, op, optype, cvt, element)                    \
2123
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2124
    {                                                                   \
2125
        int sat = 0;                                                    \
2126
        int i;                                                          \
2127
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2128
            switch (sizeof(r->element[0])) {                            \
2129
            case 1: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2130
            case 2: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2131
            case 4: VARITHSAT_CASE(optype, op, cvt, element); break;    \
2132
            }                                                           \
2133
        }                                                               \
2134
        if (sat) {                                                      \
2135
            env->vscr |= (1 << VSCR_SAT);                               \
2136
        }                                                               \
2137
    }
2138
#define VARITHSAT_SIGNED(suffix, element, optype, cvt)        \
2139
    VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element)    \
2140
    VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
2141
#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt)       \
2142
    VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element)     \
2143
    VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
2144
VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
2145
VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
2146
VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
2147
VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
2148
VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
2149
VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
2150
#undef VARITHSAT_CASE
2151
#undef VARITHSAT_DO
2152
#undef VARITHSAT_SIGNED
2153
#undef VARITHSAT_UNSIGNED
2154

    
2155
#define VAVG_DO(name, element, etype)                                   \
2156
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2157
    {                                                                   \
2158
        int i;                                                          \
2159
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2160
            etype x = (etype)a->element[i] + (etype)b->element[i] + 1;  \
2161
            r->element[i] = x >> 1;                                     \
2162
        }                                                               \
2163
    }
2164

    
2165
#define VAVG(type, signed_element, signed_type, unsigned_element, unsigned_type) \
2166
    VAVG_DO(avgs##type, signed_element, signed_type)                    \
2167
    VAVG_DO(avgu##type, unsigned_element, unsigned_type)
2168
VAVG(b, s8, int16_t, u8, uint16_t)
2169
VAVG(h, s16, int32_t, u16, uint32_t)
2170
VAVG(w, s32, int64_t, u32, uint64_t)
2171
#undef VAVG_DO
2172
#undef VAVG
2173

    
2174
#define VCF(suffix, cvt, element)                                       \
2175
    void helper_vcf##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim)  \
2176
    {                                                                   \
2177
        int i;                                                          \
2178
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2179
            float32 t = cvt(b->element[i], &env->vec_status);           \
2180
            r->f[i] = float32_scalbn (t, -uim, &env->vec_status);       \
2181
        }                                                               \
2182
    }
2183
VCF(ux, uint32_to_float32, u32)
2184
VCF(sx, int32_to_float32, s32)
2185
#undef VCF
2186

    
2187
#define VCMP_DO(suffix, compare, element, record)                       \
2188
    void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2189
    {                                                                   \
2190
        uint32_t ones = (uint32_t)-1;                                   \
2191
        uint32_t all = ones;                                            \
2192
        uint32_t none = 0;                                              \
2193
        int i;                                                          \
2194
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2195
            uint32_t result = (a->element[i] compare b->element[i] ? ones : 0x0); \
2196
            switch (sizeof (a->element[0])) {                           \
2197
            case 4: r->u32[i] = result; break;                          \
2198
            case 2: r->u16[i] = result; break;                          \
2199
            case 1: r->u8[i] = result; break;                           \
2200
            }                                                           \
2201
            all &= result;                                              \
2202
            none |= result;                                             \
2203
        }                                                               \
2204
        if (record) {                                                   \
2205
            env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1);       \
2206
        }                                                               \
2207
    }
2208
#define VCMP(suffix, compare, element)          \
2209
    VCMP_DO(suffix, compare, element, 0)        \
2210
    VCMP_DO(suffix##_dot, compare, element, 1)
2211
VCMP(equb, ==, u8)
2212
VCMP(equh, ==, u16)
2213
VCMP(equw, ==, u32)
2214
VCMP(gtub, >, u8)
2215
VCMP(gtuh, >, u16)
2216
VCMP(gtuw, >, u32)
2217
VCMP(gtsb, >, s8)
2218
VCMP(gtsh, >, s16)
2219
VCMP(gtsw, >, s32)
2220
#undef VCMP_DO
2221
#undef VCMP
2222

    
2223
void helper_vmaddfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2224
{
2225
    int i;
2226
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2227
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2228
            /* Need to do the computation in higher precision and round
2229
             * once at the end.  */
2230
            float64 af, bf, cf, t;
2231
            af = float32_to_float64(a->f[i], &env->vec_status);
2232
            bf = float32_to_float64(b->f[i], &env->vec_status);
2233
            cf = float32_to_float64(c->f[i], &env->vec_status);
2234
            t = float64_mul(af, cf, &env->vec_status);
2235
            t = float64_add(t, bf, &env->vec_status);
2236
            r->f[i] = float64_to_float32(t, &env->vec_status);
2237
        }
2238
    }
2239
}
2240

    
2241
void helper_vmhaddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2242
{
2243
    int sat = 0;
2244
    int i;
2245

    
2246
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2247
        int32_t prod = a->s16[i] * b->s16[i];
2248
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2249
        r->s16[i] = cvtswsh (t, &sat);
2250
    }
2251

    
2252
    if (sat) {
2253
        env->vscr |= (1 << VSCR_SAT);
2254
    }
2255
}
2256

    
2257
void helper_vmhraddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2258
{
2259
    int sat = 0;
2260
    int i;
2261

    
2262
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2263
        int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
2264
        int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2265
        r->s16[i] = cvtswsh (t, &sat);
2266
    }
2267

    
2268
    if (sat) {
2269
        env->vscr |= (1 << VSCR_SAT);
2270
    }
2271
}
2272

    
2273
#define VMINMAX_DO(name, compare, element)                              \
2274
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2275
    {                                                                   \
2276
        int i;                                                          \
2277
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2278
            if (a->element[i] compare b->element[i]) {                  \
2279
                r->element[i] = b->element[i];                          \
2280
            } else {                                                    \
2281
                r->element[i] = a->element[i];                          \
2282
            }                                                           \
2283
        }                                                               \
2284
    }
2285
#define VMINMAX(suffix, element)                \
2286
  VMINMAX_DO(min##suffix, >, element)           \
2287
  VMINMAX_DO(max##suffix, <, element)
2288
VMINMAX(sb, s8)
2289
VMINMAX(sh, s16)
2290
VMINMAX(sw, s32)
2291
VMINMAX(ub, u8)
2292
VMINMAX(uh, u16)
2293
VMINMAX(uw, u32)
2294
#undef VMINMAX_DO
2295
#undef VMINMAX
2296

    
2297
#define VMINMAXFP(suffix, rT, rF)                                       \
2298
    void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)    \
2299
    {                                                                   \
2300
        int i;                                                          \
2301
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2302
            HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) {                    \
2303
                if (float32_lt_quiet(a->f[i], b->f[i], &env->vec_status)) { \
2304
                    r->f[i] = rT->f[i];                                 \
2305
                } else {                                                \
2306
                    r->f[i] = rF->f[i];                                 \
2307
                }                                                       \
2308
            }                                                           \
2309
        }                                                               \
2310
    }
2311
VMINMAXFP(minfp, a, b)
2312
VMINMAXFP(maxfp, b, a)
2313
#undef VMINMAXFP
2314

    
2315
void helper_vmladduhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2316
{
2317
    int i;
2318
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2319
        int32_t prod = a->s16[i] * b->s16[i];
2320
        r->s16[i] = (int16_t) (prod + c->s16[i]);
2321
    }
2322
}
2323

    
2324
#define VMRG_DO(name, element, highp)                                   \
2325
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2326
    {                                                                   \
2327
        ppc_avr_t result;                                               \
2328
        int i;                                                          \
2329
        size_t n_elems = ARRAY_SIZE(r->element);                        \
2330
        for (i = 0; i < n_elems/2; i++) {                               \
2331
            if (highp) {                                                \
2332
                result.element[i*2+HI_IDX] = a->element[i];             \
2333
                result.element[i*2+LO_IDX] = b->element[i];             \
2334
            } else {                                                    \
2335
                result.element[n_elems - i*2 - (1+HI_IDX)] = b->element[n_elems - i - 1]; \
2336
                result.element[n_elems - i*2 - (1+LO_IDX)] = a->element[n_elems - i - 1]; \
2337
            }                                                           \
2338
        }                                                               \
2339
        *r = result;                                                    \
2340
    }
2341
#if defined(WORDS_BIGENDIAN)
2342
#define MRGHI 0
2343
#define MRGLO 1
2344
#else
2345
#define MRGHI 1
2346
#define MRGLO 0
2347
#endif
2348
#define VMRG(suffix, element)                   \
2349
  VMRG_DO(mrgl##suffix, element, MRGHI)         \
2350
  VMRG_DO(mrgh##suffix, element, MRGLO)
2351
VMRG(b, u8)
2352
VMRG(h, u16)
2353
VMRG(w, u32)
2354
#undef VMRG_DO
2355
#undef VMRG
2356
#undef MRGHI
2357
#undef MRGLO
2358

    
2359
void helper_vmsummbm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2360
{
2361
    int32_t prod[16];
2362
    int i;
2363

    
2364
    for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
2365
        prod[i] = (int32_t)a->s8[i] * b->u8[i];
2366
    }
2367

    
2368
    VECTOR_FOR_INORDER_I(i, s32) {
2369
        r->s32[i] = c->s32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2370
    }
2371
}
2372

    
2373
void helper_vmsumshm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2374
{
2375
    int32_t prod[8];
2376
    int i;
2377

    
2378
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2379
        prod[i] = a->s16[i] * b->s16[i];
2380
    }
2381

    
2382
    VECTOR_FOR_INORDER_I(i, s32) {
2383
        r->s32[i] = c->s32[i] + prod[2*i] + prod[2*i+1];
2384
    }
2385
}
2386

    
2387
void helper_vmsumshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2388
{
2389
    int32_t prod[8];
2390
    int i;
2391
    int sat = 0;
2392

    
2393
    for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2394
        prod[i] = (int32_t)a->s16[i] * b->s16[i];
2395
    }
2396

    
2397
    VECTOR_FOR_INORDER_I (i, s32) {
2398
        int64_t t = (int64_t)c->s32[i] + prod[2*i] + prod[2*i+1];
2399
        r->u32[i] = cvtsdsw(t, &sat);
2400
    }
2401

    
2402
    if (sat) {
2403
        env->vscr |= (1 << VSCR_SAT);
2404
    }
2405
}
2406

    
2407
void helper_vmsumubm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2408
{
2409
    uint16_t prod[16];
2410
    int i;
2411

    
2412
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2413
        prod[i] = a->u8[i] * b->u8[i];
2414
    }
2415

    
2416
    VECTOR_FOR_INORDER_I(i, u32) {
2417
        r->u32[i] = c->u32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2418
    }
2419
}
2420

    
2421
void helper_vmsumuhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2422
{
2423
    uint32_t prod[8];
2424
    int i;
2425

    
2426
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2427
        prod[i] = a->u16[i] * b->u16[i];
2428
    }
2429

    
2430
    VECTOR_FOR_INORDER_I(i, u32) {
2431
        r->u32[i] = c->u32[i] + prod[2*i] + prod[2*i+1];
2432
    }
2433
}
2434

    
2435
void helper_vmsumuhs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2436
{
2437
    uint32_t prod[8];
2438
    int i;
2439
    int sat = 0;
2440

    
2441
    for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2442
        prod[i] = a->u16[i] * b->u16[i];
2443
    }
2444

    
2445
    VECTOR_FOR_INORDER_I (i, s32) {
2446
        uint64_t t = (uint64_t)c->u32[i] + prod[2*i] + prod[2*i+1];
2447
        r->u32[i] = cvtuduw(t, &sat);
2448
    }
2449

    
2450
    if (sat) {
2451
        env->vscr |= (1 << VSCR_SAT);
2452
    }
2453
}
2454

    
2455
#define VMUL_DO(name, mul_element, prod_element, evenp)                 \
2456
    void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)      \
2457
    {                                                                   \
2458
        int i;                                                          \
2459
        VECTOR_FOR_INORDER_I(i, prod_element) {                         \
2460
            if (evenp) {                                                \
2461
                r->prod_element[i] = a->mul_element[i*2+HI_IDX] * b->mul_element[i*2+HI_IDX]; \
2462
            } else {                                                    \
2463
                r->prod_element[i] = a->mul_element[i*2+LO_IDX] * b->mul_element[i*2+LO_IDX]; \
2464
            }                                                           \
2465
        }                                                               \
2466
    }
2467
#define VMUL(suffix, mul_element, prod_element) \
2468
  VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
2469
  VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
2470
VMUL(sb, s8, s16)
2471
VMUL(sh, s16, s32)
2472
VMUL(ub, u8, u16)
2473
VMUL(uh, u16, u32)
2474
#undef VMUL_DO
2475
#undef VMUL
2476

    
2477
void helper_vnmsubfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2478
{
2479
    int i;
2480
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2481
        HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2482
            /* Need to do the computation is higher precision and round
2483
             * once at the end.  */
2484
            float64 af, bf, cf, t;
2485
            af = float32_to_float64(a->f[i], &env->vec_status);
2486
            bf = float32_to_float64(b->f[i], &env->vec_status);
2487
            cf = float32_to_float64(c->f[i], &env->vec_status);
2488
            t = float64_mul(af, cf, &env->vec_status);
2489
            t = float64_sub(t, bf, &env->vec_status);
2490
            t = float64_chs(t);
2491
            r->f[i] = float64_to_float32(t, &env->vec_status);
2492
        }
2493
    }
2494
}
2495

    
2496
void helper_vperm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2497
{
2498
    ppc_avr_t result;
2499
    int i;
2500
    VECTOR_FOR_INORDER_I (i, u8) {
2501
        int s = c->u8[i] & 0x1f;
2502
#if defined(WORDS_BIGENDIAN)
2503
        int index = s & 0xf;
2504
#else
2505
        int index = 15 - (s & 0xf);
2506
#endif
2507
        if (s & 0x10) {
2508
            result.u8[i] = b->u8[index];
2509
        } else {
2510
            result.u8[i] = a->u8[index];
2511
        }
2512
    }
2513
    *r = result;
2514
}
2515

    
2516
#if defined(WORDS_BIGENDIAN)
2517
#define PKBIG 1
2518
#else
2519
#define PKBIG 0
2520
#endif
2521
void helper_vpkpx (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2522
{
2523
    int i, j;
2524
    ppc_avr_t result;
2525
#if defined(WORDS_BIGENDIAN)
2526
    const ppc_avr_t *x[2] = { a, b };
2527
#else
2528
    const ppc_avr_t *x[2] = { b, a };
2529
#endif
2530

    
2531
    VECTOR_FOR_INORDER_I (i, u64) {
2532
        VECTOR_FOR_INORDER_I (j, u32){
2533
            uint32_t e = x[i]->u32[j];
2534
            result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
2535
                                 ((e >> 6) & 0x3e0) |
2536
                                 ((e >> 3) & 0x1f));
2537
        }
2538
    }
2539
    *r = result;
2540
}
2541

    
2542
#define VPK(suffix, from, to, cvt, dosat)       \
2543
    void helper_vpk##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2544
    {                                                                   \
2545
        int i;                                                          \
2546
        int sat = 0;                                                    \
2547
        ppc_avr_t result;                                               \
2548
        ppc_avr_t *a0 = PKBIG ? a : b;                                  \
2549
        ppc_avr_t *a1 = PKBIG ? b : a;                                  \
2550
        VECTOR_FOR_INORDER_I (i, from) {                                \
2551
            result.to[i] = cvt(a0->from[i], &sat);                      \
2552
            result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);  \
2553
        }                                                               \
2554
        *r = result;                                                    \
2555
        if (dosat && sat) {                                             \
2556
            env->vscr |= (1 << VSCR_SAT);                               \
2557
        }                                                               \
2558
    }
2559
#define I(x, y) (x)
2560
VPK(shss, s16, s8, cvtshsb, 1)
2561
VPK(shus, s16, u8, cvtshub, 1)
2562
VPK(swss, s32, s16, cvtswsh, 1)
2563
VPK(swus, s32, u16, cvtswuh, 1)
2564
VPK(uhus, u16, u8, cvtuhub, 1)
2565
VPK(uwus, u32, u16, cvtuwuh, 1)
2566
VPK(uhum, u16, u8, I, 0)
2567
VPK(uwum, u32, u16, I, 0)
2568
#undef I
2569
#undef VPK
2570
#undef PKBIG
2571

    
2572
#define VRFI(suffix, rounding)                                          \
2573
    void helper_vrfi##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
2574
    {                                                                   \
2575
        int i;                                                          \
2576
        float_status s = env->vec_status;                               \
2577
        set_float_rounding_mode(rounding, &s);                          \
2578
        for (i = 0; i < ARRAY_SIZE(r->f); i++) {                        \
2579
            HANDLE_NAN1(r->f[i], b->f[i]) {                             \
2580
                r->f[i] = float32_round_to_int (b->f[i], &s);           \
2581
            }                                                           \
2582
        }                                                               \
2583
    }
2584
VRFI(n, float_round_nearest_even)
2585
VRFI(m, float_round_down)
2586
VRFI(p, float_round_up)
2587
VRFI(z, float_round_to_zero)
2588
#undef VRFI
2589

    
2590
#define VROTATE(suffix, element)                                        \
2591
    void helper_vrl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2592
    {                                                                   \
2593
        int i;                                                          \
2594
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2595
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2596
            unsigned int shift = b->element[i] & mask;                  \
2597
            r->element[i] = (a->element[i] << shift) | (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
2598
        }                                                               \
2599
    }
2600
VROTATE(b, u8)
2601
VROTATE(h, u16)
2602
VROTATE(w, u32)
2603
#undef VROTATE
2604

    
2605
void helper_vsel (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2606
{
2607
    r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
2608
    r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
2609
}
2610

    
2611
void helper_vlogefp (ppc_avr_t *r, ppc_avr_t *b)
2612
{
2613
    int i;
2614
    for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2615
        HANDLE_NAN1(r->f[i], b->f[i]) {
2616
            r->f[i] = float32_log2(b->f[i], &env->vec_status);
2617
        }
2618
    }
2619
}
2620

    
2621
#if defined(WORDS_BIGENDIAN)
2622
#define LEFT 0
2623
#define RIGHT 1
2624
#else
2625
#define LEFT 1
2626
#define RIGHT 0
2627
#endif
2628
/* The specification says that the results are undefined if all of the
2629
 * shift counts are not identical.  We check to make sure that they are
2630
 * to conform to what real hardware appears to do.  */
2631
#define VSHIFT(suffix, leftp)                                           \
2632
    void helper_vs##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)   \
2633
    {                                                                   \
2634
        int shift = b->u8[LO_IDX*0x15] & 0x7;                           \
2635
        int doit = 1;                                                   \
2636
        int i;                                                          \
2637
        for (i = 0; i < ARRAY_SIZE(r->u8); i++) {                       \
2638
            doit = doit && ((b->u8[i] & 0x7) == shift);                 \
2639
        }                                                               \
2640
        if (doit) {                                                     \
2641
            if (shift == 0) {                                           \
2642
                *r = *a;                                                \
2643
            } else if (leftp) {                                         \
2644
                uint64_t carry = a->u64[LO_IDX] >> (64 - shift);        \
2645
                r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry;     \
2646
                r->u64[LO_IDX] = a->u64[LO_IDX] << shift;               \
2647
            } else {                                                    \
2648
                uint64_t carry = a->u64[HI_IDX] << (64 - shift);        \
2649
                r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry;     \
2650
                r->u64[HI_IDX] = a->u64[HI_IDX] >> shift;               \
2651
            }                                                           \
2652
        }                                                               \
2653
    }
2654
VSHIFT(l, LEFT)
2655
VSHIFT(r, RIGHT)
2656
#undef VSHIFT
2657
#undef LEFT
2658
#undef RIGHT
2659

    
2660
#define VSL(suffix, element)                                            \
2661
    void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2662
    {                                                                   \
2663
        int i;                                                          \
2664
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2665
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2666
            unsigned int shift = b->element[i] & mask;                  \
2667
            r->element[i] = a->element[i] << shift;                     \
2668
        }                                                               \
2669
    }
2670
VSL(b, u8)
2671
VSL(h, u16)
2672
VSL(w, u32)
2673
#undef VSL
2674

    
2675
void helper_vsldoi (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
2676
{
2677
    int sh = shift & 0xf;
2678
    int i;
2679
    ppc_avr_t result;
2680

    
2681
#if defined(WORDS_BIGENDIAN)
2682
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2683
        int index = sh + i;
2684
        if (index > 0xf) {
2685
            result.u8[i] = b->u8[index-0x10];
2686
        } else {
2687
            result.u8[i] = a->u8[index];
2688
        }
2689
    }
2690
#else
2691
    for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2692
        int index = (16 - sh) + i;
2693
        if (index > 0xf) {
2694
            result.u8[i] = a->u8[index-0x10];
2695
        } else {
2696
            result.u8[i] = b->u8[index];
2697
        }
2698
    }
2699
#endif
2700
    *r = result;
2701
}
2702

    
2703
void helper_vslo (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2704
{
2705
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2706

    
2707
#if defined (WORDS_BIGENDIAN)
2708
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2709
  memset (&r->u8[16-sh], 0, sh);
2710
#else
2711
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2712
  memset (&r->u8[0], 0, sh);
2713
#endif
2714
}
2715

    
2716
/* Experimental testing shows that hardware masks the immediate.  */
2717
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
2718
#if defined(WORDS_BIGENDIAN)
2719
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
2720
#else
2721
#define SPLAT_ELEMENT(element) (ARRAY_SIZE(r->element)-1 - _SPLAT_MASKED(element))
2722
#endif
2723
#define VSPLT(suffix, element)                                          \
2724
    void helper_vsplt##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
2725
    {                                                                   \
2726
        uint32_t s = b->element[SPLAT_ELEMENT(element)];                \
2727
        int i;                                                          \
2728
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2729
            r->element[i] = s;                                          \
2730
        }                                                               \
2731
    }
2732
VSPLT(b, u8)
2733
VSPLT(h, u16)
2734
VSPLT(w, u32)
2735
#undef VSPLT
2736
#undef SPLAT_ELEMENT
2737
#undef _SPLAT_MASKED
2738

    
2739
#define VSPLTI(suffix, element, splat_type)                     \
2740
    void helper_vspltis##suffix (ppc_avr_t *r, uint32_t splat)  \
2741
    {                                                           \
2742
        splat_type x = (int8_t)(splat << 3) >> 3;               \
2743
        int i;                                                  \
2744
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {          \
2745
            r->element[i] = x;                                  \
2746
        }                                                       \
2747
    }
2748
VSPLTI(b, s8, int8_t)
2749
VSPLTI(h, s16, int16_t)
2750
VSPLTI(w, s32, int32_t)
2751
#undef VSPLTI
2752

    
2753
#define VSR(suffix, element)                                            \
2754
    void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)  \
2755
    {                                                                   \
2756
        int i;                                                          \
2757
        for (i = 0; i < ARRAY_SIZE(r->element); i++) {                  \
2758
            unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2759
            unsigned int shift = b->element[i] & mask;                  \
2760
            r->element[i] = a->element[i] >> shift;                     \
2761
        }                                                               \
2762
    }
2763
VSR(ab, s8)
2764
VSR(ah, s16)
2765
VSR(aw, s32)
2766
VSR(b, u8)
2767
VSR(h, u16)
2768
VSR(w, u32)
2769
#undef VSR
2770

    
2771
void helper_vsro (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2772
{
2773
  int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2774

    
2775
#if defined (WORDS_BIGENDIAN)
2776
  memmove (&r->u8[sh], &a->u8[0], 16-sh);
2777
  memset (&r->u8[0], 0, sh);
2778
#else
2779
  memmove (&r->u8[0], &a->u8[sh], 16-sh);
2780
  memset (&r->u8[16-sh], 0, sh);
2781
#endif
2782
}
2783

    
2784
void helper_vsubcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2785
{
2786
    int i;
2787
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2788
        r->u32[i] = a->u32[i] >= b->u32[i];
2789
    }
2790
}
2791

    
2792
void helper_vsumsws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2793
{
2794
    int64_t t;
2795
    int i, upper;
2796
    ppc_avr_t result;
2797
    int sat = 0;
2798

    
2799
#if defined(WORDS_BIGENDIAN)
2800
    upper = ARRAY_SIZE(r->s32)-1;
2801
#else
2802
    upper = 0;
2803
#endif
2804
    t = (int64_t)b->s32[upper];
2805
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2806
        t += a->s32[i];
2807
        result.s32[i] = 0;
2808
    }
2809
    result.s32[upper] = cvtsdsw(t, &sat);
2810
    *r = result;
2811

    
2812
    if (sat) {
2813
        env->vscr |= (1 << VSCR_SAT);
2814
    }
2815
}
2816

    
2817
void helper_vsum2sws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2818
{
2819
    int i, j, upper;
2820
    ppc_avr_t result;
2821
    int sat = 0;
2822

    
2823
#if defined(WORDS_BIGENDIAN)
2824
    upper = 1;
2825
#else
2826
    upper = 0;
2827
#endif
2828
    for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
2829
        int64_t t = (int64_t)b->s32[upper+i*2];
2830
        result.u64[i] = 0;
2831
        for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
2832
            t += a->s32[2*i+j];
2833
        }
2834
        result.s32[upper+i*2] = cvtsdsw(t, &sat);
2835
    }
2836

    
2837
    *r = result;
2838
    if (sat) {
2839
        env->vscr |= (1 << VSCR_SAT);
2840
    }
2841
}
2842

    
2843
void helper_vsum4sbs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2844
{
2845
    int i, j;
2846
    int sat = 0;
2847

    
2848
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2849
        int64_t t = (int64_t)b->s32[i];
2850
        for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
2851
            t += a->s8[4*i+j];
2852
        }
2853
        r->s32[i] = cvtsdsw(t, &sat);
2854
    }
2855

    
2856
    if (sat) {
2857
        env->vscr |= (1 << VSCR_SAT);
2858
    }
2859
}
2860

    
2861
void helper_vsum4shs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2862
{
2863
    int sat = 0;
2864
    int i;
2865

    
2866
    for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2867
        int64_t t = (int64_t)b->s32[i];
2868
        t += a->s16[2*i] + a->s16[2*i+1];
2869
        r->s32[i] = cvtsdsw(t, &sat);
2870
    }
2871

    
2872
    if (sat) {
2873
        env->vscr |= (1 << VSCR_SAT);
2874
    }
2875
}
2876

    
2877
void helper_vsum4ubs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2878
{
2879
    int i, j;
2880
    int sat = 0;
2881

    
2882
    for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2883
        uint64_t t = (uint64_t)b->u32[i];
2884
        for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
2885
            t += a->u8[4*i+j];
2886
        }
2887
        r->u32[i] = cvtuduw(t, &sat);
2888
    }
2889

    
2890
    if (sat) {
2891
        env->vscr |= (1 << VSCR_SAT);
2892
    }
2893
}
2894

    
2895
#if defined(WORDS_BIGENDIAN)
2896
#define UPKHI 1
2897
#define UPKLO 0
2898
#else
2899
#define UPKHI 0
2900
#define UPKLO 1
2901
#endif
2902
#define VUPKPX(suffix, hi)                                      \
2903
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)       \
2904
    {                                                           \
2905
        int i;                                                  \
2906
        ppc_avr_t result;                                       \
2907
        for (i = 0; i < ARRAY_SIZE(r->u32); i++) {              \
2908
            uint16_t e = b->u16[hi ? i : i+4];                  \
2909
            uint8_t a = (e >> 15) ? 0xff : 0;                   \
2910
            uint8_t r = (e >> 10) & 0x1f;                       \
2911
            uint8_t g = (e >> 5) & 0x1f;                        \
2912
            uint8_t b = e & 0x1f;                               \
2913
            result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b;       \
2914
        }                                                               \
2915
        *r = result;                                                    \
2916
    }
2917
VUPKPX(lpx, UPKLO)
2918
VUPKPX(hpx, UPKHI)
2919
#undef VUPKPX
2920

    
2921
#define VUPK(suffix, unpacked, packee, hi)                              \
2922
    void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b)               \
2923
    {                                                                   \
2924
        int i;                                                          \
2925
        ppc_avr_t result;                                               \
2926
        if (hi) {                                                       \
2927
            for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) {             \
2928
                result.unpacked[i] = b->packee[i];                      \
2929
            }                                                           \
2930
        } else {                                                        \
2931
            for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); i++) { \
2932
                result.unpacked[i-ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
2933
            }                                                           \
2934
        }                                                               \
2935
        *r = result;                                                    \
2936
    }
2937
VUPK(hsb, s16, s8, UPKHI)
2938
VUPK(hsh, s32, s16, UPKHI)
2939
VUPK(lsb, s16, s8, UPKLO)
2940
VUPK(lsh, s32, s16, UPKLO)
2941
#undef VUPK
2942
#undef UPKHI
2943
#undef UPKLO
2944

    
2945
#undef DO_HANDLE_NAN
2946
#undef HANDLE_NAN1
2947
#undef HANDLE_NAN2
2948
#undef HANDLE_NAN3
2949
#undef VECTOR_FOR_INORDER_I
2950
#undef HI_IDX
2951
#undef LO_IDX
2952

    
2953
/*****************************************************************************/
2954
/* SPE extension helpers */
2955
/* Use a table to make this quicker */
2956
static uint8_t hbrev[16] = {
2957
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
2958
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
2959
};
2960

    
2961
static always_inline uint8_t byte_reverse (uint8_t val)
2962
{
2963
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
2964
}
2965

    
2966
static always_inline uint32_t word_reverse (uint32_t val)
2967
{
2968
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
2969
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
2970
}
2971

    
2972
#define MASKBITS 16 // Random value - to be fixed (implementation dependant)
2973
target_ulong helper_brinc (target_ulong arg1, target_ulong arg2)
2974
{
2975
    uint32_t a, b, d, mask;
2976

    
2977
    mask = UINT32_MAX >> (32 - MASKBITS);
2978
    a = arg1 & mask;
2979
    b = arg2 & mask;
2980
    d = word_reverse(1 + word_reverse(a | ~b));
2981
    return (arg1 & ~mask) | (d & b);
2982
}
2983

    
2984
uint32_t helper_cntlsw32 (uint32_t val)
2985
{
2986
    if (val & 0x80000000)
2987
        return clz32(~val);
2988
    else
2989
        return clz32(val);
2990
}
2991

    
2992
uint32_t helper_cntlzw32 (uint32_t val)
2993
{
2994
    return clz32(val);
2995
}
2996

    
2997
/* Single-precision floating-point conversions */
2998
static always_inline uint32_t efscfsi (uint32_t val)
2999
{
3000
    CPU_FloatU u;
3001

    
3002
    u.f = int32_to_float32(val, &env->vec_status);
3003

    
3004
    return u.l;
3005
}
3006

    
3007
static always_inline uint32_t efscfui (uint32_t val)
3008
{
3009
    CPU_FloatU u;
3010

    
3011
    u.f = uint32_to_float32(val, &env->vec_status);
3012

    
3013
    return u.l;
3014
}
3015

    
3016
static always_inline int32_t efsctsi (uint32_t val)
3017
{
3018
    CPU_FloatU u;
3019

    
3020
    u.l = val;
3021
    /* NaN are not treated the same way IEEE 754 does */
3022
    if (unlikely(float32_is_nan(u.f)))
3023
        return 0;
3024

    
3025
    return float32_to_int32(u.f, &env->vec_status);
3026
}
3027

    
3028
static always_inline uint32_t efsctui (uint32_t val)
3029
{
3030
    CPU_FloatU u;
3031

    
3032
    u.l = val;
3033
    /* NaN are not treated the same way IEEE 754 does */
3034
    if (unlikely(float32_is_nan(u.f)))
3035
        return 0;
3036

    
3037
    return float32_to_uint32(u.f, &env->vec_status);
3038
}
3039

    
3040
static always_inline uint32_t efsctsiz (uint32_t val)
3041
{
3042
    CPU_FloatU u;
3043

    
3044
    u.l = val;
3045
    /* NaN are not treated the same way IEEE 754 does */
3046
    if (unlikely(float32_is_nan(u.f)))
3047
        return 0;
3048

    
3049
    return float32_to_int32_round_to_zero(u.f, &env->vec_status);
3050
}
3051

    
3052
static always_inline uint32_t efsctuiz (uint32_t val)
3053
{
3054
    CPU_FloatU u;
3055

    
3056
    u.l = val;
3057
    /* NaN are not treated the same way IEEE 754 does */
3058
    if (unlikely(float32_is_nan(u.f)))
3059
        return 0;
3060

    
3061
    return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
3062
}
3063

    
3064
static always_inline uint32_t efscfsf (uint32_t val)
3065
{
3066
    CPU_FloatU u;
3067
    float32 tmp;
3068

    
3069
    u.f = int32_to_float32(val, &env->vec_status);
3070
    tmp = int64_to_float32(1ULL << 32, &env->vec_status);
3071
    u.f = float32_div(u.f, tmp, &env->vec_status);
3072

    
3073
    return u.l;
3074
}
3075

    
3076
static always_inline uint32_t efscfuf (uint32_t val)
3077
{
3078
    CPU_FloatU u;
3079
    float32 tmp;
3080

    
3081
    u.f = uint32_to_float32(val, &env->vec_status);
3082
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3083
    u.f = float32_div(u.f, tmp, &env->vec_status);
3084

    
3085
    return u.l;
3086
}
3087

    
3088
static always_inline uint32_t efsctsf (uint32_t val)
3089
{
3090
    CPU_FloatU u;
3091
    float32 tmp;
3092

    
3093
    u.l = val;
3094
    /* NaN are not treated the same way IEEE 754 does */
3095
    if (unlikely(float32_is_nan(u.f)))
3096
        return 0;
3097
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3098
    u.f = float32_mul(u.f, tmp, &env->vec_status);
3099

    
3100
    return float32_to_int32(u.f, &env->vec_status);
3101
}
3102

    
3103
static always_inline uint32_t efsctuf (uint32_t val)
3104
{
3105
    CPU_FloatU u;
3106
    float32 tmp;
3107

    
3108
    u.l = val;
3109
    /* NaN are not treated the same way IEEE 754 does */
3110
    if (unlikely(float32_is_nan(u.f)))
3111
        return 0;
3112
    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3113
    u.f = float32_mul(u.f, tmp, &env->vec_status);
3114

    
3115
    return float32_to_uint32(u.f, &env->vec_status);
3116
}
3117

    
3118
#define HELPER_SPE_SINGLE_CONV(name)                                          \
3119
uint32_t helper_e##name (uint32_t val)                                        \
3120
{                                                                             \
3121
    return e##name(val);                                                      \
3122
}
3123
/* efscfsi */
3124
HELPER_SPE_SINGLE_CONV(fscfsi);
3125
/* efscfui */
3126
HELPER_SPE_SINGLE_CONV(fscfui);
3127
/* efscfuf */
3128
HELPER_SPE_SINGLE_CONV(fscfuf);
3129
/* efscfsf */
3130
HELPER_SPE_SINGLE_CONV(fscfsf);
3131
/* efsctsi */
3132
HELPER_SPE_SINGLE_CONV(fsctsi);
3133
/* efsctui */
3134
HELPER_SPE_SINGLE_CONV(fsctui);
3135
/* efsctsiz */
3136
HELPER_SPE_SINGLE_CONV(fsctsiz);
3137
/* efsctuiz */
3138
HELPER_SPE_SINGLE_CONV(fsctuiz);
3139
/* efsctsf */
3140
HELPER_SPE_SINGLE_CONV(fsctsf);
3141
/* efsctuf */
3142
HELPER_SPE_SINGLE_CONV(fsctuf);
3143

    
3144
#define HELPER_SPE_VECTOR_CONV(name)                                          \
3145
uint64_t helper_ev##name (uint64_t val)                                       \
3146
{                                                                             \
3147
    return ((uint64_t)e##name(val >> 32) << 32) |                             \
3148
            (uint64_t)e##name(val);                                           \
3149
}
3150
/* evfscfsi */
3151
HELPER_SPE_VECTOR_CONV(fscfsi);
3152
/* evfscfui */
3153
HELPER_SPE_VECTOR_CONV(fscfui);
3154
/* evfscfuf */
3155
HELPER_SPE_VECTOR_CONV(fscfuf);
3156
/* evfscfsf */
3157
HELPER_SPE_VECTOR_CONV(fscfsf);
3158
/* evfsctsi */
3159
HELPER_SPE_VECTOR_CONV(fsctsi);
3160
/* evfsctui */
3161
HELPER_SPE_VECTOR_CONV(fsctui);
3162
/* evfsctsiz */
3163
HELPER_SPE_VECTOR_CONV(fsctsiz);
3164
/* evfsctuiz */
3165
HELPER_SPE_VECTOR_CONV(fsctuiz);
3166
/* evfsctsf */
3167
HELPER_SPE_VECTOR_CONV(fsctsf);
3168
/* evfsctuf */
3169
HELPER_SPE_VECTOR_CONV(fsctuf);
3170

    
3171
/* Single-precision floating-point arithmetic */
3172
static always_inline uint32_t efsadd (uint32_t op1, uint32_t op2)
3173
{
3174
    CPU_FloatU u1, u2;
3175
    u1.l = op1;
3176
    u2.l = op2;
3177
    u1.f = float32_add(u1.f, u2.f, &env->vec_status);
3178
    return u1.l;
3179
}
3180

    
3181
static always_inline uint32_t efssub (uint32_t op1, uint32_t op2)
3182
{
3183
    CPU_FloatU u1, u2;
3184
    u1.l = op1;
3185
    u2.l = op2;
3186
    u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
3187
    return u1.l;
3188
}
3189

    
3190
static always_inline uint32_t efsmul (uint32_t op1, uint32_t op2)
3191
{
3192
    CPU_FloatU u1, u2;
3193
    u1.l = op1;
3194
    u2.l = op2;
3195
    u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
3196
    return u1.l;
3197
}
3198

    
3199
static always_inline uint32_t efsdiv (uint32_t op1, uint32_t op2)
3200
{
3201
    CPU_FloatU u1, u2;
3202
    u1.l = op1;
3203
    u2.l = op2;
3204
    u1.f = float32_div(u1.f, u2.f, &env->vec_status);
3205
    return u1.l;
3206
}
3207

    
3208
#define HELPER_SPE_SINGLE_ARITH(name)                                         \
3209
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3210
{                                                                             \
3211
    return e##name(op1, op2);                                                 \
3212
}
3213
/* efsadd */
3214
HELPER_SPE_SINGLE_ARITH(fsadd);
3215
/* efssub */
3216
HELPER_SPE_SINGLE_ARITH(fssub);
3217
/* efsmul */
3218
HELPER_SPE_SINGLE_ARITH(fsmul);
3219
/* efsdiv */
3220
HELPER_SPE_SINGLE_ARITH(fsdiv);
3221

    
3222
#define HELPER_SPE_VECTOR_ARITH(name)                                         \
3223
uint64_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3224
{                                                                             \
3225
    return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) |                  \
3226
            (uint64_t)e##name(op1, op2);                                      \
3227
}
3228
/* evfsadd */
3229
HELPER_SPE_VECTOR_ARITH(fsadd);
3230
/* evfssub */
3231
HELPER_SPE_VECTOR_ARITH(fssub);
3232
/* evfsmul */
3233
HELPER_SPE_VECTOR_ARITH(fsmul);
3234
/* evfsdiv */
3235
HELPER_SPE_VECTOR_ARITH(fsdiv);
3236

    
3237
/* Single-precision floating-point comparisons */
3238
static always_inline uint32_t efststlt (uint32_t op1, uint32_t op2)
3239
{
3240
    CPU_FloatU u1, u2;
3241
    u1.l = op1;
3242
    u2.l = op2;
3243
    return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3244
}
3245

    
3246
static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
3247
{
3248
    CPU_FloatU u1, u2;
3249
    u1.l = op1;
3250
    u2.l = op2;
3251
    return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
3252
}
3253

    
3254
static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
3255
{
3256
    CPU_FloatU u1, u2;
3257
    u1.l = op1;
3258
    u2.l = op2;
3259
    return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3260
}
3261

    
3262
static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
3263
{
3264
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3265
    return efststlt(op1, op2);
3266
}
3267

    
3268
static always_inline uint32_t efscmpgt (uint32_t op1, uint32_t op2)
3269
{
3270
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3271
    return efststgt(op1, op2);
3272
}
3273

    
3274
static always_inline uint32_t efscmpeq (uint32_t op1, uint32_t op2)
3275
{
3276
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3277
    return efststeq(op1, op2);
3278
}
3279

    
3280
#define HELPER_SINGLE_SPE_CMP(name)                                           \
3281
uint32_t helper_e##name (uint32_t op1, uint32_t op2)                          \
3282
{                                                                             \
3283
    return e##name(op1, op2) << 2;                                            \
3284
}
3285
/* efststlt */
3286
HELPER_SINGLE_SPE_CMP(fststlt);
3287
/* efststgt */
3288
HELPER_SINGLE_SPE_CMP(fststgt);
3289
/* efststeq */
3290
HELPER_SINGLE_SPE_CMP(fststeq);
3291
/* efscmplt */
3292
HELPER_SINGLE_SPE_CMP(fscmplt);
3293
/* efscmpgt */
3294
HELPER_SINGLE_SPE_CMP(fscmpgt);
3295
/* efscmpeq */
3296
HELPER_SINGLE_SPE_CMP(fscmpeq);
3297

    
3298
static always_inline uint32_t evcmp_merge (int t0, int t1)
3299
{
3300
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
3301
}
3302

    
3303
#define HELPER_VECTOR_SPE_CMP(name)                                           \
3304
uint32_t helper_ev##name (uint64_t op1, uint64_t op2)                         \
3305
{                                                                             \
3306
    return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2));     \
3307
}
3308
/* evfststlt */
3309
HELPER_VECTOR_SPE_CMP(fststlt);
3310
/* evfststgt */
3311
HELPER_VECTOR_SPE_CMP(fststgt);
3312
/* evfststeq */
3313
HELPER_VECTOR_SPE_CMP(fststeq);
3314
/* evfscmplt */
3315
HELPER_VECTOR_SPE_CMP(fscmplt);
3316
/* evfscmpgt */
3317
HELPER_VECTOR_SPE_CMP(fscmpgt);
3318
/* evfscmpeq */
3319
HELPER_VECTOR_SPE_CMP(fscmpeq);
3320

    
3321
/* Double-precision floating-point conversion */
3322
uint64_t helper_efdcfsi (uint32_t val)
3323
{
3324
    CPU_DoubleU u;
3325

    
3326
    u.d = int32_to_float64(val, &env->vec_status);
3327

    
3328
    return u.ll;
3329
}
3330

    
3331
uint64_t helper_efdcfsid (uint64_t val)
3332
{
3333
    CPU_DoubleU u;
3334

    
3335
    u.d = int64_to_float64(val, &env->vec_status);
3336

    
3337
    return u.ll;
3338
}
3339

    
3340
uint64_t helper_efdcfui (uint32_t val)
3341
{
3342
    CPU_DoubleU u;
3343

    
3344
    u.d = uint32_to_float64(val, &env->vec_status);
3345

    
3346
    return u.ll;
3347
}
3348

    
3349
uint64_t helper_efdcfuid (uint64_t val)
3350
{
3351
    CPU_DoubleU u;
3352

    
3353
    u.d = uint64_to_float64(val, &env->vec_status);
3354

    
3355
    return u.ll;
3356
}
3357

    
3358
uint32_t helper_efdctsi (uint64_t val)
3359
{
3360
    CPU_DoubleU u;
3361

    
3362
    u.ll = val;
3363
    /* NaN are not treated the same way IEEE 754 does */
3364
    if (unlikely(float64_is_nan(u.d)))
3365
        return 0;
3366

    
3367
    return float64_to_int32(u.d, &env->vec_status);
3368
}
3369

    
3370
uint32_t helper_efdctui (uint64_t val)
3371
{
3372
    CPU_DoubleU u;
3373

    
3374
    u.ll = val;
3375
    /* NaN are not treated the same way IEEE 754 does */
3376
    if (unlikely(float64_is_nan(u.d)))
3377
        return 0;
3378

    
3379
    return float64_to_uint32(u.d, &env->vec_status);
3380
}
3381

    
3382
uint32_t helper_efdctsiz (uint64_t val)
3383
{
3384
    CPU_DoubleU u;
3385

    
3386
    u.ll = val;
3387
    /* NaN are not treated the same way IEEE 754 does */
3388
    if (unlikely(float64_is_nan(u.d)))
3389
        return 0;
3390

    
3391
    return float64_to_int32_round_to_zero(u.d, &env->vec_status);
3392
}
3393

    
3394
uint64_t helper_efdctsidz (uint64_t val)
3395
{
3396
    CPU_DoubleU u;
3397

    
3398
    u.ll = val;
3399
    /* NaN are not treated the same way IEEE 754 does */
3400
    if (unlikely(float64_is_nan(u.d)))
3401
        return 0;
3402

    
3403
    return float64_to_int64_round_to_zero(u.d, &env->vec_status);
3404
}
3405

    
3406
uint32_t helper_efdctuiz (uint64_t val)
3407
{
3408
    CPU_DoubleU u;
3409

    
3410
    u.ll = val;
3411
    /* NaN are not treated the same way IEEE 754 does */
3412
    if (unlikely(float64_is_nan(u.d)))
3413
        return 0;
3414

    
3415
    return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
3416
}
3417

    
3418
uint64_t helper_efdctuidz (uint64_t val)
3419
{
3420
    CPU_DoubleU u;
3421

    
3422
    u.ll = val;
3423
    /* NaN are not treated the same way IEEE 754 does */
3424
    if (unlikely(float64_is_nan(u.d)))
3425
        return 0;
3426

    
3427
    return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
3428
}
3429

    
3430
uint64_t helper_efdcfsf (uint32_t val)
3431
{
3432
    CPU_DoubleU u;
3433
    float64 tmp;
3434

    
3435
    u.d = int32_to_float64(val, &env->vec_status);
3436
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3437
    u.d = float64_div(u.d, tmp, &env->vec_status);
3438

    
3439
    return u.ll;
3440
}
3441

    
3442
uint64_t helper_efdcfuf (uint32_t val)
3443
{
3444
    CPU_DoubleU u;
3445
    float64 tmp;
3446

    
3447
    u.d = uint32_to_float64(val, &env->vec_status);
3448
    tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3449
    u.d = float64_div(u.d, tmp, &env->vec_status);
3450

    
3451
    return u.ll;
3452
}
3453

    
3454
uint32_t helper_efdctsf (uint64_t val)
3455
{
3456
    CPU_DoubleU u;
3457
    float64 tmp;
3458

    
3459
    u.ll = val;
3460
    /* NaN are not treated the same way IEEE 754 does */
3461
    if (unlikely(float64_is_nan(u.d)))
3462
        return 0;
3463
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3464
    u.d = float64_mul(u.d, tmp, &env->vec_status);
3465

    
3466
    return float64_to_int32(u.d, &env->vec_status);
3467
}
3468

    
3469
uint32_t helper_efdctuf (uint64_t val)
3470
{
3471
    CPU_DoubleU u;
3472
    float64 tmp;
3473

    
3474
    u.ll = val;
3475
    /* NaN are not treated the same way IEEE 754 does */
3476
    if (unlikely(float64_is_nan(u.d)))
3477
        return 0;
3478
    tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3479
    u.d = float64_mul(u.d, tmp, &env->vec_status);
3480

    
3481
    return float64_to_uint32(u.d, &env->vec_status);
3482
}
3483

    
3484
uint32_t helper_efscfd (uint64_t val)
3485
{
3486
    CPU_DoubleU u1;
3487
    CPU_FloatU u2;
3488

    
3489
    u1.ll = val;
3490
    u2.f = float64_to_float32(u1.d, &env->vec_status);
3491

    
3492
    return u2.l;
3493
}
3494

    
3495
uint64_t helper_efdcfs (uint32_t val)
3496
{
3497
    CPU_DoubleU u2;
3498
    CPU_FloatU u1;
3499

    
3500
    u1.l = val;
3501
    u2.d = float32_to_float64(u1.f, &env->vec_status);
3502

    
3503
    return u2.ll;
3504
}
3505

    
3506
/* Double precision fixed-point arithmetic */
3507
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
3508
{
3509
    CPU_DoubleU u1, u2;
3510
    u1.ll = op1;
3511
    u2.ll = op2;
3512
    u1.d = float64_add(u1.d, u2.d, &env->vec_status);
3513
    return u1.ll;
3514
}
3515

    
3516
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
3517
{
3518
    CPU_DoubleU u1, u2;
3519
    u1.ll = op1;
3520
    u2.ll = op2;
3521
    u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
3522
    return u1.ll;
3523
}
3524

    
3525
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
3526
{
3527
    CPU_DoubleU u1, u2;
3528
    u1.ll = op1;
3529
    u2.ll = op2;
3530
    u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
3531
    return u1.ll;
3532
}
3533

    
3534
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
3535
{
3536
    CPU_DoubleU u1, u2;
3537
    u1.ll = op1;
3538
    u2.ll = op2;
3539
    u1.d = float64_div(u1.d, u2.d, &env->vec_status);
3540
    return u1.ll;
3541
}
3542

    
3543
/* Double precision floating point helpers */
3544
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
3545
{
3546
    CPU_DoubleU u1, u2;
3547
    u1.ll = op1;
3548
    u2.ll = op2;
3549
    return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3550
}
3551

    
3552
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
3553
{
3554
    CPU_DoubleU u1, u2;
3555
    u1.ll = op1;
3556
    u2.ll = op2;
3557
    return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
3558
}
3559

    
3560
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
3561
{
3562
    CPU_DoubleU u1, u2;
3563
    u1.ll = op1;
3564
    u2.ll = op2;
3565
    return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3566
}
3567

    
3568
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
3569
{
3570
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3571
    return helper_efdtstlt(op1, op2);
3572
}
3573

    
3574
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
3575
{
3576
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3577
    return helper_efdtstgt(op1, op2);
3578
}
3579

    
3580
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
3581
{
3582
    /* XXX: TODO: test special values (NaN, infinites, ...) */
3583
    return helper_efdtsteq(op1, op2);
3584
}
3585

    
3586
/*****************************************************************************/
3587
/* Softmmu support */
3588
#if !defined (CONFIG_USER_ONLY)
3589

    
3590
#define MMUSUFFIX _mmu
3591

    
3592
#define SHIFT 0
3593
#include "softmmu_template.h"
3594

    
3595
#define SHIFT 1
3596
#include "softmmu_template.h"
3597

    
3598
#define SHIFT 2
3599
#include "softmmu_template.h"
3600

    
3601
#define SHIFT 3
3602
#include "softmmu_template.h"
3603

    
3604
/* try to fill the TLB and return an exception if error. If retaddr is
3605
   NULL, it means that the function was called in C code (i.e. not
3606
   from generated code or from helper.c) */
3607
/* XXX: fix it to restore all registers */
3608
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3609
{
3610
    TranslationBlock *tb;
3611
    CPUState *saved_env;
3612
    unsigned long pc;
3613
    int ret;
3614

    
3615
    /* XXX: hack to restore env in all cases, even if not called from
3616
       generated code */
3617
    saved_env = env;
3618
    env = cpu_single_env;
3619
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3620
    if (unlikely(ret != 0)) {
3621
        if (likely(retaddr)) {
3622
            /* now we have a real cpu fault */
3623
            pc = (unsigned long)retaddr;
3624
            tb = tb_find_pc(pc);
3625
            if (likely(tb)) {
3626
                /* the PC is inside the translated code. It means that we have
3627
                   a virtual CPU fault */
3628
                cpu_restore_state(tb, env, pc, NULL);
3629
            }
3630
        }
3631
        helper_raise_exception_err(env->exception_index, env->error_code);
3632
    }
3633
    env = saved_env;
3634
}
3635

    
3636
/* Segment registers load and store */
3637
target_ulong helper_load_sr (target_ulong sr_num)
3638
{
3639
    return env->sr[sr_num];
3640
}
3641

    
3642
void helper_store_sr (target_ulong sr_num, target_ulong val)
3643
{
3644
    ppc_store_sr(env, sr_num, val);
3645
}
3646

    
3647
/* SLB management */
3648
#if defined(TARGET_PPC64)
3649
target_ulong helper_load_slb (target_ulong slb_nr)
3650
{
3651
    return ppc_load_slb(env, slb_nr);
3652
}
3653

    
3654
void helper_store_slb (target_ulong slb_nr, target_ulong rs)
3655
{
3656
    ppc_store_slb(env, slb_nr, rs);
3657
}
3658

    
3659
void helper_slbia (void)
3660
{
3661
    ppc_slb_invalidate_all(env);
3662
}
3663

    
3664
void helper_slbie (target_ulong addr)
3665
{
3666
    ppc_slb_invalidate_one(env, addr);
3667
}
3668

    
3669
#endif /* defined(TARGET_PPC64) */
3670

    
3671
/* TLB management */
3672
void helper_tlbia (void)
3673
{
3674
    ppc_tlb_invalidate_all(env);
3675
}
3676

    
3677
void helper_tlbie (target_ulong addr)
3678
{
3679
    ppc_tlb_invalidate_one(env, addr);
3680
}
3681

    
3682
/* Software driven TLBs management */
3683
/* PowerPC 602/603 software TLB load instructions helpers */
3684
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
3685
{
3686
    target_ulong RPN, CMP, EPN;
3687
    int way;
3688

    
3689
    RPN = env->spr[SPR_RPA];
3690
    if (is_code) {
3691
        CMP = env->spr[SPR_ICMP];
3692
        EPN = env->spr[SPR_IMISS];
3693
    } else {
3694
        CMP = env->spr[SPR_DCMP];
3695
        EPN = env->spr[SPR_DMISS];
3696
    }
3697
    way = (env->spr[SPR_SRR1] >> 17) & 1;
3698
    LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3699
                " PTE1 " ADDRX " way %d\n",
3700
                __func__, new_EPN, EPN, CMP, RPN, way);
3701
    /* Store this TLB */
3702
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3703
                     way, is_code, CMP, RPN);
3704
}
3705

    
3706
void helper_6xx_tlbd (target_ulong EPN)
3707
{
3708
    do_6xx_tlb(EPN, 0);
3709
}
3710

    
3711
void helper_6xx_tlbi (target_ulong EPN)
3712
{
3713
    do_6xx_tlb(EPN, 1);
3714
}
3715

    
3716
/* PowerPC 74xx software TLB load instructions helpers */
3717
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
3718
{
3719
    target_ulong RPN, CMP, EPN;
3720
    int way;
3721

    
3722
    RPN = env->spr[SPR_PTELO];
3723
    CMP = env->spr[SPR_PTEHI];
3724
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
3725
    way = env->spr[SPR_TLBMISS] & 0x3;
3726
    LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
3727
                " PTE1 " ADDRX " way %d\n",
3728
                __func__, new_EPN, EPN, CMP, RPN, way);
3729
    /* Store this TLB */
3730
    ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
3731
                     way, is_code, CMP, RPN);
3732
}
3733

    
3734
void helper_74xx_tlbd (target_ulong EPN)
3735
{
3736
    do_74xx_tlb(EPN, 0);
3737
}
3738

    
3739
void helper_74xx_tlbi (target_ulong EPN)
3740
{
3741
    do_74xx_tlb(EPN, 1);
3742
}
3743

    
3744
static always_inline target_ulong booke_tlb_to_page_size (int size)
3745
{
3746
    return 1024 << (2 * size);
3747
}
3748

    
3749
static always_inline int booke_page_size_to_tlb (target_ulong page_size)
3750
{
3751
    int size;
3752

    
3753
    switch (page_size) {
3754
    case 0x00000400UL:
3755
        size = 0x0;
3756
        break;
3757
    case 0x00001000UL:
3758
        size = 0x1;
3759
        break;
3760
    case 0x00004000UL:
3761
        size = 0x2;
3762
        break;
3763
    case 0x00010000UL:
3764
        size = 0x3;
3765
        break;
3766
    case 0x00040000UL:
3767
        size = 0x4;
3768
        break;
3769
    case 0x00100000UL:
3770
        size = 0x5;
3771
        break;
3772
    case 0x00400000UL:
3773
        size = 0x6;
3774
        break;
3775
    case 0x01000000UL:
3776
        size = 0x7;
3777
        break;
3778
    case 0x04000000UL:
3779
        size = 0x8;
3780
        break;
3781
    case 0x10000000UL:
3782
        size = 0x9;
3783
        break;
3784
    case 0x40000000UL:
3785
        size = 0xA;
3786
        break;
3787
#if defined (TARGET_PPC64)
3788
    case 0x000100000000ULL:
3789
        size = 0xB;
3790
        break;
3791
    case 0x000400000000ULL:
3792
        size = 0xC;
3793
        break;
3794
    case 0x001000000000ULL:
3795
        size = 0xD;
3796
        break;
3797
    case 0x004000000000ULL:
3798
        size = 0xE;
3799
        break;
3800
    case 0x010000000000ULL:
3801
        size = 0xF;
3802
        break;
3803
#endif
3804
    default:
3805
        size = -1;
3806
        break;
3807
    }
3808

    
3809
    return size;
3810
}
3811

    
3812
/* Helpers for 4xx TLB management */
3813
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
3814
{
3815
    ppcemb_tlb_t *tlb;
3816
    target_ulong ret;
3817
    int size;
3818

    
3819
    entry &= 0x3F;
3820
    tlb = &env->tlb[entry].tlbe;
3821
    ret = tlb->EPN;
3822
    if (tlb->prot & PAGE_VALID)
3823
        ret |= 0x400;
3824
    size = booke_page_size_to_tlb(tlb->size);
3825
    if (size < 0 || size > 0x7)
3826
        size = 1;
3827
    ret |= size << 7;
3828
    env->spr[SPR_40x_PID] = tlb->PID;
3829
    return ret;
3830
}
3831

    
3832
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
3833
{
3834
    ppcemb_tlb_t *tlb;
3835
    target_ulong ret;
3836

    
3837
    entry &= 0x3F;
3838
    tlb = &env->tlb[entry].tlbe;
3839
    ret = tlb->RPN;
3840
    if (tlb->prot & PAGE_EXEC)
3841
        ret |= 0x200;
3842
    if (tlb->prot & PAGE_WRITE)
3843
        ret |= 0x100;
3844
    return ret;
3845
}
3846

    
3847
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
3848
{
3849
    ppcemb_tlb_t *tlb;
3850
    target_ulong page, end;
3851

    
3852
    LOG_SWTLB("%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
3853
    entry &= 0x3F;
3854
    tlb = &env->tlb[entry].tlbe;
3855
    /* Invalidate previous TLB (if it's valid) */
3856
    if (tlb->prot & PAGE_VALID) {
3857
        end = tlb->EPN + tlb->size;
3858
        LOG_SWTLB("%s: invalidate old TLB %d start " ADDRX
3859
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3860
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3861
            tlb_flush_page(env, page);
3862
    }
3863
    tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
3864
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
3865
     * If this ever occurs, one should use the ppcemb target instead
3866
     * of the ppc or ppc64 one
3867
     */
3868
    if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
3869
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
3870
                  "are not supported (%d)\n",
3871
                  tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
3872
    }
3873
    tlb->EPN = val & ~(tlb->size - 1);
3874
    if (val & 0x40)
3875
        tlb->prot |= PAGE_VALID;
3876
    else
3877
        tlb->prot &= ~PAGE_VALID;
3878
    if (val & 0x20) {
3879
        /* XXX: TO BE FIXED */
3880
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
3881
    }
3882
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
3883
    tlb->attr = val & 0xFF;
3884
    LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3885
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3886
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3887
                tlb->prot & PAGE_READ ? 'r' : '-',
3888
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3889
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3890
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3891
    /* Invalidate new TLB (if valid) */
3892
    if (tlb->prot & PAGE_VALID) {
3893
        end = tlb->EPN + tlb->size;
3894
        LOG_SWTLB("%s: invalidate TLB %d start " ADDRX
3895
                    " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
3896
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
3897
            tlb_flush_page(env, page);
3898
    }
3899
}
3900

    
3901
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
3902
{
3903
    ppcemb_tlb_t *tlb;
3904

    
3905
    LOG_SWTLB("%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
3906
    entry &= 0x3F;
3907
    tlb = &env->tlb[entry].tlbe;
3908
    tlb->RPN = val & 0xFFFFFC00;
3909
    tlb->prot = PAGE_READ;
3910
    if (val & 0x200)
3911
        tlb->prot |= PAGE_EXEC;
3912
    if (val & 0x100)
3913
        tlb->prot |= PAGE_WRITE;
3914
    LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
3915
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
3916
                (int)entry, tlb->RPN, tlb->EPN, tlb->size,
3917
                tlb->prot & PAGE_READ ? 'r' : '-',
3918
                tlb->prot & PAGE_WRITE ? 'w' : '-',
3919
                tlb->prot & PAGE_EXEC ? 'x' : '-',
3920
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3921
}
3922

    
3923
target_ulong helper_4xx_tlbsx (target_ulong address)
3924
{
3925
    return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
3926
}
3927

    
3928
/* PowerPC 440 TLB management */
3929
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
3930
{
3931
    ppcemb_tlb_t *tlb;
3932
    target_ulong EPN, RPN, size;
3933
    int do_flush_tlbs;
3934

    
3935
    LOG_SWTLB("%s word %d entry %d value " ADDRX "\n",
3936
                __func__, word, (int)entry, value);
3937
    do_flush_tlbs = 0;
3938
    entry &= 0x3F;
3939
    tlb = &env->tlb[entry].tlbe;
3940
    switch (word) {
3941
    default:
3942
        /* Just here to please gcc */
3943
    case 0:
3944
        EPN = value & 0xFFFFFC00;
3945
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
3946
            do_flush_tlbs = 1;
3947
        tlb->EPN = EPN;
3948
        size = booke_tlb_to_page_size((value >> 4) & 0xF);
3949
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
3950
            do_flush_tlbs = 1;
3951
        tlb->size = size;
3952
        tlb->attr &= ~0x1;
3953
        tlb->attr |= (value >> 8) & 1;
3954
        if (value & 0x200) {
3955
            tlb->prot |= PAGE_VALID;
3956
        } else {
3957
            if (tlb->prot & PAGE_VALID) {
3958
                tlb->prot &= ~PAGE_VALID;
3959
                do_flush_tlbs = 1;
3960
            }
3961
        }
3962
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
3963
        if (do_flush_tlbs)
3964
            tlb_flush(env, 1);
3965
        break;
3966
    case 1:
3967
        RPN = value & 0xFFFFFC0F;
3968
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
3969
            tlb_flush(env, 1);
3970
        tlb->RPN = RPN;
3971
        break;
3972
    case 2:
3973
        tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
3974
        tlb->prot = tlb->prot & PAGE_VALID;
3975
        if (value & 0x1)
3976
            tlb->prot |= PAGE_READ << 4;
3977
        if (value & 0x2)
3978
            tlb->prot |= PAGE_WRITE << 4;
3979
        if (value & 0x4)
3980
            tlb->prot |= PAGE_EXEC << 4;
3981
        if (value & 0x8)
3982
            tlb->prot |= PAGE_READ;
3983
        if (value & 0x10)
3984
            tlb->prot |= PAGE_WRITE;
3985
        if (value & 0x20)
3986
            tlb->prot |= PAGE_EXEC;
3987
        break;
3988
    }
3989
}
3990

    
3991
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
3992
{
3993
    ppcemb_tlb_t *tlb;
3994
    target_ulong ret;
3995
    int size;
3996

    
3997
    entry &= 0x3F;
3998
    tlb = &env->tlb[entry].tlbe;
3999
    switch (word) {
4000
    default:
4001
        /* Just here to please gcc */
4002
    case 0:
4003
        ret = tlb->EPN;
4004
        size = booke_page_size_to_tlb(tlb->size);
4005
        if (size < 0 || size > 0xF)
4006
            size = 1;
4007
        ret |= size << 4;
4008
        if (tlb->attr & 0x1)
4009
            ret |= 0x100;
4010
        if (tlb->prot & PAGE_VALID)
4011
            ret |= 0x200;
4012
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
4013
        env->spr[SPR_440_MMUCR] |= tlb->PID;
4014
        break;
4015
    case 1:
4016
        ret = tlb->RPN;
4017
        break;
4018
    case 2:
4019
        ret = tlb->attr & ~0x1;
4020
        if (tlb->prot & (PAGE_READ << 4))
4021
            ret |= 0x1;
4022
        if (tlb->prot & (PAGE_WRITE << 4))
4023
            ret |= 0x2;
4024
        if (tlb->prot & (PAGE_EXEC << 4))
4025
            ret |= 0x4;
4026
        if (tlb->prot & PAGE_READ)
4027
            ret |= 0x8;
4028
        if (tlb->prot & PAGE_WRITE)
4029
            ret |= 0x10;
4030
        if (tlb->prot & PAGE_EXEC)
4031
            ret |= 0x20;
4032
        break;
4033
    }
4034
    return ret;
4035
}
4036

    
4037
target_ulong helper_440_tlbsx (target_ulong address)
4038
{
4039
    return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
4040
}
4041

    
4042
#endif /* !CONFIG_USER_ONLY */