Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 1e42b8f0

History | View | Annotate | Download (61.2 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include "exec.h"
21

    
22
#include "op_helper.h"
23

    
24
#define MEMSUFFIX _raw
25
#include "op_helper.h"
26
#include "op_helper_mem.h"
27
#if !defined(CONFIG_USER_ONLY)
28
#define MEMSUFFIX _user
29
#include "op_helper.h"
30
#include "op_helper_mem.h"
31
#define MEMSUFFIX _kernel
32
#include "op_helper.h"
33
#include "op_helper_mem.h"
34
#if defined(TARGET_PPC64H)
35
#define MEMSUFFIX _hypv
36
#include "op_helper.h"
37
#include "op_helper_mem.h"
38
#endif
39
#endif
40

    
41
//#define DEBUG_OP
42
//#define DEBUG_EXCEPTIONS
43
//#define DEBUG_SOFTWARE_TLB
44

    
45
/*****************************************************************************/
46
/* Exceptions processing helpers */
47

    
48
void do_raise_exception_err (uint32_t exception, int error_code)
49
{
50
#if 0
51
    printf("Raise exception %3x code : %d\n", exception, error_code);
52
#endif
53
    switch (exception) {
54
    case POWERPC_EXCP_PROGRAM:
55
        if (error_code == POWERPC_EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
56
            return;
57
        break;
58
    default:
59
        break;
60
    }
61
    env->exception_index = exception;
62
    env->error_code = error_code;
63
    cpu_loop_exit();
64
}
65

    
66
void do_raise_exception (uint32_t exception)
67
{
68
    do_raise_exception_err(exception, 0);
69
}
70

    
71
void cpu_dump_EA (target_ulong EA);
72
void do_print_mem_EA (target_ulong EA)
73
{
74
    cpu_dump_EA(EA);
75
}
76

    
77
/*****************************************************************************/
78
/* Registers load and stores */
79
void do_load_cr (void)
80
{
81
    T0 = (env->crf[0] << 28) |
82
        (env->crf[1] << 24) |
83
        (env->crf[2] << 20) |
84
        (env->crf[3] << 16) |
85
        (env->crf[4] << 12) |
86
        (env->crf[5] << 8) |
87
        (env->crf[6] << 4) |
88
        (env->crf[7] << 0);
89
}
90

    
91
void do_store_cr (uint32_t mask)
92
{
93
    int i, sh;
94

    
95
    for (i = 0, sh = 7; i < 8; i++, sh--) {
96
        if (mask & (1 << sh))
97
            env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
98
    }
99
}
100

    
101
void do_load_xer (void)
102
{
103
    T0 = (xer_so << XER_SO) |
104
        (xer_ov << XER_OV) |
105
        (xer_ca << XER_CA) |
106
        (xer_bc << XER_BC) |
107
        (xer_cmp << XER_CMP);
108
}
109

    
110
void do_store_xer (void)
111
{
112
    xer_so = (T0 >> XER_SO) & 0x01;
113
    xer_ov = (T0 >> XER_OV) & 0x01;
114
    xer_ca = (T0 >> XER_CA) & 0x01;
115
    xer_cmp = (T0 >> XER_CMP) & 0xFF;
116
    xer_bc = (T0 >> XER_BC) & 0x7F;
117
}
118

    
119
#if defined(TARGET_PPC64)
120
void do_store_pri (int prio)
121
{
122
    env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
123
    env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
124
}
125
#endif
126

    
127
void do_load_fpscr (void)
128
{
129
    /* The 32 MSB of the target fpr are undefined.
130
     * They'll be zero...
131
     */
132
    union {
133
        float64 d;
134
        struct {
135
            uint32_t u[2];
136
        } s;
137
    } u;
138
    int i;
139

    
140
#if defined(WORDS_BIGENDIAN)
141
#define WORD0 0
142
#define WORD1 1
143
#else
144
#define WORD0 1
145
#define WORD1 0
146
#endif
147
    u.s.u[WORD0] = 0;
148
    u.s.u[WORD1] = 0;
149
    for (i = 0; i < 8; i++)
150
        u.s.u[WORD1] |= env->fpscr[i] << (4 * i);
151
    FT0 = u.d;
152
}
153

    
154
void do_store_fpscr (uint32_t mask)
155
{
156
    /*
157
     * We use only the 32 LSB of the incoming fpr
158
     */
159
    union {
160
        double d;
161
        struct {
162
            uint32_t u[2];
163
        } s;
164
    } u;
165
    int i, rnd_type;
166

    
167
    u.d = FT0;
168
    if (mask & 0x80)
169
        env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);
170
    for (i = 1; i < 7; i++) {
171
        if (mask & (1 << (7 - i)))
172
            env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;
173
    }
174
    /* TODO: update FEX & VX */
175
    /* Set rounding mode */
176
    switch (env->fpscr[0] & 0x3) {
177
    case 0:
178
        /* Best approximation (round to nearest) */
179
        rnd_type = float_round_nearest_even;
180
        break;
181
    case 1:
182
        /* Smaller magnitude (round toward zero) */
183
        rnd_type = float_round_to_zero;
184
        break;
185
    case 2:
186
        /* Round toward +infinite */
187
        rnd_type = float_round_up;
188
        break;
189
    default:
190
    case 3:
191
        /* Round toward -infinite */
192
        rnd_type = float_round_down;
193
        break;
194
    }
195
    set_float_rounding_mode(rnd_type, &env->fp_status);
196
}
197

    
198
target_ulong ppc_load_dump_spr (int sprn)
199
{
200
    if (loglevel != 0) {
201
        fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
202
                sprn, sprn, env->spr[sprn]);
203
    }
204

    
205
    return env->spr[sprn];
206
}
207

    
208
void ppc_store_dump_spr (int sprn, target_ulong val)
209
{
210
    if (loglevel != 0) {
211
        fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
212
                sprn, sprn, env->spr[sprn], val);
213
    }
214
    env->spr[sprn] = val;
215
}
216

    
217
/*****************************************************************************/
218
/* Fixed point operations helpers */
219
#if defined(TARGET_PPC64)
220
static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
221
{
222
    *plow += a;
223
    /* carry test */
224
    if (*plow < a)
225
        (*phigh)++;
226
    *phigh += b;
227
}
228

    
229
static void neg128 (uint64_t *plow, uint64_t *phigh)
230
{
231
    *plow = ~*plow;
232
    *phigh = ~*phigh;
233
    add128(plow, phigh, 1, 0);
234
}
235

    
236
static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
237
{
238
    uint32_t a0, a1, b0, b1;
239
    uint64_t v;
240

    
241
    a0 = a;
242
    a1 = a >> 32;
243

    
244
    b0 = b;
245
    b1 = b >> 32;
246

    
247
    v = (uint64_t)a0 * (uint64_t)b0;
248
    *plow = v;
249
    *phigh = 0;
250

    
251
    v = (uint64_t)a0 * (uint64_t)b1;
252
    add128(plow, phigh, v << 32, v >> 32);
253

    
254
    v = (uint64_t)a1 * (uint64_t)b0;
255
    add128(plow, phigh, v << 32, v >> 32);
256

    
257
    v = (uint64_t)a1 * (uint64_t)b1;
258
    *phigh += v;
259
#if defined(DEBUG_MULDIV)
260
    printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
261
           a, b, *phigh, *plow);
262
#endif
263
}
264

    
265
void do_mul64 (uint64_t *plow, uint64_t *phigh)
266
{
267
    mul64(plow, phigh, T0, T1);
268
}
269

    
270
static void imul64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
271
{
272
    int sa, sb;
273

    
274
    sa = (a < 0);
275
    if (sa)
276
        a = -a;
277
    sb = (b < 0);
278
    if (sb)
279
        b = -b;
280
    mul64(plow, phigh, a, b);
281
    if (sa ^ sb) {
282
        neg128(plow, phigh);
283
    }
284
}
285

    
286
void do_imul64 (uint64_t *plow, uint64_t *phigh)
287
{
288
    imul64(plow, phigh, T0, T1);
289
}
290
#endif
291

    
292
void do_adde (void)
293
{
294
    T2 = T0;
295
    T0 += T1 + xer_ca;
296
    if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
297
                 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
298
        xer_ca = 0;
299
    } else {
300
        xer_ca = 1;
301
    }
302
}
303

    
304
#if defined(TARGET_PPC64)
305
void do_adde_64 (void)
306
{
307
    T2 = T0;
308
    T0 += T1 + xer_ca;
309
    if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
310
                 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
311
        xer_ca = 0;
312
    } else {
313
        xer_ca = 1;
314
    }
315
}
316
#endif
317

    
318
void do_addmeo (void)
319
{
320
    T1 = T0;
321
    T0 += xer_ca + (-1);
322
    if (likely(!((uint32_t)T1 &
323
                 ((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) {
324
        xer_ov = 0;
325
    } else {
326
        xer_ov = 1;
327
        xer_so = 1;
328
    }
329
    if (likely(T1 != 0))
330
        xer_ca = 1;
331
}
332

    
333
#if defined(TARGET_PPC64)
334
void do_addmeo_64 (void)
335
{
336
    T1 = T0;
337
    T0 += xer_ca + (-1);
338
    if (likely(!((uint64_t)T1 &
339
                 ((uint64_t)T1 ^ (uint64_t)T0) & (1ULL << 63)))) {
340
        xer_ov = 0;
341
    } else {
342
        xer_ov = 1;
343
        xer_so = 1;
344
    }
345
    if (likely(T1 != 0))
346
        xer_ca = 1;
347
}
348
#endif
349

    
350
void do_divwo (void)
351
{
352
    if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) ||
353
                 (int32_t)T1 == 0))) {
354
        xer_ov = 0;
355
        T0 = (int32_t)T0 / (int32_t)T1;
356
    } else {
357
        xer_ov = 1;
358
        xer_so = 1;
359
        T0 = (-1) * ((uint32_t)T0 >> 31);
360
    }
361
}
362

    
363
#if defined(TARGET_PPC64)
364
void do_divdo (void)
365
{
366
    if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == -1ULL) ||
