Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ b068d6a7

History | View | Annotate | Download (61.1 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
#endif
35

    
36
//#define DEBUG_OP
37
//#define DEBUG_EXCEPTIONS
38
//#define DEBUG_SOFTWARE_TLB
39

    
40
/*****************************************************************************/
41
/* Exceptions processing helpers */
42

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

    
61
void do_raise_exception (uint32_t exception)
62
{
63
    do_raise_exception_err(exception, 0);
64
}
65

    
66
void cpu_dump_EA (target_ulong EA);
67
void do_print_mem_EA (target_ulong EA)
68
{
69
    cpu_dump_EA(EA);
70
}
71

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

    
86
void do_store_cr (uint32_t mask)
87
{
88
    int i, sh;
89

    
90
    for (i = 0, sh = 7; i < 8; i++, sh--) {
91
        if (mask & (1 << sh))
92
            env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
93
    }
94
}
95

    
96
void do_load_xer (void)
97
{
98
    T0 = (xer_so << XER_SO) |
99
        (xer_ov << XER_OV) |
100
        (xer_ca << XER_CA) |
101
        (xer_bc << XER_BC) |
102
        (xer_cmp << XER_CMP);
103
}
104

    
105
void do_store_xer (void)
106
{
107
    xer_so = (T0 >> XER_SO) & 0x01;
108
    xer_ov = (T0 >> XER_OV) & 0x01;
109
    xer_ca = (T0 >> XER_CA) & 0x01;
110
    xer_cmp = (T0 >> XER_CMP) & 0xFF;
111
    xer_bc = (T0 >> XER_BC) & 0x7F;
112
}
113

    
114
#if defined(TARGET_PPC64)
115
void do_store_pri (int prio)
116
{
117
    env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
118
    env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
119
}
120
#endif
121

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

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

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

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

    
193
target_ulong ppc_load_dump_spr (int sprn)
194
{
195
    if (loglevel != 0) {
196
        fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
197
                sprn, sprn, env->spr[sprn]);
198
    }
199

    
200
    return env->spr[sprn];
201
}
202

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

    
212
/*****************************************************************************/
213
/* Fixed point operations helpers */
214
#if defined(TARGET_PPC64)
215
static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
216
{
217
    *plow += a;
218
    /* carry test */
219
    if (*plow < a)
220
        (*phigh)++;
221
    *phigh += b;
222
}
223

    
224
static void neg128 (uint64_t *plow, uint64_t *phigh)
225
{
226
    *plow = ~*plow;
227
    *phigh = ~*phigh;
228
    add128(plow, phigh, 1, 0);
229
}
230

    
231
static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
232
{
233
    uint32_t a0, a1, b0, b1;
234
    uint64_t v;
235

    
236
    a0 = a;
237
    a1 = a >> 32;
238

    
239
    b0 = b;
240
    b1 = b >> 32;
241

    
242
    v = (uint64_t)a0 * (uint64_t)b0;
243
    *plow = v;
244
    *phigh = 0;
245

    
246
    v = (uint64_t)a0 * (uint64_t)b1;
247
    add128(plow, phigh, v << 32, v >> 32);
248

    
249
    v = (uint64_t)a1 * (uint64_t)b0;
250
    add128(plow, phigh, v << 32, v >> 32);
251

    
252
    v = (uint64_t)a1 * (uint64_t)b1;
253
    *phigh += v;
254
#if defined(DEBUG_MULDIV)
255
    printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
256
           a, b, *phigh, *plow);
257
#endif
258
}
259

    
260
void do_mul64 (uint64_t *plow, uint64_t *phigh)
261
{
262
    mul64(plow, phigh, T0, T1);
263
}
264

    
265
static void imul64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
266
{
267
    int sa, sb;
268

    
269
    sa = (a < 0);
270
    if (sa)
271
        a = -a;
272
    sb = (b < 0);
273
    if (sb)
274
        b = -b;
275
    mul64(plow, phigh, a, b);
276
    if (sa ^ sb) {
277
        neg128(plow, phigh);
278
    }
279
}
280

    
281
void do_imul64 (uint64_t *plow, uint64_t *phigh)
282
{
283
    imul64(plow, phigh, T0, T1);
284
}
285
#endif
286

    
287
void do_adde (void)
288
{
289
    T2 = T0;
290
    T0 += T1 + xer_ca;
291
    if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
292
                 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
293
        xer_ca = 0;
294
    } else {
295
        xer_ca = 1;
296
    }
297
}
298

    
299
#if defined(TARGET_PPC64)
300
void do_adde_64 (void)
301
{
302
    T2 = T0;
303
    T0 += T1 + xer_ca;
304
    if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
305
                 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
306
        xer_ca = 0;
307
    } else {
308
        xer_ca = 1;
309
    }