367
                 (int64_t)T1 == 0))) {
368
        xer_ov = 0;
369
        T0 = (int64_t)T0 / (int64_t)T1;
370
    } else {
371
        xer_ov = 1;
372
        xer_so = 1;
373
        T0 = (-1ULL) * ((uint64_t)T0 >> 63);
374
    }
375
}
376
#endif
377

    
378
void do_divwuo (void)
379
{
380
    if (likely((uint32_t)T1 != 0)) {
381
        xer_ov = 0;
382
        T0 = (uint32_t)T0 / (uint32_t)T1;
383
    } else {
384
        xer_ov = 1;
385
        xer_so = 1;
386
        T0 = 0;
387
    }
388
}
389

    
390
#if defined(TARGET_PPC64)
391
void do_divduo (void)
392
{
393
    if (likely((uint64_t)T1 != 0)) {
394
        xer_ov = 0;
395
        T0 = (uint64_t)T0 / (uint64_t)T1;
396
    } else {
397
        xer_ov = 1;
398
        xer_so = 1;
399
        T0 = 0;
400
    }
401
}
402
#endif
403

    
404
void do_mullwo (void)
405
{
406
    int64_t res = (int64_t)T0 * (int64_t)T1;
407

    
408
    if (likely((int32_t)res == res)) {
409
        xer_ov = 0;
410
    } else {
411
        xer_ov = 1;
412
        xer_so = 1;
413
    }
414
    T0 = (int32_t)res;
415
}
416

    
417
#if defined(TARGET_PPC64)
418
void do_mulldo (void)
419
{
420
    int64_t th;
421
    uint64_t tl;
422

    
423
    do_imul64(&tl, &th);
424
    if (likely(th == 0)) {
425
        xer_ov = 0;
426
    } else {
427
        xer_ov = 1;
428
        xer_so = 1;
429
    }
430
    T0 = (int64_t)tl;
431
}
432
#endif
433

    
434
void do_nego (void)
435
{
436
    if (likely((int32_t)T0 != INT32_MIN)) {
437
        xer_ov = 0;
438
        T0 = -(int32_t)T0;
439
    } else {
440
        xer_ov = 1;
441
        xer_so = 1;
442
    }
443
}
444

    
445
#if defined(TARGET_PPC64)
446
void do_nego_64 (void)
447
{
448
    if (likely((int64_t)T0 != INT64_MIN)) {
449
        xer_ov = 0;
450
        T0 = -(int64_t)T0;
451
    } else {
452
        xer_ov = 1;
453
        xer_so = 1;
454
    }
455
}
456
#endif
457

    
458
void do_subfe (void)
459
{
460
    T0 = T1 + ~T0 + xer_ca;
461
    if (likely((uint32_t)T0 >= (uint32_t)T1 &&
462
               (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
463
        xer_ca = 0;
464
    } else {
465
        xer_ca = 1;
466
    }
467
}
468

    
469
#if defined(TARGET_PPC64)
470
void do_subfe_64 (void)
471
{
472
    T0 = T1 + ~T0 + xer_ca;
473
    if (likely((uint64_t)T0 >= (uint64_t)T1 &&
474
               (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
475
        xer_ca = 0;
476
    } else {
477
        xer_ca = 1;
478
    }
479
}
480
#endif
481

    
482
void do_subfmeo (void)
483
{
484
    T1 = T0;
485
    T0 = ~T0 + xer_ca - 1;
486
    if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) &
487
                 (1UL << 31)))) {
488
        xer_ov = 0;
489
    } else {
490
        xer_ov = 1;
491
        xer_so = 1;
492
    }
493
    if (likely((uint32_t)T1 != UINT32_MAX))
494
        xer_ca = 1;
495
}
496

    
497
#if defined(TARGET_PPC64)
498
void do_subfmeo_64 (void)
499
{
500
    T1 = T0;
501
    T0 = ~T0 + xer_ca - 1;
502
    if (likely(!((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0) &
503
                 (1ULL << 63)))) {
504
        xer_ov = 0;
505
    } else {
506
        xer_ov = 1;
507
        xer_so = 1;
508
    }
509
    if (likely((uint64_t)T1 != UINT64_MAX))
510
        xer_ca = 1;
511
}
512
#endif
513

    
514
void do_subfzeo (void)
515
{
516
    T1 = T0;
517
    T0 = ~T0 + xer_ca;
518
    if (likely(!(((uint32_t)~T1 ^ UINT32_MAX) &
519
                 ((uint32_t)(~T1) ^ (uint32_t)T0) & (1UL << 31)))) {
520
        xer_ov = 0;
521
    } else {
522
        xer_ov = 1;
523
        xer_so = 1;
524
    }
525
    if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
526
        xer_ca = 0;
527
    } else {
528
        xer_ca = 1;
529
    }
530
}
531

    
532
#if defined(TARGET_PPC64)
533
void do_subfzeo_64 (void)
534
{
535
    T1 = T0;
536
    T0 = ~T0 + xer_ca;
537
    if (likely(!(((uint64_t)~T1 ^ UINT64_MAX) &
538
                 ((uint64_t)(~T1) ^ (uint64_t)T0) & (1ULL << 63)))) {
539
        xer_ov = 0;
540
    } else {
541
        xer_ov = 1;
542
        xer_so = 1;
543
    }
544
    if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
545
        xer_ca = 0;
546
    } else {
547
        xer_ca = 1;
548
    }
549
}
550
#endif
551

    
552
/* shift right arithmetic helper */
553
void do_sraw (void)
554
{
555
    int32_t ret;
556

    
557
    if (likely(!(T1 & 0x20UL))) {
558
        if (likely((uint32_t)T1 != 0)) {
559
            ret = (int32_t)T0 >> (T1 & 0x1fUL);
560
            if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
561
                xer_ca = 0;
562
            } else {
563
                xer_ca = 1;
564
            }
565
        } else {
566
            ret = T0;
567
            xer_ca = 0;
568
        }
569
    } else {
570
        ret = (-1) * ((uint32_t)T0 >> 31);
571
        if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
572
            xer_ca = 0;
573
        } else {
574
            xer_ca = 1;
575
        }
576
    }
577
    T0 = ret;
578
}
579

    
580
#if defined(TARGET_PPC64)
581
void do_srad (void)
582
{
583
    int64_t ret;
584

    
585
    if (likely(!(T1 & 0x40UL))) {
586
        if (likely((uint64_t)T1 != 0)) {
587
            ret = (int64_t)T0 >> (T1 & 0x3FUL);
588
            if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
589
                xer_ca = 0;
590
            } else {
591
                xer_ca = 1;
592
            }
593
        } else {
594
            ret = T0;
595
            xer_ca = 0;
596
        }
597
    } else {
598
        ret = (-1) * ((uint64_t)T0 >> 63);
599
        if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
600
            xer_ca = 0;
601
        } else {
602
            xer_ca = 1;
603
        }
604
    }
605
    T0 = ret;
606
}
607
#endif
608

    
609
static always_inline int popcnt (uint32_t val)
610
{
611
    int i;
612

    
613
    for (i = 0; val != 0;)
614
        val = val ^ (val - 1);
615

    
616
    return i;
617
}
618

    
619
void do_popcntb (void)
620
{
621
    uint32_t ret;
622
    int i;
623

    
624
    ret = 0;
625
    for (i = 0; i < 32; i += 8)
626
        ret |= popcnt((T0 >> i) & 0xFF) << i;
627
    T0 = ret;
628
}
629

    
630
#if defined(TARGET_PPC64)
631
void do_popcntb_64 (void)
632
{
633
    uint64_t ret;
634
    int i;
635

    
636
    ret = 0;
637
    for (i = 0; i < 64; i += 8)
638
        ret |= popcnt((T0 >> i) & 0xFF) << i;
639
    T0 = ret;
640
}
641
#endif
642

    
643
/*****************************************************************************/
644
/* Floating point operations helpers */
645
void do_fctiw (void)
646
{
647
    union {
648
        double d;
649
        uint64_t i;
650
    } p;
651

    
652
    p.i = float64_to_int32(FT0, &env->fp_status);
653
#if USE_PRECISE_EMULATION
654
    /* XXX: higher bits are not supposed to be significant.
655
     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
656
     */
657
    p.i |= 0xFFF80000ULL << 32;
658
#endif
659
    FT0 = p.d;
660
}
661

    
662
void do_fctiwz (void)
663
{
664
    union {
665
        double d;
666
        uint64_t i;
667
    } p;
668

    
669
    p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
670
#if USE_PRECISE_EMULATION
671
    /* XXX: higher bits are not supposed to be significant.
672
     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
673
     */
674
    p.i |= 0xFFF80000ULL << 32;
675
#endif
676
    FT0 = p.d;
677
}
678

    
679
#if defined(TARGET_PPC64)
680
void do_fcfid (void)
681
{
682
    union {
683
        double d;
684
        uint64_t i;
685
    } p;
686

    
687
    p.d = FT0;
688
    FT0 = int64_to_float64(p.i, &env->fp_status);
689
}
690

    
691
void do_fctid (void)
692
{
693
    union {
694
        double d;
695
        uint64_t i;
696
    } p;
697

    
698
    p.i = float64_to_int64(FT0, &env->fp_status);
699
    FT0 = p.d;
700
}
701

    
702
void do_fctidz (void)
703
{
704
    union {
705
        double d;
706
        uint64_t i;
707
    } p;
708

    
709
    p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
710
    FT0 = p.d;
711
}
712

    
713
#endif
714

    
715
static always_inline void do_fri (int rounding_mode)
716
{
717
    int curmode;
718

    
719
    curmode = env->fp_status.float_rounding_mode;
720
    set_float_rounding_mode(rounding_mode, &env->fp_status);
721
    FT0 = float64_round_to_int(FT0, &env->fp_status);
722
    set_float_rounding_mode(curmode, &env->fp_status);
723
}
724

    
725
void do_frin (void)
726
{
727
    do_fri(float_round_nearest_even);
728
}
729

    
730
void do_friz (void)
731
{
732
    do_fri(float_round_to_zero);
733
}
734

    
735
void do_frip (void)
736
{
737
    do_fri(float_round_up);
738
}
739

    
740
void do_frim (void)
741
{
742
    do_fri(float_round_down);
743
}
744

    
745
#if USE_PRECISE_EMULATION
746
void do_fmadd (void)
747
{
748
#ifdef FLOAT128
749
    float128 ft0_128, ft1_128;
750

    
751
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
752
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
753
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
754
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
755
    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
756
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
757
#else
758
    /* This is OK on x86 hosts */
759
    FT0 = (FT0 * FT1) + FT2;
760
#endif
761
}
762

    
763
void do_fmsub (void)
764
{
765
#ifdef FLOAT128
766
    float128 ft0_128, ft1_128;
767

    
768
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
769
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
770
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
771
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
772
    ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
773
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
774
#else
775
    /* This is OK on x86 hosts */
776
    FT0 = (FT0 * FT1) - FT2;
777
#endif
778
}
779
#endif /* USE_PRECISE_EMULATION */
780

    
781
void do_fnmadd (void)
782
{
783
#if USE_PRECISE_EMULATION
784
#ifdef FLOAT128
785
    float128 ft0_128, ft1_128;
786

    
787
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
788
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
789
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
790
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
791
    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
792
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
793
#else
794
    /* This is OK on x86 hosts */
795
    FT0 = (FT0 * FT1) + FT2;
796
#endif
797
#else
798
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
799
    FT0 = float64_add(FT0, FT2, &env->fp_status);
800
#endif
801
    if (likely(!isnan(FT0)))
802
        FT0 = float64_chs(FT0);
803
}
804

    
805
void do_fnmsub (void)
806
{
807
#if USE_PRECISE_EMULATION
808
#ifdef FLOAT128
809
    float128 ft0_128, ft1_128;
810

    
811
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
812
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
813
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
814
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
815
    ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
816
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
817
#else
818
    /* This is OK on x86 hosts */
819
    FT0 = (FT0 * FT1) - FT2;
820
#endif
821
#else
822
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
823
    FT0 = float64_sub(FT0, FT2, &env->fp_status);
824
#endif
825
    if (likely(!isnan(FT0)))
826
        FT0 = float64_chs(FT0);
827
}
828

    
829
void do_fsqrt (void)
830
{
831
    FT0 = float64_sqrt(FT0, &env->fp_status);
832
}
833

    
834
void do_fre (void)
835
{
836
    union {
837
        double d;
838
        uint64_t i;
839
    } p;
840

    
841
    if (likely(isnormal(FT0))) {
842
        FT0 = float64_div(1.0, FT0, &env->fp_status);
843
    } else {
844
        p.d = FT0;
845
        if (p.i == 0x8000000000000000ULL) {
846
            p.i = 0xFFF0000000000000ULL;
847
        } else if (p.i == 0x0000000000000000ULL) {
848
            p.i = 0x7FF0000000000000ULL;
849
        } else if (isnan(FT0)) {
850
            p.i = 0x7FF8000000000000ULL;
851
        } else if (FT0 < 0.0) {
852
            p.i = 0x8000000000000000ULL;
853
        } else {
854
            p.i = 0x0000000000000000ULL;
855
        }
856
        FT0 = p.d;
857
    }
858
}
859

    
860
void do_fres (void)
861
{
862
    union {
863
        double d;
864
        uint64_t i;
865
    } p;
866

    
867
    if (likely(isnormal(FT0))) {
868
#if USE_PRECISE_EMULATION
869
        FT0 = float64_div(1.0, FT0, &env->fp_status);
870
        FT0 = float64_to_float32(FT0, &env->fp_status);
871
#else
872
        FT0 = float32_div(1.0, FT0, &env->fp_status);
873
#endif
874
    } else {
875
        p.d = FT0;
876
        if (p.i == 0x8000000000000000ULL) {
877
            p.i = 0xFFF0000000000000ULL;
878
        } else if (p.i == 0x0000000000000000ULL) {
879
            p.i = 0x7FF0000000000000ULL;
880
        } else if (isnan(FT0)) {
881
            p.i = 0x7FF8000000000000ULL;
882
        } else if (FT0 < 0.0) {
883
            p.i = 0x8000000000000000ULL;
884
        } else {
885
            p.i = 0x0000000000000000ULL;
886
        }
887
        FT0 = p.d;
888
    }
889
}
890

    
891
void do_frsqrte (void)
892
{
893
    union {
894
        double d;
895
        uint64_t i;
896
    } p;
897

    
898
    if (likely(isnormal(FT0) && FT0 > 0.0)) {
899
        FT0 = float64_sqrt(FT0, &env->fp_status);
900
        FT0 = float32_div(1.0, FT0, &env->fp_status);
901
    } else {
902
        p.d = FT0;
903
        if (p.i == 0x8000000000000000ULL) {
904
            p.i = 0xFFF0000000000000ULL;
905
        } else if (p.i == 0x0000000000000000ULL) {
906
            p.i = 0x7FF0000000000000ULL;
907
        } else if (isnan(FT0)) {
908
            if (!(p.i & 0x0008000000000000ULL))
909
                p.i |= 0x000FFFFFFFFFFFFFULL;
910
        } else if (FT0 < 0) {
911
            p.i = 0x7FF8000000000000ULL;
912
        } else {
913
            p.i = 0x0000000000000000ULL;
914
        }
915
        FT0 = p.d;
916
    }
917
}
918

    
919
void do_fsel (void)
920
{
921
    if (FT0 >= 0)
922
        FT0 = FT1;
923
    else
924
        FT0 = FT2;
925
}
926

    
927
void do_fcmpu (void)
928
{
929
    if (likely(!isnan(FT0) && !isnan(FT1))) {
930
        if (float64_lt(FT0, FT1, &env->fp_status)) {
931
            T0 = 0x08UL;
932
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
933
            T0 = 0x04UL;
934
        } else {
935
            T0 = 0x02UL;
936
        }
937
    } else {
938
        T0 = 0x01UL;
939
        env->fpscr[4] |= 0x1;
940
        env->fpscr[6] |= 0x1;
941
    }
942
    env->fpscr[3] = T0;
943
}
944

    
945
void do_fcmpo (void)
946
{
947
    env->fpscr[4] &= ~0x1;
948
    if (likely(!isnan(FT0) && !isnan(FT1))) {
949
        if (float64_lt(FT0, FT1, &env->fp_status)) {
950
            T0 = 0x08UL;
951
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
952
            T0 = 0x04UL;
953
        } else {
954
            T0 = 0x02UL;
955
        }
956
    } else {
957
        T0 = 0x01UL;
958
        env->fpscr[4] |= 0x1;
959
        if (!float64_is_signaling_nan(FT0) || !float64_is_signaling_nan(FT1)) {
960
            /* Quiet NaN case */
961
            env->fpscr[6] |= 0x1;
962
            if (!(env->fpscr[1] & 0x8))
963
                env->fpscr[4] |= 0x8;
964
        } else {
965
            env->fpscr[4] |= 0x8;
966
        }
967
    }
968
    env->fpscr[3] = T0;
969
}
970

    
971
#if !defined (CONFIG_USER_ONLY)
972
void cpu_dump_rfi (target_ulong RA, target_ulong msr);
973
void do_rfi (void)
974
{
975
#if defined(TARGET_PPC64)
976
    if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
977
        env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
978
        do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
979
    } else {
980
        env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
981
        ppc_store_msr_32(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
982
    }
983
#else
984
    env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
985
    do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
986
#endif
987
#if defined (DEBUG_OP)
988
    cpu_dump_rfi(env->nip, do_load_msr(env));
989
#endif
990
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
991
}
992

    
993
#if defined(TARGET_PPC64)
994
void do_rfid (void)
995
{
996
    if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
997
        env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
998
        do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
999
    } else {
1000
        env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
1001
        do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
1002
    }
1003
#if defined (DEBUG_OP)
1004
    cpu_dump_rfi(env->nip, do_load_msr(env));
1005
#endif
1006
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1007
}
1008
#endif
1009
#if defined(TARGET_PPC64H)
1010
void do_hrfid (void)
1011
{
1012
    if (env->spr[SPR_HSRR1] & (1ULL << MSR_SF)) {
1013
        env->nip = (uint64_t)(env->spr[SPR_HSRR0] & ~0x00000003);
1014
        do_store_msr(env, (uint64_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL));
1015
    } else {
1016
        env->nip = (uint32_t)(env->spr[SPR_HSRR0] & ~0x00000003);
1017
        do_store_msr(env, (uint32_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL));
1018
    }
1019
#if defined (DEBUG_OP)
1020
    cpu_dump_rfi(env->nip, do_load_msr(env));
1021
#endif
1022
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1023
}
1024
#endif
1025
#endif
1026

    
1027
void do_tw (int flags)
1028
{
1029
    if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
1030
                  ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
1031
                  ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
1032
                  ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
1033
                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
1034
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1035
    }
1036
}
1037

    
1038
#if defined(TARGET_PPC64)
1039
void do_td (int flags)
1040
{
1041
    if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
1042
                  ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
1043
                  ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
1044
                  ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
1045
                  ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
1046
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1047
}
1048
#endif
1049

    
1050
/*****************************************************************************/
1051
/* PowerPC 601 specific instructions (POWER bridge) */
1052
void do_POWER_abso (void)
1053
{
1054
    if ((uint32_t)T0 == INT32_MIN) {
1055
        T0 = INT32_MAX;
1056
        xer_ov = 1;
1057
        xer_so = 1;
1058
    } else {
1059
        T0 = -T0;
1060
        xer_ov = 0;
1061
    }
1062
}
1063

    
1064
void do_POWER_clcs (void)
1065
{
1066
    switch (T0) {
1067
    case 0x0CUL:
1068
        /* Instruction cache line size */
1069
        T0 = env->icache_line_size;
1070
        break;
1071
    case 0x0DUL:
1072
        /* Data cache line size */
1073
        T0 = env->dcache_line_size;
1074
        break;
1075
    case 0x0EUL:
1076
        /* Minimum cache line size */
1077
        T0 = env->icache_line_size < env->dcache_line_size ?
1078
            env->icache_line_size : env->dcache_line_size;
1079
        break;
1080
    case 0x0FUL:
1081
        /* Maximum cache line size */
1082
        T0 = env->icache_line_size > env->dcache_line_size ?
1083
            env->icache_line_size : env->dcache_line_size;
1084
        break;
1085
    default:
1086
        /* Undefined */
1087
        break;
1088
    }
1089
}
1090

    
1091
void do_POWER_div (void)
1092
{
1093
    uint64_t tmp;
1094

    
1095
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1096
        T0 = (long)((-1) * (T0 >> 31));
1097
        env->spr[SPR_MQ] = 0;
1098
    } else {
1099
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1100
        env->spr[SPR_MQ] = tmp % T1;
1101
        T0 = tmp / (int32_t)T1;
1102
    }