310
}
311
#endif
312

    
313
void do_addmeo (void)
314
{
315
    T1 = T0;
316
    T0 += xer_ca + (-1);
317
    if (likely(!((uint32_t)T1 &
318
                 ((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) {
319
        xer_ov = 0;
320
    } else {
321
        xer_ov = 1;
322
        xer_so = 1;
323
    }
324
    if (likely(T1 != 0))
325
        xer_ca = 1;
326
}
327

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

    
345
void do_divwo (void)
346
{
347
    if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) ||
348
                 (int32_t)T1 == 0))) {
349
        xer_ov = 0;
350
        T0 = (int32_t)T0 / (int32_t)T1;
351
    } else {
352
        xer_ov = 1;
353
        xer_so = 1;
354
        T0 = (-1) * ((uint32_t)T0 >> 31);
355
    }
356
}
357

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

    
373
void do_divwuo (void)
374
{
375
    if (likely((uint32_t)T1 != 0)) {
376
        xer_ov = 0;
377
        T0 = (uint32_t)T0 / (uint32_t)T1;
378
    } else {
379
        xer_ov = 1;
380
        xer_so = 1;
381
        T0 = 0;
382
    }
383
}
384

    
385
#if defined(TARGET_PPC64)
386
void do_divduo (void)
387
{
388
    if (likely((uint64_t)T1 != 0)) {
389
        xer_ov = 0;
390
        T0 = (uint64_t)T0 / (uint64_t)T1;
391
    } else {
392
        xer_ov = 1;
393
        xer_so = 1;
394
        T0 = 0;
395
    }
396
}
397
#endif
398

    
399
void do_mullwo (void)
400
{
401
    int64_t res = (int64_t)T0 * (int64_t)T1;
402

    
403
    if (likely((int32_t)res == res)) {
404
        xer_ov = 0;
405
    } else {
406
        xer_ov = 1;
407
        xer_so = 1;
408
    }
409
    T0 = (int32_t)res;
410
}
411

    
412
#if defined(TARGET_PPC64)
413
void do_mulldo (void)
414
{
415
    int64_t th;
416
    uint64_t tl;
417

    
418
    do_imul64(&tl, &th);
419
    if (likely(th == 0)) {
420
        xer_ov = 0;
421
    } else {
422
        xer_ov = 1;
423
        xer_so = 1;
424
    }
425
    T0 = (int64_t)tl;
426
}
427
#endif
428

    
429
void do_nego (void)
430
{
431
    if (likely((int32_t)T0 != INT32_MIN)) {
432
        xer_ov = 0;
433
        T0 = -(int32_t)T0;
434
    } else {
435
        xer_ov = 1;
436
        xer_so = 1;
437
    }
438
}
439

    
440
#if defined(TARGET_PPC64)
441
void do_nego_64 (void)
442
{
443
    if (likely((int64_t)T0 != INT64_MIN)) {
444
        xer_ov = 0;
445
        T0 = -(int64_t)T0;
446
    } else {
447
        xer_ov = 1;
448
        xer_so = 1;
449
    }
450
}
451
#endif
452

    
453
void do_subfe (void)
454
{
455
    T0 = T1 + ~T0 + xer_ca;
456
    if (likely((uint32_t)T0 >= (uint32_t)T1 &&
457
               (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
458
        xer_ca = 0;
459
    } else {
460
        xer_ca = 1;
461
    }
462
}
463

    
464
#if defined(TARGET_PPC64)
465
void do_subfe_64 (void)
466
{
467
    T0 = T1 + ~T0 + xer_ca;
468
    if (likely((uint64_t)T0 >= (uint64_t)T1 &&
469
               (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
470
        xer_ca = 0;
471
    } else {
472
        xer_ca = 1;
473
    }
474
}
475
#endif
476

    
477
void do_subfmeo (void)
478
{
479
    T1 = T0;
480
    T0 = ~T0 + xer_ca - 1;
481
    if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) &
482
                 (1UL << 31)))) {
483
        xer_ov = 0;
484
    } else {
485
        xer_ov = 1;
486
        xer_so = 1;
487
    }
488
    if (likely((uint32_t)T1 != UINT32_MAX))
489
        xer_ca = 1;
490
}
491

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

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

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

    
547
/* shift right arithmetic helper */
548
void do_sraw (void)
549
{
550
    int32_t ret;
551

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

    
575
#if defined(TARGET_PPC64)
576
void do_srad (void)
577
{
578
    int64_t ret;
579

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

    
604
static always_inline int popcnt (uint32_t val)
605
{
606
    int i;
607

    
608
    for (i = 0; val != 0;)
609
        val = val ^ (val - 1);
610

    
611
    return i;
612
}
613

    
614
void do_popcntb (void)
615
{
616
    uint32_t ret;
617
    int i;
618

    
619
    ret = 0;
620
    for (i = 0; i < 32; i += 8)
621
        ret |= popcnt((T0 >> i) & 0xFF) << i;
622
    T0 = ret;
623
}
624

    
625
#if defined(TARGET_PPC64)
626
void do_popcntb_64 (void)
627
{
628
    uint64_t ret;
629
    int i;
630

    
631
    ret = 0;
632
    for (i = 0; i < 64; i += 8)
633
        ret |= popcnt((T0 >> i) & 0xFF) << i;
634
    T0 = ret;
635
}
636
#endif
637

    
638
/*****************************************************************************/
639
/* Floating point operations helpers */
640
void do_fctiw (void)
641
{
642
    union {
643
        double d;
644
        uint64_t i;
645
    } p;
646

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

    
657
void do_fctiwz (void)
658
{
659
    union {
660
        double d;
661
        uint64_t i;
662
    } p;
663

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

    
674
#if defined(TARGET_PPC64)
675
void do_fcfid (void)
676
{
677
    union {
678
        double d;
679
        uint64_t i;
680
    } p;
681

    
682
    p.d = FT0;
683
    FT0 = int64_to_float64(p.i, &env->fp_status);
684
}
685

    
686
void do_fctid (void)
687
{
688
    union {
689
        double d;
690
        uint64_t i;
691
    } p;
692

    
693
    p.i = float64_to_int64(FT0, &env->fp_status);
694
    FT0 = p.d;
695
}
696

    
697
void do_fctidz (void)
698
{
699
    union {
700
        double d;
701
        uint64_t i;
702
    } p;
703

    
704
    p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
705
    FT0 = p.d;
706
}
707

    
708
#endif
709

    
710
static always_inline void do_fri (int rounding_mode)
711
{
712
    int curmode;
713

    
714
    curmode = env->fp_status.float_rounding_mode;
715
    set_float_rounding_mode(rounding_mode, &env->fp_status);
716
    FT0 = float64_round_to_int(FT0, &env->fp_status);
717
    set_float_rounding_mode(curmode, &env->fp_status);
718
}
719

    
720
void do_frin (void)
721
{
722
    do_fri(float_round_nearest_even);
723
}
724

    
725
void do_friz (void)
726
{
727
    do_fri(float_round_to_zero);
728
}
729

    
730
void do_frip (void)
731
{
732
    do_fri(float_round_up);
733
}
734

    
735
void do_frim (void)
736
{
737
    do_fri(float_round_down);
738
}
739

    
740
#if USE_PRECISE_EMULATION
741
void do_fmadd (void)
742
{
743
#ifdef FLOAT128
744
    float128 ft0_128, ft1_128;
745

    
746
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
747
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
748
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
749
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
750
    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
751
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
752
#else
753
    /* This is OK on x86 hosts */
754
    FT0 = (FT0 * FT1) + FT2;
755
#endif
756
}
757

    
758
void do_fmsub (void)
759
{
760
#ifdef FLOAT128
761
    float128 ft0_128, ft1_128;
762

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

    
776
void do_fnmadd (void)
777
{
778
#if USE_PRECISE_EMULATION
779
#ifdef FLOAT128
780
    float128 ft0_128, ft1_128;
781

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

    
800
void do_fnmsub (void)
801
{
802
#if USE_PRECISE_EMULATION
803
#ifdef FLOAT128
804
    float128 ft0_128, ft1_128;
805

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

    
824
void do_fsqrt (void)
825
{
826
    FT0 = float64_sqrt(FT0, &env->fp_status);
827
}
828

    
829
void do_fre (void)
830
{
831
    union {
832
        double d;
833
        uint64_t i;
834
    } p;
835

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

    
855
void do_fres (void)
856
{
857
    union {
858
        double d;
859
        uint64_t i;
860
    } p;
861

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

    
886
void do_frsqrte (void)
887
{
888
    union {
889
        double d;
890
        uint64_t i;
891
    } p;
892

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

    
914
void do_fsel (void)
915
{
916
    if (FT0 >= 0)
917
        FT0 = FT1;
918
    else
919
        FT0 = FT2;
920
}
921

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

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

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

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

    
1022
void do_tw (int flags)
1023
{
1024
    if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
1025
                  ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
1026
                  ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
1027
                  ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
1028
                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
1029
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
1030
    }
1031
}
1032

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

    
1045
/*****************************************************************************/
1046
/* PowerPC 601 specific instructions (POWER bridge) */
1047
void do_POWER_abso (void)
1048
{
1049
    if ((uint32_t)T0 == INT32_MIN) {
1050
        T0 = INT32_MAX;
1051
        xer_ov = 1;
1052
        xer_so = 1;
1053
    } else {
1054
        T0 = -T0;
1055
        xer_ov = 0;
1056
    }
1057
}
1058

    
1059
void do_POWER_clcs (void)
1060
{
1061
    switch (T0) {
1062
    case 0x0CUL:
1063
        /* Instruction cache line size */
1064
        T0 = env->icache_line_size;
1065
        break;
1066
    case 0x0DUL:
1067
        /* Data cache line size */
1068
        T0 = env->dcache_line_size;
1069
        break;
1070
    case 0x0EUL:
1071
        /* Minimum cache line size */
1072
        T0 = env->icache_line_size < env->dcache_line_size ?
1073
            env->icache_line_size : env->dcache_line_size;
1074
        break;
1075
    case 0x0FUL:
1076
        /* Maximum 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
    default:
1081
        /* Undefined */
1082
        break;
1083
    }
1084
}
1085

    
1086
void do_POWER_div (void)
1087
{
1088
    uint64_t tmp;
1089

    
1090
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1091
        T0 = (long)((-1) * (T0 >> 31));
1092
        env->spr[SPR_MQ] = 0;
1093
    } else {
1094
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1095
        env->spr[SPR_MQ] = tmp % T1;
1096
        T0 = tmp / (int32_t)T1;
1097
    }
1098
}
1099

    
1100
void do_POWER_divo (void)
1101
{
1102
    int64_t tmp;
1103

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

    
1123
void do_POWER_divs (void)
1124
{
1125
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1126
        T0 = (long)((-1) * (T0 >> 31));
1127
        env->spr[SPR_MQ] = 0;
1128
    } else {
1129
        env->spr[SPR_MQ] = T0 % T1;
1130
        T0 = (int32_t)T0 / (int32_t)T1;
1131
    }
1132
}
1133

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

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

    
1166
void do_POWER_maskg (void)
1167
{
1168
    uint32_t ret;
1169

    
1170
    if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
1171
        ret = -1;
1172
    } else {
1173
        ret = (((uint32_t)(-1)) >> ((uint32_t)T0)) ^
1174
            (((uint32_t)(-1) >> ((uint32_t)T1)) >> 1);
1175
        if ((uint32_t)T0 > (uint32_t)T1)
1176
            ret = ~ret;
1177
    }
1178
    T0 = ret;
1179
}
1180

    
1181
void do_POWER_mulo (void)
1182
{
1183
    uint64_t tmp;
1184

    
1185
    tmp = (uint64_t)T0 * (uint64_t)T1;
1186
    env->spr[SPR_MQ] = tmp >> 32;
1187
    T0 = tmp;
1188
    if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
1189
        xer_ov = 1;
1190
        xer_so = 1;
1191
    } else {
1192
        xer_ov = 0;
1193
    }
1194
}
1195

    
1196
#if !defined (CONFIG_USER_ONLY)
1197
void do_POWER_rac (void)
1198
{
1199
#if 0
1200
    mmu_ctx_t ctx;
1201

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

    
1210
void do_POWER_rfsvc (void)
1211
{
1212
    env->nip = env->lr & ~0x00000003UL;
1213
    T0 = env->ctr & 0x0000FFFFUL;
1214
    do_store_msr(env, T0);
1215
#if defined (DEBUG_OP)
1216
    cpu_dump_rfi(env->nip, do_load_msr(env));
1217
#endif
1218
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1219
}
1220

    
1221
/* PowerPC 601 BAT management helper */
1222
void do_store_601_batu (int nr)
1223
{
1224
    do_store_ibatu(env, nr, (uint32_t)T0);
1225
    env->DBAT[0][nr] = env->IBAT[0][nr];
1226
    env->DBAT[1][nr] = env->IBAT[1][nr];
1227
}
1228
#endif
1229

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

    
1262
/*****************************************************************************/
1263
/* Embedded PowerPC specific helpers */
1264
void do_405_check_ov (void)
1265
{
1266
    if (likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1267
               !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1268
        xer_ov = 0;
1269
    } else {
1270
        xer_ov = 1;
1271
        xer_so = 1;
1272
    }
1273
}
1274

    
1275
void do_405_check_sat (void)
1276
{
1277
    if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1278
                !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1279
        /* Saturate result */
1280
        if (T2 >> 31) {
1281
            T0 = INT32_MIN;
1282
        } else {
1283
            T0 = INT32_MAX;
1284
        }
1285
    }
1286
}
1287

    
1288
/* XXX: to be improved to check access rights when in user-mode */
1289
void do_load_dcr (void)
1290
{
1291
    target_ulong val;
1292

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

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

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

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

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

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

    
1389
void do_load_403_pb (int num)
1390
{
1391
    T0 = env->pb[num];
1392
}
1393

    
1394
void do_store_403_pb (int num)
1395
{
1396
    if (likely(env->pb[num] != T0)) {
1397
        env->pb[num] = T0;
1398
        /* Should be optimized */
1399
        tlb_flush(env, 1);
1400
    }
1401
}
1402
#endif
1403

    
1404
/* 440 specific */
1405
void do_440_dlmzb (void)
1406
{
1407
    target_ulong mask;
1408
    int i;
1409

    
1410
    i = 1;
1411
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1412
        if ((T0 & mask) == 0)
1413
            goto done;
1414
        i++;
1415
    }
1416
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1417
        if ((T1 & mask) == 0)
1418
            break;
1419
        i++;
1420
    }
1421
 done:
1422
    T0 = i;
1423
}
1424

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

    
1433
static always_inline uint8_t byte_reverse (uint8_t val)
1434
{
1435
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1436
}
1437

    
1438
static always_inline uint32_t word_reverse (uint32_t val)
1439
{
1440
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1441
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1442
}
1443

    
1444
#define MASKBITS 16 // Random value - to be fixed
1445
void do_brinc (void)
1446
{
1447
    uint32_t a, b, d, mask;
1448

    
1449
    mask = (uint32_t)(-1UL) >> MASKBITS;
1450
    b = T1_64 & mask;
1451
    a = T0_64 & mask;
1452
    d = word_reverse(1 + word_reverse(a | ~mask));
1453
    T0_64 = (T0_64 & ~mask) | (d & mask);
1454
}
1455

    
1456
#define DO_SPE_OP2(name)                                                      \
1457
void do_ev##name (void)                                                       \
1458
{                                                                             \
1459
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) |         \
1460
        (uint64_t)_do_e##name(T0_64, T1_64);                                  \
1461
}
1462

    
1463
#define DO_SPE_OP1(name)                                                      \
1464
void do_ev##name (void)                                                       \
1465
{                                                                             \
1466
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) |                      \
1467
        (uint64_t)_do_e##name(T0_64);                                         \
1468
}
1469

    
1470
/* Fixed-point vector arithmetic */
1471
static always_inline uint32_t _do_eabs (uint32_t val)
1472
{
1473
    if (val != 0x80000000)
1474
        val &= ~0x80000000;
1475

    
1476
    return val;
1477
}
1478

    
1479
static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1480
{
1481
    return op1 + op2;
1482
}
1483

    
1484
static always_inline int _do_ecntlsw (uint32_t val)
1485
{
1486
    if (val & 0x80000000)
1487
        return _do_cntlzw(~val);
1488
    else
1489
        return _do_cntlzw(val);
1490
}
1491

    
1492
static always_inline int _do_ecntlzw (uint32_t val)
1493
{
1494
    return _do_cntlzw(val);
1495
}
1496

    
1497
static always_inline uint32_t _do_eneg (uint32_t val)
1498
{
1499
    if (val != 0x80000000)
1500
        val ^= 0x80000000;
1501

    
1502
    return val;
1503
}
1504

    
1505
static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1506
{
1507
    return rotl32(op1, op2);
1508
}
1509

    
1510
static always_inline uint32_t _do_erndw (uint32_t val)
1511
{
1512
    return (val + 0x000080000000) & 0xFFFF0000;
1513
}
1514

    
1515
static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1516
{
1517
    /* No error here: 6 bits are used */
1518
    return op1 << (op2 & 0x3F);
1519
}
1520

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

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

    
1533
static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1534
{
1535
    return op2 - op1;
1536
}
1537

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

    
1561
/* evsel is a little bit more complicated... */
1562
static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1563
{
1564
    if (n)
1565
        return op1;
1566
    else
1567
        return op2;
1568
}
1569

    
1570
void do_evsel (void)
1571
{
1572
    T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1573
        (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
1574
}
1575

    
1576
/* Fixed-point vector comparisons */
1577
#define DO_SPE_CMP(name)                                                      \
1578
void do_ev##name (void)                                                       \
1579
{                                                                             \
1580
    T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32,                   \
1581
                                               T1_64 >> 32) << 32,            \
1582
                         _do_e##name(T0_64, T1_64));                          \
1583
}
1584

    
1585
static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
1586
{
1587
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1588
}
1589
static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1590
{
1591
    return op1 == op2 ? 1 : 0;
1592
}
1593

    
1594
static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
1595
{
1596
    return op1 > op2 ? 1 : 0;
1597
}
1598

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

    
1604
static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
1605
{
1606
    return op1 < op2 ? 1 : 0;
1607
}
1608

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

    
1614
/* evcmpeq */
1615
DO_SPE_CMP(cmpeq);
1616
/* evcmpgts */
1617
DO_SPE_CMP(cmpgts);
1618
/* evcmpgtu */
1619
DO_SPE_CMP(cmpgtu);
1620
/* evcmplts */
1621
DO_SPE_CMP(cmplts);
1622
/* evcmpltu */
1623
DO_SPE_CMP(cmpltu);
1624

    
1625
/* Single precision floating-point conversions from/to integer */
1626
static always_inline uint32_t _do_efscfsi (int32_t val)
1627
{
1628
    union {
1629
        uint32_t u;
1630
        float32 f;
1631
    } u;
1632

    
1633
    u.f = int32_to_float32(val, &env->spe_status);
1634

    
1635
    return u.u;
1636
}
1637

    
1638
static always_inline uint32_t _do_efscfui (uint32_t val)
1639
{
1640
    union {
1641
        uint32_t u;
1642
        float32 f;
1643
    } u;
1644

    
1645
    u.f = uint32_to_float32(val, &env->spe_status);
1646

    
1647
    return u.u;
1648
}
1649

    
1650
static always_inline int32_t _do_efsctsi (uint32_t val)
1651
{
1652
    union {
1653
        int32_t u;
1654
        float32 f;
1655
    } u;
1656

    
1657
    u.u = val;
1658
    /* NaN are not treated the same way IEEE 754 does */
1659
    if (unlikely(isnan(u.f)))
1660
        return 0;
1661

    
1662
    return float32_to_int32(u.f, &env->spe_status);
1663
}
1664

    
1665
static always_inline uint32_t _do_efsctui (uint32_t val)
1666
{
1667
    union {
1668
        int32_t u;
1669
        float32 f;
1670
    } u;
1671

    
1672
    u.u = val;
1673
    /* NaN are not treated the same way IEEE 754 does */
1674
    if (unlikely(isnan(u.f)))
1675
        return 0;
1676

    
1677
    return float32_to_uint32(u.f, &env->spe_status);
1678
}
1679

    
1680
static always_inline int32_t _do_efsctsiz (uint32_t val)
1681
{
1682
    union {
1683
        int32_t u;
1684
        float32 f;
1685
    } u;
1686

    
1687
    u.u = val;
1688
    /* NaN are not treated the same way IEEE 754 does */
1689
    if (unlikely(isnan(u.f)))
1690
        return 0;
1691

    
1692
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1693
}
1694

    
1695
static always_inline uint32_t _do_efsctuiz (uint32_t val)
1696
{
1697
    union {
1698
        int32_t u;
1699
        float32 f;
1700
    } u;
1701

    
1702
    u.u = val;
1703
    /* NaN are not treated the same way IEEE 754 does */
1704
    if (unlikely(isnan(u.f)))
1705
        return 0;
1706

    
1707
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1708
}
1709

    
1710
void do_efscfsi (void)
1711
{
1712
    T0_64 = _do_efscfsi(T0_64);
1713
}
1714

    
1715
void do_efscfui (void)
1716
{
1717
    T0_64 = _do_efscfui(T0_64);
1718
}
1719

    
1720
void do_efsctsi (void)
1721
{
1722
    T0_64 = _do_efsctsi(T0_64);
1723
}
1724

    
1725
void do_efsctui (void)
1726
{
1727
    T0_64 = _do_efsctui(T0_64);
1728
}
1729

    
1730
void do_efsctsiz (void)
1731
{
1732
    T0_64 = _do_efsctsiz(T0_64);
1733
}
1734

    
1735
void do_efsctuiz (void)
1736
{
1737
    T0_64 = _do_efsctuiz(T0_64);
1738
}
1739

    
1740
/* Single precision floating-point conversion to/from fractional */
1741
static always_inline uint32_t _do_efscfsf (uint32_t val)
1742
{
1743
    union {
1744
        uint32_t u;
1745
        float32 f;
1746
    } u;
1747
    float32 tmp;
1748

    
1749
    u.f = int32_to_float32(val, &env->spe_status);
1750
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
1751
    u.f = float32_div(u.f, tmp, &env->spe_status);
1752

    
1753
    return u.u;
1754
}
1755

    
1756
static always_inline uint32_t _do_efscfuf (uint32_t val)
1757
{
1758
    union {
1759
        uint32_t u;
1760
        float32 f;
1761
    } u;
1762
    float32 tmp;
1763

    
1764
    u.f = uint32_to_float32(val, &env->spe_status);
1765
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1766
    u.f = float32_div(u.f, tmp, &env->spe_status);
1767

    
1768
    return u.u;
1769
}
1770

    
1771
static always_inline int32_t _do_efsctsf (uint32_t val)
1772
{
1773
    union {
1774
        int32_t u;
1775
        float32 f;
1776
    } u;
1777
    float32 tmp;
1778

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

    
1786
    return float32_to_int32(u.f, &env->spe_status);
1787
}
1788

    
1789
static always_inline uint32_t _do_efsctuf (uint32_t val)
1790
{
1791
    union {
1792
        int32_t u;
1793
        float32 f;
1794
    } u;
1795
    float32 tmp;
1796

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

    
1804
    return float32_to_uint32(u.f, &env->spe_status);
1805
}
1806

    
1807
static always_inline int32_t _do_efsctsfz (uint32_t val)
1808
{
1809
    union {
1810
        int32_t u;
1811
        float32 f;
1812
    } u;
1813
    float32 tmp;
1814

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

    
1822
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1823
}
1824

    
1825
static always_inline uint32_t _do_efsctufz (uint32_t val)
1826
{
1827
    union {
1828
        int32_t u;
1829
        float32 f;
1830
    } u;
1831
    float32 tmp;
1832

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

    
1840
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1841
}
1842

    
1843
void do_efscfsf (void)
1844
{
1845
    T0_64 = _do_efscfsf(T0_64);
1846
}
1847

    
1848
void do_efscfuf (void)
1849
{
1850
    T0_64 = _do_efscfuf(T0_64);
1851
}
1852

    
1853
void do_efsctsf (void)
1854
{
1855
    T0_64 = _do_efsctsf(T0_64);
1856
}
1857

    
1858
void do_efsctuf (void)
1859
{
1860
    T0_64 = _do_efsctuf(T0_64);
1861
}
1862

    
1863
void do_efsctsfz (void)
1864
{
1865
    T0_64 = _do_efsctsfz(T0_64);
1866
}
1867

    
1868
void do_efsctufz (void)
1869
{
1870
    T0_64 = _do_efsctufz(T0_64);
1871
}
1872

    
1873
/* Double precision floating point helpers */
1874
static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
1875
{
1876
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1877
    return _do_efdtstlt(op1, op2);
1878
}
1879

    
1880
static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
1881
{
1882
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1883
    return _do_efdtstgt(op1, op2);
1884
}
1885

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

    
1892
void do_efdcmplt (void)
1893
{
1894
    T0 = _do_efdcmplt(T0_64, T1_64);
1895
}
1896

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

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

    
1907
/* Double precision floating-point conversion to/from integer */
1908
static always_inline uint64_t _do_efdcfsi (int64_t val)
1909
{
1910
    union {
1911
        uint64_t u;
1912
        float64 f;
1913
    } u;
1914

    
1915
    u.f = int64_to_float64(val, &env->spe_status);
1916

    
1917
    return u.u;
1918
}
1919

    
1920
static always_inline uint64_t _do_efdcfui (uint64_t val)
1921
{
1922
    union {
1923
        uint64_t u;
1924
        float64 f;
1925
    } u;
1926

    
1927
    u.f = uint64_to_float64(val, &env->spe_status);
1928

    
1929
    return u.u;
1930
}
1931

    
1932
static always_inline int64_t _do_efdctsi (uint64_t val)
1933
{
1934
    union {
1935
        int64_t u;
1936
        float64 f;
1937
    } u;
1938

    
1939
    u.u = val;
1940
    /* NaN are not treated the same way IEEE 754 does */
1941
    if (unlikely(isnan(u.f)))
1942
        return 0;
1943

    
1944
    return float64_to_int64(u.f, &env->spe_status);
1945
}
1946

    
1947
static always_inline uint64_t _do_efdctui (uint64_t val)
1948
{
1949
    union {
1950
        int64_t u;
1951
        float64 f;
1952
    } u;
1953

    
1954
    u.u = val;
1955
    /* NaN are not treated the same way IEEE 754 does */
1956
    if (unlikely(isnan(u.f)))
1957
        return 0;
1958

    
1959
    return float64_to_uint64(u.f, &env->spe_status);
1960
}
1961

    
1962
static always_inline int64_t _do_efdctsiz (uint64_t val)
1963
{
1964
    union {
1965
        int64_t u;
1966
        float64 f;
1967
    } u;
1968

    
1969
    u.u = val;
1970
    /* NaN are not treated the same way IEEE 754 does */
1971
    if (unlikely(isnan(u.f)))
1972
        return 0;
1973

    
1974
    return float64_to_int64_round_to_zero(u.f, &env->spe_status);
1975
}
1976

    
1977
static always_inline uint64_t _do_efdctuiz (uint64_t val)
1978
{
1979
    union {
1980
        int64_t u;
1981
        float64 f;
1982
    } u;
1983

    
1984
    u.u = val;
1985
    /* NaN are not treated the same way IEEE 754 does */
1986
    if (unlikely(isnan(u.f)))
1987
        return 0;
1988

    
1989
    return float64_to_uint64_round_to_zero(u.f, &env->spe_status);
1990
}
1991

    
1992
void do_efdcfsi (void)
1993
{
1994
    T0_64 = _do_efdcfsi(T0_64);
1995
}
1996

    
1997
void do_efdcfui (void)
1998
{
1999
    T0_64 = _do_efdcfui(T0_64);
2000
}
2001

    
2002
void do_efdctsi (void)
2003
{
2004
    T0_64 = _do_efdctsi(T0_64);
2005
}
2006

    
2007
void do_efdctui (void)
2008
{
2009
    T0_64 = _do_efdctui(T0_64);
2010
}
2011

    
2012
void do_efdctsiz (void)
2013
{
2014
    T0_64 = _do_efdctsiz(T0_64);
2015
}
2016

    
2017
void do_efdctuiz (void)
2018
{
2019
    T0_64 = _do_efdctuiz(T0_64);
2020
}
2021

    
2022
/* Double precision floating-point conversion to/from fractional */
2023
static always_inline uint64_t _do_efdcfsf (int64_t val)
2024
{
2025
    union {
2026
        uint64_t u;
2027
        float64 f;
2028
    } u;
2029
    float64 tmp;
2030

    
2031
    u.f = int32_to_float64(val, &env->spe_status);
2032
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2033
    u.f = float64_div(u.f, tmp, &env->spe_status);
2034

    
2035
    return u.u;
2036
}
2037

    
2038
static always_inline uint64_t _do_efdcfuf (uint64_t val)
2039
{
2040
    union {
2041
        uint64_t u;
2042
        float64 f;
2043
    } u;
2044
    float64 tmp;
2045

    
2046
    u.f = uint32_to_float64(val, &env->spe_status);
2047
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2048
    u.f = float64_div(u.f, tmp, &env->spe_status);
2049

    
2050
    return u.u;
2051
}
2052

    
2053
static always_inline int64_t _do_efdctsf (uint64_t val)
2054
{
2055
    union {
2056
        int64_t u;
2057
        float64 f;
2058
    } u;
2059
    float64 tmp;
2060

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

    
2068
    return float64_to_int32(u.f, &env->spe_status);
2069
}
2070

    
2071
static always_inline uint64_t _do_efdctuf (uint64_t val)
2072
{
2073
    union {
2074
        int64_t u;
2075
        float64 f;
2076
    } u;
2077
    float64 tmp;
2078

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

    
2086
    return float64_to_uint32(u.f, &env->spe_status);
2087
}
2088

    
2089
static always_inline int64_t _do_efdctsfz (uint64_t val)
2090
{
2091
    union {
2092
        int64_t u;
2093
        float64 f;
2094
    } u;
2095
    float64 tmp;
2096

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

    
2104
    return float64_to_int32_round_to_zero(u.f, &env->spe_status);
2105
}
2106

    
2107
static always_inline uint64_t _do_efdctufz (uint64_t val)
2108
{
2109
    union {
2110
        int64_t u;
2111
        float64 f;
2112
    } u;
2113
    float64 tmp;
2114

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

    
2122
    return float64_to_uint32_round_to_zero(u.f, &env->spe_status);
2123
}
2124

    
2125
void do_efdcfsf (void)
2126
{
2127
    T0_64 = _do_efdcfsf(T0_64);
2128
}
2129

    
2130
void do_efdcfuf (void)
2131
{
2132
    T0_64 = _do_efdcfuf(T0_64);
2133
}
2134

    
2135
void do_efdctsf (void)
2136
{
2137
    T0_64 = _do_efdctsf(T0_64);
2138
}
2139

    
2140
void do_efdctuf (void)
2141
{
2142
    T0_64 = _do_efdctuf(T0_64);
2143
}
2144

    
2145
void do_efdctsfz (void)
2146
{
2147
    T0_64 = _do_efdctsfz(T0_64);
2148
}
2149

    
2150
void do_efdctufz (void)
2151
{
2152
    T0_64 = _do_efdctufz(T0_64);
2153
}
2154

    
2155
/* Floating point conversion between single and double precision */
2156
static always_inline uint32_t _do_efscfd (uint64_t val)
2157
{
2158
    union {
2159
        uint64_t u;
2160
        float64 f;
2161
    } u1;
2162
    union {
2163
        uint32_t u;
2164
        float32 f;
2165
    } u2;
2166

    
2167
    u1.u = val;
2168
    u2.f = float64_to_float32(u1.f, &env->spe_status);
2169

    
2170
    return u2.u;
2171
}
2172

    
2173
static always_inline uint64_t _do_efdcfs (uint32_t val)
2174
{
2175
    union {
2176
        uint64_t u;
2177
        float64 f;
2178
    } u2;
2179
    union {
2180
        uint32_t u;
2181
        float32 f;
2182
    } u1;
2183

    
2184
    u1.u = val;
2185
    u2.f = float32_to_float64(u1.f, &env->spe_status);
2186

    
2187
    return u2.u;
2188
}
2189

    
2190
void do_efscfd (void)
2191
{
2192
    T0_64 = _do_efscfd(T0_64);
2193
}
2194

    
2195
void do_efdcfs (void)
2196
{
2197
    T0_64 = _do_efdcfs(T0_64);
2198
}
2199

    
2200
/* Single precision fixed-point vector arithmetic */
2201
/* evfsabs */
2202
DO_SPE_OP1(fsabs);
2203
/* evfsnabs */
2204
DO_SPE_OP1(fsnabs);
2205
/* evfsneg */
2206
DO_SPE_OP1(fsneg);
2207
/* evfsadd */
2208
DO_SPE_OP2(fsadd);
2209
/* evfssub */
2210
DO_SPE_OP2(fssub);
2211
/* evfsmul */
2212
DO_SPE_OP2(fsmul);
2213
/* evfsdiv */
2214
DO_SPE_OP2(fsdiv);
2215

    
2216
/* Single-precision floating-point comparisons */
2217
static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2218
{
2219
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2220
    return _do_efststlt(op1, op2);
2221
}
2222

    
2223
static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2224
{
2225
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2226
    return _do_efststgt(op1, op2);
2227
}
2228

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

    
2235
void do_efscmplt (void)
2236
{
2237
    T0 = _do_efscmplt(T0_64, T1_64);
2238
}
2239

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

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

    
2250
/* Single-precision floating-point vector comparisons */
2251
/* evfscmplt */
2252
DO_SPE_CMP(fscmplt);
2253
/* evfscmpgt */
2254
DO_SPE_CMP(fscmpgt);
2255
/* evfscmpeq */
2256
DO_SPE_CMP(fscmpeq);
2257
/* evfststlt */
2258
DO_SPE_CMP(fststlt);
2259
/* evfststgt */
2260
DO_SPE_CMP(fststgt);
2261
/* evfststeq */
2262
DO_SPE_CMP(fststeq);
2263

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

    
2287
/*****************************************************************************/
2288
/* Softmmu support */
2289
#if !defined (CONFIG_USER_ONLY)
2290

    
2291
#define MMUSUFFIX _mmu
2292
#define GETPC() (__builtin_return_address(0))
2293

    
2294
#define SHIFT 0
2295
#include "softmmu_template.h"
2296

    
2297
#define SHIFT 1
2298
#include "softmmu_template.h"
2299

    
2300
#define SHIFT 2
2301
#include "softmmu_template.h"
2302

    
2303
#define SHIFT 3
2304
#include "softmmu_template.h"
2305

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

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

    
2338
/* Software driven TLBs management */
2339
/* PowerPC 602/603 software TLB load instructions helpers */
2340
void do_load_6xx_tlb (int is_code)
2341
{
2342
    target_ulong RPN, CMP, EPN;
2343
    int way;
2344

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

    
2366
void do_load_74xx_tlb (int is_code)
2367
{
2368
    target_ulong RPN, CMP, EPN;
2369
    int way;
2370

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

    
2387
static target_ulong booke_tlb_to_page_size (int size)
2388
{
2389
    return 1024 << (2 * size);
2390
}
2391

    
2392
static int booke_page_size_to_tlb (target_ulong page_size)
2393
{
2394
    int size;
2395

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

    
2452
    return size;
2453
}
2454

    
2455
/* Helpers for 4xx TLB management */
2456
void do_4xx_tlbre_lo (void)
2457
{
2458
    ppcemb_tlb_t *tlb;
2459
    int size;
2460

    
2461
    T0 &= 0x3F;
2462
    tlb = &env->tlb[T0].tlbe;
2463
    T0 = tlb->EPN;
2464
    if (tlb->prot & PAGE_VALID)
2465
        T0 |= 0x400;
2466
    size = booke_page_size_to_tlb(tlb->size);
2467
    if (size < 0 || size > 0x7)
2468
        size = 1;
2469
    T0 |= size << 7;
2470
    env->spr[SPR_40x_PID] = tlb->PID;
2471
}
2472

    
2473
void do_4xx_tlbre_hi (void)
2474
{
2475
    ppcemb_tlb_t *tlb;
2476

    
2477
    T0 &= 0x3F;
2478
    tlb = &env->tlb[T0].tlbe;
2479
    T0 = tlb->RPN;
2480
    if (tlb->prot & PAGE_EXEC)
2481
        T0 |= 0x200;
2482
    if (tlb->prot & PAGE_WRITE)
2483
        T0 |= 0x100;
2484
}
2485

    
2486
void do_4xx_tlbwe_hi (void)
2487
{
2488
    ppcemb_tlb_t *tlb;
2489
    target_ulong page, end;
2490

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

    
2556
void do_4xx_tlbwe_lo (void)
2557
{
2558
    ppcemb_tlb_t *tlb;
2559

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

    
2586
/* PowerPC 440 TLB management */
2587
void do_440_tlbwe (int word)
2588
{
2589
    ppcemb_tlb_t *tlb;
2590
    target_ulong EPN, RPN, size;
2591
    int do_flush_tlbs;
2592

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

    
2653
void do_440_tlbre (int word)
2654
{
2655
    ppcemb_tlb_t *tlb;
2656
    int size;
2657

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