1103
}
1104

    
1105
void do_POWER_divo (void)
1106
{
1107
    int64_t tmp;
1108

    
1109
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1110
        T0 = (long)((-1) * (T0 >> 31));
1111
        env->spr[SPR_MQ] = 0;
1112
        xer_ov = 1;
1113
        xer_so = 1;
1114
    } else {
1115
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1116
        env->spr[SPR_MQ] = tmp % T1;
1117
        tmp /= (int32_t)T1;
1118
        if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
1119
            xer_ov = 1;
1120
            xer_so = 1;
1121
        } else {
1122
            xer_ov = 0;
1123
        }
1124
        T0 = tmp;
1125
    }
1126
}
1127

    
1128
void do_POWER_divs (void)
1129
{
1130
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1131
        T0 = (long)((-1) * (T0 >> 31));
1132
        env->spr[SPR_MQ] = 0;
1133
    } else {
1134
        env->spr[SPR_MQ] = T0 % T1;
1135
        T0 = (int32_t)T0 / (int32_t)T1;
1136
    }
1137
}
1138

    
1139
void do_POWER_divso (void)
1140
{
1141
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1142
        T0 = (long)((-1) * (T0 >> 31));
1143
        env->spr[SPR_MQ] = 0;
1144
        xer_ov = 1;
1145
        xer_so = 1;
1146
    } else {
1147
        T0 = (int32_t)T0 / (int32_t)T1;
1148
        env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
1149
        xer_ov = 0;
1150
    }
1151
}
1152

    
1153
void do_POWER_dozo (void)
1154
{
1155
    if ((int32_t)T1 > (int32_t)T0) {
1156
        T2 = T0;
1157
        T0 = T1 - T0;
1158
        if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
1159
            ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
1160
            xer_ov = 1;
1161
            xer_so = 1;
1162
        } else {
1163
            xer_ov = 0;
1164
        }
1165
    } else {
1166
        T0 = 0;
1167
        xer_ov = 0;
1168
    }
1169
}
1170

    
1171
void do_POWER_maskg (void)
1172
{
1173
    uint32_t ret;
1174

    
1175
    if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
1176
        ret = -1;
1177
    } else {
1178
        ret = (((uint32_t)(-1)) >> ((uint32_t)T0)) ^
1179
            (((uint32_t)(-1) >> ((uint32_t)T1)) >> 1);
1180
        if ((uint32_t)T0 > (uint32_t)T1)
1181
            ret = ~ret;
1182
    }
1183
    T0 = ret;
1184
}
1185

    
1186
void do_POWER_mulo (void)
1187
{
1188
    uint64_t tmp;
1189

    
1190
    tmp = (uint64_t)T0 * (uint64_t)T1;
1191
    env->spr[SPR_MQ] = tmp >> 32;
1192
    T0 = tmp;
1193
    if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
1194
        xer_ov = 1;
1195
        xer_so = 1;
1196
    } else {
1197
        xer_ov = 0;
1198
    }
1199
}
1200

    
1201
#if !defined (CONFIG_USER_ONLY)
1202
void do_POWER_rac (void)
1203
{
1204
#if 0
1205
    mmu_ctx_t ctx;
1206

1207
    /* We don't have to generate many instances of this instruction,
1208
     * as rac is supervisor only.
1209
     */
1210
    if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT, 1) == 0)
1211
        T0 = ctx.raddr;
1212
#endif
1213
}
1214

    
1215
void do_POWER_rfsvc (void)
1216
{
1217
    env->nip = env->lr & ~0x00000003UL;
1218
    T0 = env->ctr & 0x0000FFFFUL;
1219
    do_store_msr(env, T0);
1220
#if defined (DEBUG_OP)
1221
    cpu_dump_rfi(env->nip, do_load_msr(env));
1222
#endif
1223
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1224
}
1225

    
1226
/* PowerPC 601 BAT management helper */
1227
void do_store_601_batu (int nr)
1228
{
1229
    do_store_ibatu(env, nr, (uint32_t)T0);
1230
    env->DBAT[0][nr] = env->IBAT[0][nr];
1231
    env->DBAT[1][nr] = env->IBAT[1][nr];
1232
}
1233
#endif
1234

    
1235
/*****************************************************************************/
1236
/* 602 specific instructions */
1237
/* mfrom is the most crazy instruction ever seen, imho ! */
1238
/* Real implementation uses a ROM table. Do the same */
1239
#define USE_MFROM_ROM_TABLE
1240
void do_op_602_mfrom (void)
1241
{
1242
    if (likely(T0 < 602)) {
1243
#if defined(USE_MFROM_ROM_TABLE)
1244
#include "mfrom_table.c"
1245
        T0 = mfrom_ROM_table[T0];
1246
#else
1247
        double d;
1248
        /* Extremly decomposed:
1249
         *                    -T0 / 256
1250
         * T0 = 256 * log10(10          + 1.0) + 0.5
1251
         */
1252
        d = T0;
1253
        d = float64_div(d, 256, &env->fp_status);
1254
        d = float64_chs(d);
1255
        d = exp10(d); // XXX: use float emulation function
1256
        d = float64_add(d, 1.0, &env->fp_status);
1257
        d = log10(d); // XXX: use float emulation function
1258
        d = float64_mul(d, 256, &env->fp_status);
1259
        d = float64_add(d, 0.5, &env->fp_status);
1260
        T0 = float64_round_to_int(d, &env->fp_status);
1261
#endif
1262
    } else {
1263
        T0 = 0;
1264
    }
1265
}
1266

    
1267
/*****************************************************************************/
1268
/* Embedded PowerPC specific helpers */
1269
void do_405_check_ov (void)
1270
{
1271
    if (likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1272
               !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1273
        xer_ov = 0;
1274
    } else {
1275
        xer_ov = 1;
1276
        xer_so = 1;
1277
    }
1278
}
1279

    
1280
void do_405_check_sat (void)
1281
{
1282
    if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1283
                !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1284
        /* Saturate result */
1285
        if (T2 >> 31) {
1286
            T0 = INT32_MIN;
1287
        } else {
1288
            T0 = INT32_MAX;
1289
        }
1290
    }
1291
}
1292

    
1293
/* XXX: to be improved to check access rights when in user-mode */
1294
void do_load_dcr (void)
1295
{
1296
    target_ulong val;
1297

    
1298
    if (unlikely(env->dcr_env == NULL)) {
1299
        if (loglevel != 0) {
1300
            fprintf(logfile, "No DCR environment\n");
1301
        }
1302
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1303
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1304
    } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
1305
        if (loglevel != 0) {
1306
            fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
1307
        }
1308
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1309
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1310
    } else {
1311
        T0 = val;
1312
    }
1313
}
1314

    
1315
void do_store_dcr (void)
1316
{
1317
    if (unlikely(env->dcr_env == NULL)) {
1318
        if (loglevel != 0) {
1319
            fprintf(logfile, "No DCR environment\n");
1320
        }
1321
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1322
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1323
    } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
1324
        if (loglevel != 0) {
1325
            fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
1326
        }
1327
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1328
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1329
    }
1330
}
1331

    
1332
#if !defined(CONFIG_USER_ONLY)
1333
void do_40x_rfci (void)
1334
{
1335
    env->nip = env->spr[SPR_40x_SRR2];
1336
    do_store_msr(env, env->spr[SPR_40x_SRR3] & ~0xFFFF0000);
1337
#if defined (DEBUG_OP)
1338
    cpu_dump_rfi(env->nip, do_load_msr(env));
1339
#endif
1340
    env->interrupt_request = CPU_INTERRUPT_EXITTB;
1341
}
1342

    
1343
void do_rfci (void)
1344
{
1345
#if defined(TARGET_PPC64)
1346
    if (env->spr[SPR_BOOKE_CSRR1] & (1 << MSR_CM)) {
1347
        env->nip = (uint64_t)env->spr[SPR_BOOKE_CSRR0];
1348
    } else
1349
#endif
1350
    {
1351
        env->nip = (uint32_t)env->spr[SPR_BOOKE_CSRR0];
1352
    }
1353
    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_CSRR1] & ~0x3FFF0000);
1354
#if defined (DEBUG_OP)
1355
    cpu_dump_rfi(env->nip, do_load_msr(env));
1356
#endif
1357
    env->interrupt_request = CPU_INTERRUPT_EXITTB;
1358
}
1359

    
1360
void do_rfdi (void)
1361
{
1362
#if defined(TARGET_PPC64)
1363
    if (env->spr[SPR_BOOKE_DSRR1] & (1 << MSR_CM)) {
1364
        env->nip = (uint64_t)env->spr[SPR_BOOKE_DSRR0];
1365
    } else
1366
#endif
1367
    {
1368
        env->nip = (uint32_t)env->spr[SPR_BOOKE_DSRR0];
1369
    }
1370
    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_DSRR1] & ~0x3FFF0000);
1371
#if defined (DEBUG_OP)
1372
    cpu_dump_rfi(env->nip, do_load_msr(env));
1373
#endif
1374
    env->interrupt_request = CPU_INTERRUPT_EXITTB;
1375
}
1376

    
1377
void do_rfmci (void)
1378
{
1379
#if defined(TARGET_PPC64)
1380
    if (env->spr[SPR_BOOKE_MCSRR1] & (1 << MSR_CM)) {
1381
        env->nip = (uint64_t)env->spr[SPR_BOOKE_MCSRR0];
1382
    } else
1383
#endif
1384
    {
1385
        env->nip = (uint32_t)env->spr[SPR_BOOKE_MCSRR0];
1386
    }
1387
    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_MCSRR1] & ~0x3FFF0000);
1388
#if defined (DEBUG_OP)
1389
    cpu_dump_rfi(env->nip, do_load_msr(env));
1390
#endif
1391
    env->interrupt_request = CPU_INTERRUPT_EXITTB;
1392
}
1393

    
1394
void do_load_403_pb (int num)
1395
{
1396
    T0 = env->pb[num];
1397
}
1398

    
1399
void do_store_403_pb (int num)
1400
{
1401
    if (likely(env->pb[num] != T0)) {
1402
        env->pb[num] = T0;
1403
        /* Should be optimized */
1404
        tlb_flush(env, 1);
1405
    }
1406
}
1407
#endif
1408

    
1409
/* 440 specific */
1410
void do_440_dlmzb (void)
1411
{
1412
    target_ulong mask;
1413
    int i;
1414

    
1415
    i = 1;
1416
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1417
        if ((T0 & mask) == 0)
1418
            goto done;
1419
        i++;
1420
    }
1421
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1422
        if ((T1 & mask) == 0)
1423
            break;
1424
        i++;
1425
    }
1426
 done:
1427
    T0 = i;
1428
}
1429

    
1430
#if defined(TARGET_PPCEMB)
1431
/* SPE extension helpers */
1432
/* Use a table to make this quicker */
1433
static uint8_t hbrev[16] = {
1434
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1435
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1436
};
1437

    
1438
static always_inline uint8_t byte_reverse (uint8_t val)
1439
{
1440
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1441
}
1442

    
1443
static always_inline uint32_t word_reverse (uint32_t val)
1444
{
1445
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1446
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1447
}
1448

    
1449
#define MASKBITS 16 // Random value - to be fixed
1450
void do_brinc (void)
1451
{
1452
    uint32_t a, b, d, mask;
1453

    
1454
    mask = (uint32_t)(-1UL) >> MASKBITS;
1455
    b = T1_64 & mask;
1456
    a = T0_64 & mask;
1457
    d = word_reverse(1 + word_reverse(a | ~mask));
1458
    T0_64 = (T0_64 & ~mask) | (d & mask);
1459
}
1460

    
1461
#define DO_SPE_OP2(name)                                                      \
1462
void do_ev##name (void)                                                       \
1463
{                                                                             \
1464
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) |         \
1465
        (uint64_t)_do_e##name(T0_64, T1_64);                                  \
1466
}
1467

    
1468
#define DO_SPE_OP1(name)                                                      \
1469
void do_ev##name (void)                                                       \
1470
{                                                                             \
1471
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) |                      \
1472
        (uint64_t)_do_e##name(T0_64);                                         \
1473
}
1474

    
1475
/* Fixed-point vector arithmetic */
1476
static always_inline uint32_t _do_eabs (uint32_t val)
1477
{
1478
    if (val != 0x80000000)
1479
        val &= ~0x80000000;
1480

    
1481
    return val;
1482
}
1483

    
1484
static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1485
{
1486
    return op1 + op2;
1487
}
1488

    
1489
static always_inline int _do_ecntlsw (uint32_t val)
1490
{
1491
    if (val & 0x80000000)
1492
        return _do_cntlzw(~val);
1493
    else
1494
        return _do_cntlzw(val);
1495
}
1496

    
1497
static always_inline int _do_ecntlzw (uint32_t val)
1498
{
1499
    return _do_cntlzw(val);
1500
}
1501

    
1502
static always_inline uint32_t _do_eneg (uint32_t val)
1503
{
1504
    if (val != 0x80000000)
1505
        val ^= 0x80000000;
1506

    
1507
    return val;
1508
}
1509

    
1510
static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1511
{
1512
    return rotl32(op1, op2);
1513
}
1514

    
1515
static always_inline uint32_t _do_erndw (uint32_t val)
1516
{
1517
    return (val + 0x000080000000) & 0xFFFF0000;
1518
}
1519

    
1520
static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1521
{
1522
    /* No error here: 6 bits are used */
1523
    return op1 << (op2 & 0x3F);
1524
}
1525

    
1526
static always_inline int32_t _do_esrws (int32_t op1, uint32_t op2)
1527
{
1528
    /* No error here: 6 bits are used */
1529
    return op1 >> (op2 & 0x3F);
1530
}
1531

    
1532
static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1533
{
1534
    /* No error here: 6 bits are used */
1535
    return op1 >> (op2 & 0x3F);
1536
}
1537

    
1538
static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1539
{
1540
    return op2 - op1;
1541
}
1542

    
1543
/* evabs */
1544
DO_SPE_OP1(abs);
1545
/* evaddw */
1546
DO_SPE_OP2(addw);
1547
/* evcntlsw */
1548
DO_SPE_OP1(cntlsw);
1549
/* evcntlzw */
1550
DO_SPE_OP1(cntlzw);
1551
/* evneg */
1552
DO_SPE_OP1(neg);
1553
/* evrlw */
1554
DO_SPE_OP2(rlw);
1555
/* evrnd */
1556
DO_SPE_OP1(rndw);
1557
/* evslw */
1558
DO_SPE_OP2(slw);
1559
/* evsrws */
1560
DO_SPE_OP2(srws);
1561
/* evsrwu */
1562
DO_SPE_OP2(srwu);
1563
/* evsubfw */
1564
DO_SPE_OP2(subfw);
1565

    
1566
/* evsel is a little bit more complicated... */
1567
static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1568
{
1569
    if (n)
1570
        return op1;
1571
    else
1572
        return op2;
1573
}
1574

    
1575
void do_evsel (void)
1576
{
1577
    T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1578
        (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
1579
}
1580

    
1581
/* Fixed-point vector comparisons */
1582
#define DO_SPE_CMP(name)                                                      \
1583
void do_ev##name (void)                                                       \
1584
{                                                                             \
1585
    T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32,                   \
1586
                                               T1_64 >> 32) << 32,            \
1587
                         _do_e##name(T0_64, T1_64));                          \
1588
}
1589

    
1590
static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
1591
{
1592
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1593
}
1594
static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1595
{
1596
    return op1 == op2 ? 1 : 0;
1597
}
1598

    
1599
static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
1600
{
1601
    return op1 > op2 ? 1 : 0;
1602
}
1603

    
1604
static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
1605
{
1606
    return op1 > op2 ? 1 : 0;
1607
}
1608

    
1609
static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
1610
{
1611
    return op1 < op2 ? 1 : 0;
1612
}
1613

    
1614
static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
1615
{
1616
    return op1 < op2 ? 1 : 0;
1617
}
1618

    
1619
/* evcmpeq */
1620
DO_SPE_CMP(cmpeq);
1621
/* evcmpgts */
1622
DO_SPE_CMP(cmpgts);
1623
/* evcmpgtu */
1624
DO_SPE_CMP(cmpgtu);
1625
/* evcmplts */
1626
DO_SPE_CMP(cmplts);
1627
/* evcmpltu */
1628
DO_SPE_CMP(cmpltu);
1629

    
1630
/* Single precision floating-point conversions from/to integer */
1631
static always_inline uint32_t _do_efscfsi (int32_t val)
1632
{
1633
    union {
1634
        uint32_t u;
1635
        float32 f;
1636
    } u;
1637

    
1638
    u.f = int32_to_float32(val, &env->spe_status);
1639

    
1640
    return u.u;
1641
}
1642

    
1643
static always_inline uint32_t _do_efscfui (uint32_t val)
1644
{
1645
    union {
1646
        uint32_t u;
1647
        float32 f;
1648
    } u;
1649

    
1650
    u.f = uint32_to_float32(val, &env->spe_status);
1651

    
1652
    return u.u;
1653
}
1654

    
1655
static always_inline int32_t _do_efsctsi (uint32_t val)
1656
{
1657
    union {
1658
        int32_t u;
1659
        float32 f;
1660
    } u;
1661

    
1662
    u.u = val;
1663
    /* NaN are not treated the same way IEEE 754 does */
1664
    if (unlikely(isnan(u.f)))
1665
        return 0;
1666

    
1667
    return float32_to_int32(u.f, &env->spe_status);
1668
}
1669

    
1670
static always_inline uint32_t _do_efsctui (uint32_t val)
1671
{
1672
    union {
1673
        int32_t u;
1674
        float32 f;
1675
    } u;
1676

    
1677
    u.u = val;
1678
    /* NaN are not treated the same way IEEE 754 does */
1679
    if (unlikely(isnan(u.f)))
1680
        return 0;
1681

    
1682
    return float32_to_uint32(u.f, &env->spe_status);
1683
}
1684

    
1685
static always_inline int32_t _do_efsctsiz (uint32_t val)
1686
{
1687
    union {
1688
        int32_t u;
1689
        float32 f;
1690
    } u;
1691

    
1692
    u.u = val;
1693
    /* NaN are not treated the same way IEEE 754 does */
1694
    if (unlikely(isnan(u.f)))
1695
        return 0;
1696

    
1697
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1698
}
1699

    
1700
static always_inline uint32_t _do_efsctuiz (uint32_t val)
1701
{
1702
    union {
1703
        int32_t u;
1704
        float32 f;
1705
    } u;
1706

    
1707
    u.u = val;
1708
    /* NaN are not treated the same way IEEE 754 does */
1709
    if (unlikely(isnan(u.f)))
1710
        return 0;
1711

    
1712
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1713
}
1714

    
1715
void do_efscfsi (void)
1716
{
1717
    T0_64 = _do_efscfsi(T0_64);
1718
}
1719

    
1720
void do_efscfui (void)
1721
{
1722
    T0_64 = _do_efscfui(T0_64);
1723
}
1724

    
1725
void do_efsctsi (void)
1726
{
1727
    T0_64 = _do_efsctsi(T0_64);
1728
}
1729

    
1730
void do_efsctui (void)
1731
{
1732
    T0_64 = _do_efsctui(T0_64);
1733
}
1734

    
1735
void do_efsctsiz (void)
1736
{
1737
    T0_64 = _do_efsctsiz(T0_64);
1738
}
1739

    
1740
void do_efsctuiz (void)
1741
{
1742
    T0_64 = _do_efsctuiz(T0_64);
1743
}
1744

    
1745
/* Single precision floating-point conversion to/from fractional */
1746
static always_inline uint32_t _do_efscfsf (uint32_t val)
1747
{
1748
    union {
1749
        uint32_t u;
1750
        float32 f;
1751
    } u;
1752
    float32 tmp;
1753

    
1754
    u.f = int32_to_float32(val, &env->spe_status);
1755
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
1756
    u.f = float32_div(u.f, tmp, &env->spe_status);
1757

    
1758
    return u.u;
1759
}
1760

    
1761
static always_inline uint32_t _do_efscfuf (uint32_t val)
1762
{
1763
    union {
1764
        uint32_t u;
1765
        float32 f;
1766
    } u;
1767
    float32 tmp;
1768

    
1769
    u.f = uint32_to_float32(val, &env->spe_status);
1770
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1771
    u.f = float32_div(u.f, tmp, &env->spe_status);
1772

    
1773
    return u.u;
1774
}
1775

    
1776
static always_inline int32_t _do_efsctsf (uint32_t val)
1777
{
1778
    union {
1779
        int32_t u;
1780
        float32 f;
1781
    } u;
1782
    float32 tmp;
1783

    
1784
    u.u = val;
1785
    /* NaN are not treated the same way IEEE 754 does */
1786
    if (unlikely(isnan(u.f)))
1787
        return 0;
1788
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1789
    u.f = float32_mul(u.f, tmp, &env->spe_status);
1790

    
1791
    return float32_to_int32(u.f, &env->spe_status);
1792
}
1793

    
1794
static always_inline uint32_t _do_efsctuf (uint32_t val)
1795
{
1796
    union {
1797
        int32_t u;
1798
        float32 f;
1799
    } u;
1800
    float32 tmp;
1801

    
1802
    u.u = val;
1803
    /* NaN are not treated the same way IEEE 754 does */
1804
    if (unlikely(isnan(u.f)))
1805
        return 0;
1806
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1807
    u.f = float32_mul(u.f, tmp, &env->spe_status);
1808

    
1809
    return float32_to_uint32(u.f, &env->spe_status);
1810
}
1811

    
1812
static always_inline int32_t _do_efsctsfz (uint32_t val)
1813
{
1814
    union {
1815
        int32_t u;
1816
        float32 f;
1817
    } u;
1818
    float32 tmp;
1819

    
1820
    u.u = val;
1821
    /* NaN are not treated the same way IEEE 754 does */
1822
    if (unlikely(isnan(u.f)))
1823
        return 0;
1824
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1825
    u.f = float32_mul(u.f, tmp, &env->spe_status);
1826

    
1827
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1828
}
1829

    
1830
static always_inline uint32_t _do_efsctufz (uint32_t val)
1831
{
1832
    union {
1833
        int32_t u;
1834
        float32 f;
1835
    } u;
1836
    float32 tmp;
1837

    
1838
    u.u = val;
1839
    /* NaN are not treated the same way IEEE 754 does */
1840
    if (unlikely(isnan(u.f)))
1841
        return 0;
1842
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1843
    u.f = float32_mul(u.f, tmp, &env->spe_status);
1844

    
1845
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1846
}
1847

    
1848
void do_efscfsf (void)
1849
{
1850
    T0_64 = _do_efscfsf(T0_64);
1851
}
1852

    
1853
void do_efscfuf (void)
1854
{
1855
    T0_64 = _do_efscfuf(T0_64);
1856
}
1857

    
1858
void do_efsctsf (void)
1859
{
1860
    T0_64 = _do_efsctsf(T0_64);
1861
}
1862

    
1863
void do_efsctuf (void)
1864
{
1865
    T0_64 = _do_efsctuf(T0_64);
1866
}
1867

    
1868
void do_efsctsfz (void)
1869
{
1870
    T0_64 = _do_efsctsfz(T0_64);
1871
}
1872

    
1873
void do_efsctufz (void)
1874
{
1875
    T0_64 = _do_efsctufz(T0_64);
1876
}
1877

    
1878
/* Double precision floating point helpers */
1879
static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
1880
{
1881
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1882
    return _do_efdtstlt(op1, op2);
1883
}
1884

    
1885
static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
1886
{
1887
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1888
    return _do_efdtstgt(op1, op2);
1889
}
1890

    
1891
static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
1892
{
1893
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1894
    return _do_efdtsteq(op1, op2);
1895
}
1896

    
1897
void do_efdcmplt (void)
1898
{
1899
    T0 = _do_efdcmplt(T0_64, T1_64);
1900
}
1901

    
1902
void do_efdcmpgt (void)
1903
{
1904
    T0 = _do_efdcmpgt(T0_64, T1_64);
1905
}
1906

    
1907
void do_efdcmpeq (void)
1908
{
1909
    T0 = _do_efdcmpeq(T0_64, T1_64);
1910
}
1911

    
1912
/* Double precision floating-point conversion to/from integer */
1913
static always_inline uint64_t _do_efdcfsi (int64_t val)
1914
{
1915
    union {
1916
        uint64_t u;
1917
        float64 f;
1918
    } u;
1919

    
1920
    u.f = int64_to_float64(val, &env->spe_status);
1921

    
1922
    return u.u;
1923
}
1924

    
1925
static always_inline uint64_t _do_efdcfui (uint64_t val)
1926
{
1927
    union {
1928
        uint64_t u;
1929
        float64 f;
1930
    } u;
1931

    
1932
    u.f = uint64_to_float64(val, &env->spe_status);
1933

    
1934
    return u.u;
1935
}
1936

    
1937
static always_inline int64_t _do_efdctsi (uint64_t val)
1938
{
1939
    union {
1940
        int64_t u;
1941
        float64 f;
1942
    } u;
1943

    
1944
    u.u = val;
1945
    /* NaN are not treated the same way IEEE 754 does */
1946
    if (unlikely(isnan(u.f)))
1947
        return 0;
1948

    
1949
    return float64_to_int64(u.f, &env->spe_status);
1950
}
1951

    
1952
static always_inline uint64_t _do_efdctui (uint64_t val)
1953
{
1954
    union {
1955
        int64_t u;
1956
        float64 f;
1957
    } u;
1958

    
1959
    u.u = val;
1960
    /* NaN are not treated the same way IEEE 754 does */
1961
    if (unlikely(isnan(u.f)))
1962
        return 0;
1963

    
1964
    return float64_to_uint64(u.f, &env->spe_status);
1965
}
1966

    
1967
static always_inline int64_t _do_efdctsiz (uint64_t val)
1968
{
1969
    union {
1970
        int64_t u;
1971
        float64 f;
1972
    } u;
1973

    
1974
    u.u = val;
1975
    /* NaN are not treated the same way IEEE 754 does */
1976
    if (unlikely(isnan(u.f)))
1977
        return 0;
1978

    
1979
    return float64_to_int64_round_to_zero(u.f, &env->spe_status);
1980
}
1981

    
1982
static always_inline uint64_t _do_efdctuiz (uint64_t val)
1983
{
1984
    union {
1985
        int64_t u;
1986
        float64 f;
1987
    } u;
1988

    
1989
    u.u = val;
1990
    /* NaN are not treated the same way IEEE 754 does */
1991
    if (unlikely(isnan(u.f)))
1992
        return 0;
1993

    
1994
    return float64_to_uint64_round_to_zero(u.f, &env->spe_status);
1995
}
1996

    
1997
void do_efdcfsi (void)
1998
{
1999
    T0_64 = _do_efdcfsi(T0_64);
2000
}
2001

    
2002
void do_efdcfui (void)
2003
{
2004
    T0_64 = _do_efdcfui(T0_64);
2005
}
2006

    
2007
void do_efdctsi (void)
2008
{
2009
    T0_64 = _do_efdctsi(T0_64);
2010
}
2011

    
2012
void do_efdctui (void)
2013
{
2014
    T0_64 = _do_efdctui(T0_64);
2015
}
2016

    
2017
void do_efdctsiz (void)
2018
{
2019
    T0_64 = _do_efdctsiz(T0_64);
2020
}
2021

    
2022
void do_efdctuiz (void)
2023
{
2024
    T0_64 = _do_efdctuiz(T0_64);
2025
}
2026

    
2027
/* Double precision floating-point conversion to/from fractional */
2028
static always_inline uint64_t _do_efdcfsf (int64_t val)
2029
{
2030
    union {
2031
        uint64_t u;
2032
        float64 f;
2033
    } u;
2034
    float64 tmp;
2035

    
2036
    u.f = int32_to_float64(val, &env->spe_status);
2037
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2038
    u.f = float64_div(u.f, tmp, &env->spe_status);
2039

    
2040
    return u.u;
2041
}
2042

    
2043
static always_inline uint64_t _do_efdcfuf (uint64_t val)
2044
{
2045
    union {
2046
        uint64_t u;
2047
        float64 f;
2048
    } u;
2049
    float64 tmp;
2050

    
2051
    u.f = uint32_to_float64(val, &env->spe_status);
2052
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2053
    u.f = float64_div(u.f, tmp, &env->spe_status);
2054

    
2055
    return u.u;
2056
}
2057

    
2058
static always_inline int64_t _do_efdctsf (uint64_t val)
2059
{
2060
    union {
2061
        int64_t u;
2062
        float64 f;
2063
    } u;
2064
    float64 tmp;
2065

    
2066
    u.u = val;
2067
    /* NaN are not treated the same way IEEE 754 does */
2068
    if (unlikely(isnan(u.f)))
2069
        return 0;
2070
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2071
    u.f = float64_mul(u.f, tmp, &env->spe_status);
2072

    
2073
    return float64_to_int32(u.f, &env->spe_status);
2074
}
2075

    
2076
static always_inline uint64_t _do_efdctuf (uint64_t val)
2077
{
2078
    union {
2079
        int64_t u;
2080
        float64 f;
2081
    } u;
2082
    float64 tmp;
2083

    
2084
    u.u = val;
2085
    /* NaN are not treated the same way IEEE 754 does */
2086
    if (unlikely(isnan(u.f)))
2087
        return 0;
2088
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2089
    u.f = float64_mul(u.f, tmp, &env->spe_status);
2090

    
2091
    return float64_to_uint32(u.f, &env->spe_status);
2092
}
2093

    
2094
static always_inline int64_t _do_efdctsfz (uint64_t val)
2095
{
2096
    union {
2097
        int64_t u;
2098
        float64 f;
2099
    } u;
2100
    float64 tmp;
2101

    
2102
    u.u = val;
2103
    /* NaN are not treated the same way IEEE 754 does */
2104
    if (unlikely(isnan(u.f)))
2105
        return 0;
2106
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2107
    u.f = float64_mul(u.f, tmp, &env->spe_status);
2108

    
2109
    return float64_to_int32_round_to_zero(u.f, &env->spe_status);
2110
}
2111

    
2112
static always_inline uint64_t _do_efdctufz (uint64_t val)
2113
{
2114
    union {
2115
        int64_t u;
2116
        float64 f;
2117
    } u;
2118
    float64 tmp;
2119

    
2120
    u.u = val;
2121
    /* NaN are not treated the same way IEEE 754 does */
2122
    if (unlikely(isnan(u.f)))
2123
        return 0;
2124
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2125
    u.f = float64_mul(u.f, tmp, &env->spe_status);
2126

    
2127
    return float64_to_uint32_round_to_zero(u.f, &env->spe_status);
2128
}
2129

    
2130
void do_efdcfsf (void)
2131
{
2132
    T0_64 = _do_efdcfsf(T0_64);
2133
}
2134

    
2135
void do_efdcfuf (void)
2136
{
2137
    T0_64 = _do_efdcfuf(T0_64);
2138
}
2139

    
2140
void do_efdctsf (void)
2141
{
2142
    T0_64 = _do_efdctsf(T0_64);
2143
}
2144

    
2145
void do_efdctuf (void)
2146
{
2147
    T0_64 = _do_efdctuf(T0_64);
2148
}
2149

    
2150
void do_efdctsfz (void)
2151
{
2152
    T0_64 = _do_efdctsfz(T0_64);
2153
}
2154

    
2155
void do_efdctufz (void)
2156
{
2157
    T0_64 = _do_efdctufz(T0_64);
2158
}
2159

    
2160
/* Floating point conversion between single and double precision */
2161
static always_inline uint32_t _do_efscfd (uint64_t val)
2162
{
2163
    union {
2164
        uint64_t u;
2165
        float64 f;
2166
    } u1;
2167
    union {
2168
        uint32_t u;
2169
        float32 f;
2170
    } u2;
2171

    
2172
    u1.u = val;
2173
    u2.f = float64_to_float32(u1.f, &env->spe_status);
2174

    
2175
    return u2.u;
2176
}
2177

    
2178
static always_inline uint64_t _do_efdcfs (uint32_t val)
2179
{
2180
    union {
2181
        uint64_t u;
2182
        float64 f;
2183
    } u2;
2184
    union {
2185
        uint32_t u;
2186
        float32 f;
2187
    } u1;
2188

    
2189
    u1.u = val;
2190
    u2.f = float32_to_float64(u1.f, &env->spe_status);
2191

    
2192
    return u2.u;
2193
}
2194

    
2195
void do_efscfd (void)
2196
{
2197
    T0_64 = _do_efscfd(T0_64);
2198
}
2199

    
2200
void do_efdcfs (void)
2201
{
2202
    T0_64 = _do_efdcfs(T0_64);
2203
}
2204

    
2205
/* Single precision fixed-point vector arithmetic */
2206
/* evfsabs */
2207
DO_SPE_OP1(fsabs);
2208
/* evfsnabs */
2209
DO_SPE_OP1(fsnabs);
2210
/* evfsneg */
2211
DO_SPE_OP1(fsneg);
2212
/* evfsadd */
2213
DO_SPE_OP2(fsadd);
2214
/* evfssub */
2215
DO_SPE_OP2(fssub);
2216
/* evfsmul */
2217
DO_SPE_OP2(fsmul);
2218
/* evfsdiv */
2219
DO_SPE_OP2(fsdiv);
2220

    
2221
/* Single-precision floating-point comparisons */
2222
static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2223
{
2224
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2225
    return _do_efststlt(op1, op2);
2226
}
2227

    
2228
static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2229
{
2230
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2231
    return _do_efststgt(op1, op2);
2232
}
2233

    
2234
static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
2235
{
2236
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2237
    return _do_efststeq(op1, op2);
2238
}
2239

    
2240
void do_efscmplt (void)
2241
{
2242
    T0 = _do_efscmplt(T0_64, T1_64);
2243
}
2244

    
2245
void do_efscmpgt (void)
2246
{
2247
    T0 = _do_efscmpgt(T0_64, T1_64);
2248
}
2249

    
2250
void do_efscmpeq (void)
2251
{
2252
    T0 = _do_efscmpeq(T0_64, T1_64);
2253
}
2254

    
2255
/* Single-precision floating-point vector comparisons */
2256
/* evfscmplt */
2257
DO_SPE_CMP(fscmplt);
2258
/* evfscmpgt */
2259
DO_SPE_CMP(fscmpgt);
2260
/* evfscmpeq */
2261
DO_SPE_CMP(fscmpeq);
2262
/* evfststlt */
2263
DO_SPE_CMP(fststlt);
2264
/* evfststgt */
2265
DO_SPE_CMP(fststgt);
2266
/* evfststeq */
2267
DO_SPE_CMP(fststeq);
2268

    
2269
/* Single-precision floating-point vector conversions */
2270
/* evfscfsi */
2271
DO_SPE_OP1(fscfsi);
2272
/* evfscfui */
2273
DO_SPE_OP1(fscfui);
2274
/* evfscfuf */
2275
DO_SPE_OP1(fscfuf);
2276
/* evfscfsf */
2277
DO_SPE_OP1(fscfsf);
2278
/* evfsctsi */
2279
DO_SPE_OP1(fsctsi);
2280
/* evfsctui */
2281
DO_SPE_OP1(fsctui);
2282
/* evfsctsiz */
2283
DO_SPE_OP1(fsctsiz);
2284
/* evfsctuiz */
2285
DO_SPE_OP1(fsctuiz);
2286
/* evfsctsf */
2287
DO_SPE_OP1(fsctsf);
2288
/* evfsctuf */
2289
DO_SPE_OP1(fsctuf);
2290
#endif /* defined(TARGET_PPCEMB) */
2291

    
2292
/*****************************************************************************/
2293
/* Softmmu support */
2294
#if !defined (CONFIG_USER_ONLY)
2295

    
2296
#define MMUSUFFIX _mmu
2297
#define GETPC() (__builtin_return_address(0))
2298

    
2299
#define SHIFT 0
2300
#include "softmmu_template.h"
2301

    
2302
#define SHIFT 1
2303
#include "softmmu_template.h"
2304

    
2305
#define SHIFT 2
2306
#include "softmmu_template.h"
2307

    
2308
#define SHIFT 3
2309
#include "softmmu_template.h"
2310

    
2311
/* try to fill the TLB and return an exception if error. If retaddr is
2312
   NULL, it means that the function was called in C code (i.e. not
2313
   from generated code or from helper.c) */
2314
/* XXX: fix it to restore all registers */
2315
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2316
{
2317
    TranslationBlock *tb;
2318
    CPUState *saved_env;
2319
    target_phys_addr_t pc;
2320
    int ret;
2321

    
2322
    /* XXX: hack to restore env in all cases, even if not called from
2323
       generated code */
2324
    saved_env = env;
2325
    env = cpu_single_env;
2326
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2327
    if (unlikely(ret != 0)) {
2328
        if (likely(retaddr)) {
2329
            /* now we have a real cpu fault */
2330
            pc = (target_phys_addr_t)(unsigned long)retaddr;
2331
            tb = tb_find_pc(pc);
2332
            if (likely(tb)) {
2333
                /* the PC is inside the translated code. It means that we have
2334
                   a virtual CPU fault */
2335
                cpu_restore_state(tb, env, pc, NULL);
2336
            }
2337
        }
2338
        do_raise_exception_err(env->exception_index, env->error_code);
2339
    }
2340
    env = saved_env;
2341
}
2342

    
2343
/* Software driven TLBs management */
2344
/* PowerPC 602/603 software TLB load instructions helpers */
2345
void do_load_6xx_tlb (int is_code)
2346
{
2347
    target_ulong RPN, CMP, EPN;
2348
    int way;
2349

    
2350
    RPN = env->spr[SPR_RPA];
2351
    if (is_code) {
2352
        CMP = env->spr[SPR_ICMP];
2353
        EPN = env->spr[SPR_IMISS];
2354
    } else {
2355
        CMP = env->spr[SPR_DCMP];
2356
        EPN = env->spr[SPR_DMISS];
2357
    }
2358
    way = (env->spr[SPR_SRR1] >> 17) & 1;
2359
#if defined (DEBUG_SOFTWARE_TLB)
2360
    if (loglevel != 0) {
2361
        fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
2362
                __func__, (unsigned long)T0, (unsigned long)EPN,
2363
                (unsigned long)CMP, (unsigned long)RPN, way);
2364
    }
2365
#endif
2366
    /* Store this TLB */
2367
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2368
                     way, is_code, CMP, RPN);
2369
}
2370

    
2371
void do_load_74xx_tlb (int is_code)
2372
{
2373
    target_ulong RPN, CMP, EPN;
2374
    int way;
2375

    
2376
    RPN = env->spr[SPR_PTELO];
2377
    CMP = env->spr[SPR_PTEHI];
2378
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2379
    way = env->spr[SPR_TLBMISS] & 0x3;
2380
#if defined (DEBUG_SOFTWARE_TLB)
2381
    if (loglevel != 0) {
2382
        fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
2383
                __func__, (unsigned long)T0, (unsigned long)EPN,
2384
                (unsigned long)CMP, (unsigned long)RPN, way);
2385
    }
2386
#endif
2387
    /* Store this TLB */
2388
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2389
                     way, is_code, CMP, RPN);
2390
}
2391

    
2392
static target_ulong booke_tlb_to_page_size (int size)
2393
{
2394
    return 1024 << (2 * size);
2395
}
2396

    
2397
static int booke_page_size_to_tlb (target_ulong page_size)
2398
{
2399
    int size;
2400

    
2401
    switch (page_size) {
2402
    case 0x00000400UL:
2403
        size = 0x0;
2404
        break;
2405
    case 0x00001000UL:
2406
        size = 0x1;
2407
        break;
2408
    case 0x00004000UL:
2409
        size = 0x2;
2410
        break;
2411
    case 0x00010000UL:
2412
        size = 0x3;
2413
        break;
2414
    case 0x00040000UL:
2415
        size = 0x4;
2416
        break;
2417
    case 0x00100000UL:
2418
        size = 0x5;
2419
        break;
2420
    case 0x00400000UL:
2421
        size = 0x6;
2422
        break;
2423
    case 0x01000000UL:
2424
        size = 0x7;
2425
        break;
2426
    case 0x04000000UL:
2427
        size = 0x8;
2428
        break;
2429
    case 0x10000000UL:
2430
        size = 0x9;
2431
        break;
2432
    case 0x40000000UL:
2433
        size = 0xA;
2434
        break;
2435
#if defined (TARGET_PPC64)
2436
    case 0x000100000000ULL:
2437
        size = 0xB;
2438
        break;
2439
    case 0x000400000000ULL:
2440
        size = 0xC;
2441
        break;
2442
    case 0x001000000000ULL:
2443
        size = 0xD;
2444
        break;
2445
    case 0x004000000000ULL:
2446
        size = 0xE;
2447
        break;
2448
    case 0x010000000000ULL:
2449
        size = 0xF;
2450
        break;
2451
#endif
2452
    default:
2453
        size = -1;
2454
        break;
2455
    }
2456

    
2457
    return size;
2458
}
2459

    
2460
/* Helpers for 4xx TLB management */
2461
void do_4xx_tlbre_lo (void)
2462
{
2463
    ppcemb_tlb_t *tlb;
2464
    int size;
2465

    
2466
    T0 &= 0x3F;
2467
    tlb = &env->tlb[T0].tlbe;
2468
    T0 = tlb->EPN;
2469
    if (tlb->prot & PAGE_VALID)
2470
        T0 |= 0x400;
2471
    size = booke_page_size_to_tlb(tlb->size);
2472
    if (size < 0 || size > 0x7)
2473
        size = 1;
2474
    T0 |= size << 7;
2475
    env->spr[SPR_40x_PID] = tlb->PID;
2476
}
2477

    
2478
void do_4xx_tlbre_hi (void)
2479
{
2480
    ppcemb_tlb_t *tlb;
2481

    
2482
    T0 &= 0x3F;
2483
    tlb = &env->tlb[T0].tlbe;
2484
    T0 = tlb->RPN;
2485
    if (tlb->prot & PAGE_EXEC)
2486
        T0 |= 0x200;
2487
    if (tlb->prot & PAGE_WRITE)
2488
        T0 |= 0x100;
2489
}
2490

    
2491
void do_4xx_tlbwe_hi (void)
2492
{
2493
    ppcemb_tlb_t *tlb;
2494
    target_ulong page, end;
2495

    
2496
#if defined (DEBUG_SOFTWARE_TLB)
2497
    if (loglevel != 0) {
2498
        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2499
    }
2500
#endif
2501
    T0 &= 0x3F;
2502
    tlb = &env->tlb[T0].tlbe;
2503
    /* Invalidate previous TLB (if it's valid) */
2504
    if (tlb->prot & PAGE_VALID) {
2505
        end = tlb->EPN + tlb->size;
2506
#if defined (DEBUG_SOFTWARE_TLB)
2507
        if (loglevel != 0) {
2508
            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
2509
                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2510
        }
2511
#endif
2512
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2513
            tlb_flush_page(env, page);
2514
    }
2515
    tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
2516
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2517
     * If this ever occurs, one should use the ppcemb target instead
2518
     * of the ppc or ppc64 one
2519
     */
2520
    if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
2521
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2522
                  "are not supported (%d)\n",
2523
                  tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
2524
    }
2525
    tlb->EPN = T1 & ~(tlb->size - 1);
2526
    if (T1 & 0x40)
2527
        tlb->prot |= PAGE_VALID;
2528
    else
2529
        tlb->prot &= ~PAGE_VALID;
2530
    if (T1 & 0x20) {
2531
        /* XXX: TO BE FIXED */
2532
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
2533
    }
2534
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2535
    tlb->attr = T1 & 0xFF;
2536
#if defined (DEBUG_SOFTWARE_TLB)
2537
    if (loglevel != 0) {
2538
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2539
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2540
                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2541
                tlb->prot & PAGE_READ ? 'r' : '-',
2542
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2543
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2544
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2545
    }
2546
#endif
2547
    /* Invalidate new TLB (if valid) */
2548
    if (tlb->prot & PAGE_VALID) {
2549
        end = tlb->EPN + tlb->size;
2550
#if defined (DEBUG_SOFTWARE_TLB)
2551
        if (loglevel != 0) {
2552
            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
2553
                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2554
        }
2555
#endif
2556
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2557
            tlb_flush_page(env, page);
2558
    }
2559
}
2560

    
2561
void do_4xx_tlbwe_lo (void)
2562
{
2563
    ppcemb_tlb_t *tlb;
2564

    
2565
#if defined (DEBUG_SOFTWARE_TLB)
2566
    if (loglevel != 0) {
2567
        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2568
    }
2569
#endif
2570
    T0 &= 0x3F;
2571
    tlb = &env->tlb[T0].tlbe;
2572
    tlb->RPN = T1 & 0xFFFFFC00;
2573
    tlb->prot = PAGE_READ;
2574
    if (T1 & 0x200)
2575
        tlb->prot |= PAGE_EXEC;
2576
    if (T1 & 0x100)
2577
        tlb->prot |= PAGE_WRITE;
2578
#if defined (DEBUG_SOFTWARE_TLB)
2579
    if (loglevel != 0) {
2580
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2581
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2582
                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2583
                tlb->prot & PAGE_READ ? 'r' : '-',
2584
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2585
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2586
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2587
    }
2588
#endif
2589
}
2590

    
2591
/* PowerPC 440 TLB management */
2592
void do_440_tlbwe (int word)
2593
{
2594
    ppcemb_tlb_t *tlb;
2595
    target_ulong EPN, RPN, size;
2596
    int do_flush_tlbs;
2597

    
2598
#if defined (DEBUG_SOFTWARE_TLB)
2599
    if (loglevel != 0) {
2600
        fprintf(logfile, "%s word %d T0 " REGX " T1 " REGX "\n",
2601
                __func__, word, T0, T1);
2602
    }
2603
#endif
2604
    do_flush_tlbs = 0;
2605
    T0 &= 0x3F;
2606
    tlb = &env->tlb[T0].tlbe;
2607
    switch (word) {
2608
    default:
2609
        /* Just here to please gcc */
2610
    case 0:
2611
        EPN = T1 & 0xFFFFFC00;
2612
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2613
            do_flush_tlbs = 1;
2614
        tlb->EPN = EPN;
2615
        size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
2616
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2617
            do_flush_tlbs = 1;
2618
        tlb->size = size;
2619
        tlb->attr &= ~0x1;
2620
        tlb->attr |= (T1 >> 8) & 1;
2621
        if (T1 & 0x200) {
2622
            tlb->prot |= PAGE_VALID;
2623
        } else {
2624
            if (tlb->prot & PAGE_VALID) {
2625
                tlb->prot &= ~PAGE_VALID;
2626
                do_flush_tlbs = 1;
2627
            }
2628
        }
2629
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2630
        if (do_flush_tlbs)
2631
            tlb_flush(env, 1);
2632
        break;
2633
    case 1:
2634
        RPN = T1 & 0xFFFFFC0F;
2635
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
2636
            tlb_flush(env, 1);
2637
        tlb->RPN = RPN;
2638
        break;
2639
    case 2:
2640
        tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
2641
        tlb->prot = tlb->prot & PAGE_VALID;
2642
        if (T1 & 0x1)
2643
            tlb->prot |= PAGE_READ << 4;
2644
        if (T1 & 0x2)
2645
            tlb->prot |= PAGE_WRITE << 4;
2646
        if (T1 & 0x4)
2647
            tlb->prot |= PAGE_EXEC << 4;
2648
        if (T1 & 0x8)
2649
            tlb->prot |= PAGE_READ;
2650
        if (T1 & 0x10)
2651
            tlb->prot |= PAGE_WRITE;
2652
        if (T1 & 0x20)
2653
            tlb->prot |= PAGE_EXEC;
2654
        break;
2655
    }
2656
}
2657

    
2658
void do_440_tlbre (int word)
2659
{
2660
    ppcemb_tlb_t *tlb;
2661
    int size;
2662

    
2663
    T0 &= 0x3F;
2664
    tlb = &env->tlb[T0].tlbe;
2665
    switch (word) {
2666
    default:
2667
        /* Just here to please gcc */
2668
    case 0:
2669
        T0 = tlb->EPN;
2670
        size = booke_page_size_to_tlb(tlb->size);
2671
        if (size < 0 || size > 0xF)
2672
            size = 1;
2673
        T0 |= size << 4;
2674
        if (tlb->attr & 0x1)
2675
            T0 |= 0x100;
2676
        if (tlb->prot & PAGE_VALID)
2677
            T0 |= 0x200;
2678
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2679
        env->spr[SPR_440_MMUCR] |= tlb->PID;
2680
        break;
2681
    case 1:
2682
        T0 = tlb->RPN;
2683
        break;
2684
    case 2:
2685
        T0 = tlb->attr & ~0x1;
2686
        if (tlb->prot & (PAGE_READ << 4))
2687
            T0 |= 0x1;
2688
        if (tlb->prot & (PAGE_WRITE << 4))
2689
            T0 |= 0x2;
2690
        if (tlb->prot & (PAGE_EXEC << 4))
2691
            T0 |= 0x4;
2692
        if (tlb->prot & PAGE_READ)
2693
            T0 |= 0x8;
2694
        if (tlb->prot & PAGE_WRITE)
2695
            T0 |= 0x10;
2696
        if (tlb->prot & PAGE_EXEC)
2697
            T0 |= 0x20;
2698
        break;
2699
    }
2700
}
2701
#endif /* !CONFIG_USER_ONLY */