Statistics
| Branch: | Revision:

root / target-ppc / op_helper.c @ 88ad920b

History | View | Annotate | Download (58.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 "helper_regs.h"
23
#include "op_helper.h"
24

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

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

    
46
/*****************************************************************************/
47
/* Exceptions processing helpers */
48

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

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

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

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

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

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

    
102
#if defined(TARGET_PPC64)
103
void do_store_pri (int prio)
104
{
105
    env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
106
    env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
107
}
108
#endif
109

    
110
void do_load_fpscr (void)
111
{
112
    /* The 32 MSB of the target fpr are undefined.
113
     * They'll be zero...
114
     */
115
    union {
116
        float64 d;
117
        struct {
118
            uint32_t u[2];
119
        } s;
120
    } u;
121
    int i;
122

    
123
#if defined(WORDS_BIGENDIAN)
124
#define WORD0 0
125
#define WORD1 1
126
#else
127
#define WORD0 1
128
#define WORD1 0
129
#endif
130
    u.s.u[WORD0] = 0;
131
    u.s.u[WORD1] = 0;
132
    for (i = 0; i < 8; i++)
133
        u.s.u[WORD1] |= env->fpscr[i] << (4 * i);
134
    FT0 = u.d;
135
}
136

    
137
void do_store_fpscr (uint32_t mask)
138
{
139
    /*
140
     * We use only the 32 LSB of the incoming fpr
141
     */
142
    union {
143
        double d;
144
        struct {
145
            uint32_t u[2];
146
        } s;
147
    } u;
148
    int i, rnd_type;
149

    
150
    u.d = FT0;
151
    if (mask & 0x80)
152
        env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);
153
    for (i = 1; i < 7; i++) {
154
        if (mask & (1 << (7 - i)))
155
            env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;
156
    }
157
    /* TODO: update FEX & VX */
158
    /* Set rounding mode */
159
    switch (env->fpscr[0] & 0x3) {
160
    case 0:
161
        /* Best approximation (round to nearest) */
162
        rnd_type = float_round_nearest_even;
163
        break;
164
    case 1:
165
        /* Smaller magnitude (round toward zero) */
166
        rnd_type = float_round_to_zero;
167
        break;
168
    case 2:
169
        /* Round toward +infinite */
170
        rnd_type = float_round_up;
171
        break;
172
    default:
173
    case 3:
174
        /* Round toward -infinite */
175
        rnd_type = float_round_down;
176
        break;
177
    }
178
    set_float_rounding_mode(rnd_type, &env->fp_status);
179
}
180

    
181
target_ulong ppc_load_dump_spr (int sprn)
182
{
183
    if (loglevel != 0) {
184
        fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
185
                sprn, sprn, env->spr[sprn]);
186
    }
187

    
188
    return env->spr[sprn];
189
}
190

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

    
200
/*****************************************************************************/
201
/* Fixed point operations helpers */
202
void do_adde (void)
203
{
204
    T2 = T0;
205
    T0 += T1 + xer_ca;
206
    if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
207
                 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
208
        xer_ca = 0;
209
    } else {
210
        xer_ca = 1;
211
    }
212
}
213

    
214
#if defined(TARGET_PPC64)
215
void do_adde_64 (void)
216
{
217
    T2 = T0;
218
    T0 += T1 + xer_ca;
219
    if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
220
                 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
221
        xer_ca = 0;
222
    } else {
223
        xer_ca = 1;
224
    }
225
}
226
#endif
227

    
228
void do_addmeo (void)
229
{
230
    T1 = T0;
231
    T0 += xer_ca + (-1);
232
    if (likely(!((uint32_t)T1 &
233
                 ((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) {
234
        xer_ov = 0;
235
    } else {
236
        xer_ov = 1;
237
        xer_so = 1;
238
    }
239
    if (likely(T1 != 0))
240
        xer_ca = 1;
241
}
242

    
243
#if defined(TARGET_PPC64)
244
void do_addmeo_64 (void)
245
{
246
    T1 = T0;
247
    T0 += xer_ca + (-1);
248
    if (likely(!((uint64_t)T1 &
249
                 ((uint64_t)T1 ^ (uint64_t)T0) & (1ULL << 63)))) {
250
        xer_ov = 0;
251
    } else {
252
        xer_ov = 1;
253
        xer_so = 1;
254
    }
255
    if (likely(T1 != 0))
256
        xer_ca = 1;
257
}
258
#endif
259

    
260
void do_divwo (void)
261
{
262
    if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) ||
263
                 (int32_t)T1 == 0))) {
264
        xer_ov = 0;
265
        T0 = (int32_t)T0 / (int32_t)T1;
266
    } else {
267
        xer_ov = 1;
268
        xer_so = 1;
269
        T0 = (-1) * ((uint32_t)T0 >> 31);
270
    }
271
}
272

    
273
#if defined(TARGET_PPC64)
274
void do_divdo (void)
275
{
276
    if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == -1ULL) ||
277
                 (int64_t)T1 == 0))) {
278
        xer_ov = 0;
279
        T0 = (int64_t)T0 / (int64_t)T1;
280
    } else {
281
        xer_ov = 1;
282
        xer_so = 1;
283
        T0 = (-1ULL) * ((uint64_t)T0 >> 63);
284
    }
285
}
286
#endif
287

    
288
void do_divwuo (void)
289
{
290
    if (likely((uint32_t)T1 != 0)) {
291
        xer_ov = 0;
292
        T0 = (uint32_t)T0 / (uint32_t)T1;
293
    } else {
294
        xer_ov = 1;
295
        xer_so = 1;
296
        T0 = 0;
297
    }
298
}
299

    
300
#if defined(TARGET_PPC64)
301
void do_divduo (void)
302
{
303
    if (likely((uint64_t)T1 != 0)) {
304
        xer_ov = 0;
305
        T0 = (uint64_t)T0 / (uint64_t)T1;
306
    } else {
307
        xer_ov = 1;
308
        xer_so = 1;
309
        T0 = 0;
310
    }
311
}
312
#endif
313

    
314
void do_mullwo (void)
315
{
316
    int64_t res = (int64_t)T0 * (int64_t)T1;
317

    
318
    if (likely((int32_t)res == res)) {
319
        xer_ov = 0;
320
    } else {
321
        xer_ov = 1;
322
        xer_so = 1;
323
    }
324
    T0 = (int32_t)res;
325
}
326

    
327
#if defined(TARGET_PPC64)
328
void do_mulldo (void)
329
{
330
    int64_t th;
331
    uint64_t tl;
332

    
333
    muls64(&tl, &th, T0, T1);
334
    /* If th != 0 && th != -1, then we had an overflow */
335
    if (likely((th + 1) <= 1)) {
336
        xer_ov = 0;
337
    } else {
338
        xer_ov = 1;
339
        xer_so = 1;
340
    }
341
    T0 = (int64_t)tl;
342
}
343
#endif
344

    
345
void do_nego (void)
346
{
347
    if (likely((int32_t)T0 != INT32_MIN)) {
348
        xer_ov = 0;
349
        T0 = -(int32_t)T0;
350
    } else {
351
        xer_ov = 1;
352
        xer_so = 1;
353
    }
354
}
355

    
356
#if defined(TARGET_PPC64)
357
void do_nego_64 (void)
358
{
359
    if (likely((int64_t)T0 != INT64_MIN)) {
360
        xer_ov = 0;
361
        T0 = -(int64_t)T0;
362
    } else {
363
        xer_ov = 1;
364
        xer_so = 1;
365
    }
366
}
367
#endif
368

    
369
void do_subfe (void)
370
{
371
    T0 = T1 + ~T0 + xer_ca;
372
    if (likely((uint32_t)T0 >= (uint32_t)T1 &&
373
               (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
374
        xer_ca = 0;
375
    } else {
376
        xer_ca = 1;
377
    }
378
}
379

    
380
#if defined(TARGET_PPC64)
381
void do_subfe_64 (void)
382
{
383
    T0 = T1 + ~T0 + xer_ca;
384
    if (likely((uint64_t)T0 >= (uint64_t)T1 &&
385
               (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
386
        xer_ca = 0;
387
    } else {
388
        xer_ca = 1;
389
    }
390
}
391
#endif
392

    
393
void do_subfmeo (void)
394
{
395
    T1 = T0;
396
    T0 = ~T0 + xer_ca - 1;
397
    if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) &
398
                 (1UL << 31)))) {
399
        xer_ov = 0;
400
    } else {
401
        xer_ov = 1;
402
        xer_so = 1;
403
    }
404
    if (likely((uint32_t)T1 != UINT32_MAX))
405
        xer_ca = 1;
406
}
407

    
408
#if defined(TARGET_PPC64)
409
void do_subfmeo_64 (void)
410
{
411
    T1 = T0;
412
    T0 = ~T0 + xer_ca - 1;
413
    if (likely(!((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0) &
414
                 (1ULL << 63)))) {
415
        xer_ov = 0;
416
    } else {
417
        xer_ov = 1;
418
        xer_so = 1;
419
    }
420
    if (likely((uint64_t)T1 != UINT64_MAX))
421
        xer_ca = 1;
422
}
423
#endif
424

    
425
void do_subfzeo (void)
426
{
427
    T1 = T0;
428
    T0 = ~T0 + xer_ca;
429
    if (likely(!(((uint32_t)~T1 ^ UINT32_MAX) &
430
                 ((uint32_t)(~T1) ^ (uint32_t)T0) & (1UL << 31)))) {
431
        xer_ov = 0;
432
    } else {
433
        xer_ov = 1;
434
        xer_so = 1;
435
    }
436
    if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
437
        xer_ca = 0;
438
    } else {
439
        xer_ca = 1;
440
    }
441
}
442

    
443
#if defined(TARGET_PPC64)
444
void do_subfzeo_64 (void)
445
{
446
    T1 = T0;
447
    T0 = ~T0 + xer_ca;
448
    if (likely(!(((uint64_t)~T1 ^ UINT64_MAX) &
449
                 ((uint64_t)(~T1) ^ (uint64_t)T0) & (1ULL << 63)))) {
450
        xer_ov = 0;
451
    } else {
452
        xer_ov = 1;
453
        xer_so = 1;
454
    }
455
    if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
456
        xer_ca = 0;
457
    } else {
458
        xer_ca = 1;
459
    }
460
}
461
#endif
462

    
463
/* shift right arithmetic helper */
464
void do_sraw (void)
465
{
466
    int32_t ret;
467

    
468
    if (likely(!(T1 & 0x20UL))) {
469
        if (likely((uint32_t)T1 != 0)) {
470
            ret = (int32_t)T0 >> (T1 & 0x1fUL);
471
            if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
472
                xer_ca = 0;
473
            } else {
474
                xer_ca = 1;
475
            }
476
        } else {
477
            ret = T0;
478
            xer_ca = 0;
479
        }
480
    } else {
481
        ret = (-1) * ((uint32_t)T0 >> 31);
482
        if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
483
            xer_ca = 0;
484
        } else {
485
            xer_ca = 1;
486
        }
487
    }
488
    T0 = ret;
489
}
490

    
491
#if defined(TARGET_PPC64)
492
void do_srad (void)
493
{
494
    int64_t ret;
495

    
496
    if (likely(!(T1 & 0x40UL))) {
497
        if (likely((uint64_t)T1 != 0)) {
498
            ret = (int64_t)T0 >> (T1 & 0x3FUL);
499
            if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
500
                xer_ca = 0;
501
            } else {
502
                xer_ca = 1;
503
            }
504
        } else {
505
            ret = T0;
506
            xer_ca = 0;
507
        }
508
    } else {
509
        ret = (-1) * ((uint64_t)T0 >> 63);
510
        if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
511
            xer_ca = 0;
512
        } else {
513
            xer_ca = 1;
514
        }
515
    }
516
    T0 = ret;
517
}
518
#endif
519

    
520
static always_inline int popcnt (uint32_t val)
521
{
522
    int i;
523

    
524
    for (i = 0; val != 0;)
525
        val = val ^ (val - 1);
526

    
527
    return i;
528
}
529

    
530
void do_popcntb (void)
531
{
532
    uint32_t ret;
533
    int i;
534

    
535
    ret = 0;
536
    for (i = 0; i < 32; i += 8)
537
        ret |= popcnt((T0 >> i) & 0xFF) << i;
538
    T0 = ret;
539
}
540

    
541
#if defined(TARGET_PPC64)
542
void do_popcntb_64 (void)
543
{
544
    uint64_t ret;
545
    int i;
546

    
547
    ret = 0;
548
    for (i = 0; i < 64; i += 8)
549
        ret |= popcnt((T0 >> i) & 0xFF) << i;
550
    T0 = ret;
551
}
552
#endif
553

    
554
/*****************************************************************************/
555
/* Floating point operations helpers */
556
void do_fctiw (void)
557
{
558
    union {
559
        double d;
560
        uint64_t i;
561
    } p;
562

    
563
    p.i = float64_to_int32(FT0, &env->fp_status);
564
#if USE_PRECISE_EMULATION
565
    /* XXX: higher bits are not supposed to be significant.
566
     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
567
     */
568
    p.i |= 0xFFF80000ULL << 32;
569
#endif
570
    FT0 = p.d;
571
}
572

    
573
void do_fctiwz (void)
574
{
575
    union {
576
        double d;
577
        uint64_t i;
578
    } p;
579

    
580
    p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
581
#if USE_PRECISE_EMULATION
582
    /* XXX: higher bits are not supposed to be significant.
583
     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
584
     */
585
    p.i |= 0xFFF80000ULL << 32;
586
#endif
587
    FT0 = p.d;
588
}
589

    
590
#if defined(TARGET_PPC64)
591
void do_fcfid (void)
592
{
593
    union {
594
        double d;
595
        uint64_t i;
596
    } p;
597

    
598
    p.d = FT0;
599
    FT0 = int64_to_float64(p.i, &env->fp_status);
600
}
601

    
602
void do_fctid (void)
603
{
604
    union {
605
        double d;
606
        uint64_t i;
607
    } p;
608

    
609
    p.i = float64_to_int64(FT0, &env->fp_status);
610
    FT0 = p.d;
611
}
612

    
613
void do_fctidz (void)
614
{
615
    union {
616
        double d;
617
        uint64_t i;
618
    } p;
619

    
620
    p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
621
    FT0 = p.d;
622
}
623

    
624
#endif
625

    
626
static always_inline void do_fri (int rounding_mode)
627
{
628
    int curmode;
629

    
630
    curmode = env->fp_status.float_rounding_mode;
631
    set_float_rounding_mode(rounding_mode, &env->fp_status);
632
    FT0 = float64_round_to_int(FT0, &env->fp_status);
633
    set_float_rounding_mode(curmode, &env->fp_status);
634
}
635

    
636
void do_frin (void)
637
{
638
    do_fri(float_round_nearest_even);
639
}
640

    
641
void do_friz (void)
642
{
643
    do_fri(float_round_to_zero);
644
}
645

    
646
void do_frip (void)
647
{
648
    do_fri(float_round_up);
649
}
650

    
651
void do_frim (void)
652
{
653
    do_fri(float_round_down);
654
}
655

    
656
#if USE_PRECISE_EMULATION
657
void do_fmadd (void)
658
{
659
#ifdef FLOAT128
660
    float128 ft0_128, ft1_128;
661

    
662
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
663
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
664
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
665
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
666
    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
667
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
668
#else
669
    /* This is OK on x86 hosts */
670
    FT0 = (FT0 * FT1) + FT2;
671
#endif
672
}
673

    
674
void do_fmsub (void)
675
{
676
#ifdef FLOAT128
677
    float128 ft0_128, ft1_128;
678

    
679
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
680
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
681
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
682
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
683
    ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
684
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
685
#else
686
    /* This is OK on x86 hosts */
687
    FT0 = (FT0 * FT1) - FT2;
688
#endif
689
}
690
#endif /* USE_PRECISE_EMULATION */
691

    
692
void do_fnmadd (void)
693
{
694
#if USE_PRECISE_EMULATION
695
#ifdef FLOAT128
696
    float128 ft0_128, ft1_128;
697

    
698
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
699
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
700
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
701
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
702
    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
703
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
704
#else
705
    /* This is OK on x86 hosts */
706
    FT0 = (FT0 * FT1) + FT2;
707
#endif
708
#else
709
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
710
    FT0 = float64_add(FT0, FT2, &env->fp_status);
711
#endif
712
    if (likely(!isnan(FT0)))
713
        FT0 = float64_chs(FT0);
714
}
715

    
716
void do_fnmsub (void)
717
{
718
#if USE_PRECISE_EMULATION
719
#ifdef FLOAT128
720
    float128 ft0_128, ft1_128;
721

    
722
    ft0_128 = float64_to_float128(FT0, &env->fp_status);
723
    ft1_128 = float64_to_float128(FT1, &env->fp_status);
724
    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
725
    ft1_128 = float64_to_float128(FT2, &env->fp_status);
726
    ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
727
    FT0 = float128_to_float64(ft0_128, &env->fp_status);
728
#else
729
    /* This is OK on x86 hosts */
730
    FT0 = (FT0 * FT1) - FT2;
731
#endif
732
#else
733
    FT0 = float64_mul(FT0, FT1, &env->fp_status);
734
    FT0 = float64_sub(FT0, FT2, &env->fp_status);
735
#endif
736
    if (likely(!isnan(FT0)))
737
        FT0 = float64_chs(FT0);
738
}
739

    
740
void do_fsqrt (void)
741
{
742
    FT0 = float64_sqrt(FT0, &env->fp_status);
743
}
744

    
745
void do_fre (void)
746
{
747
    union {
748
        double d;
749
        uint64_t i;
750
    } p;
751

    
752
    if (likely(isnormal(FT0))) {
753
        FT0 = float64_div(1.0, FT0, &env->fp_status);
754
    } else {
755
        p.d = FT0;
756
        if (p.i == 0x8000000000000000ULL) {
757
            p.i = 0xFFF0000000000000ULL;
758
        } else if (p.i == 0x0000000000000000ULL) {
759
            p.i = 0x7FF0000000000000ULL;
760
        } else if (isnan(FT0)) {
761
            p.i = 0x7FF8000000000000ULL;
762
        } else if (FT0 < 0.0) {
763
            p.i = 0x8000000000000000ULL;
764
        } else {
765
            p.i = 0x0000000000000000ULL;
766
        }
767
        FT0 = p.d;
768
    }
769
}
770

    
771
void do_fres (void)
772
{
773
    union {
774
        double d;
775
        uint64_t i;
776
    } p;
777

    
778
    if (likely(isnormal(FT0))) {
779
#if USE_PRECISE_EMULATION
780
        FT0 = float64_div(1.0, FT0, &env->fp_status);
781
        FT0 = float64_to_float32(FT0, &env->fp_status);
782
#else
783
        FT0 = float32_div(1.0, FT0, &env->fp_status);
784
#endif
785
    } else {
786
        p.d = FT0;
787
        if (p.i == 0x8000000000000000ULL) {
788
            p.i = 0xFFF0000000000000ULL;
789
        } else if (p.i == 0x0000000000000000ULL) {
790
            p.i = 0x7FF0000000000000ULL;
791
        } else if (isnan(FT0)) {
792
            p.i = 0x7FF8000000000000ULL;
793
        } else if (FT0 < 0.0) {
794
            p.i = 0x8000000000000000ULL;
795
        } else {
796
            p.i = 0x0000000000000000ULL;
797
        }
798
        FT0 = p.d;
799
    }
800
}
801

    
802
void do_frsqrte (void)
803
{
804
    union {
805
        double d;
806
        uint64_t i;
807
    } p;
808

    
809
    if (likely(isnormal(FT0) && FT0 > 0.0)) {
810
        FT0 = float64_sqrt(FT0, &env->fp_status);
811
        FT0 = float32_div(1.0, FT0, &env->fp_status);
812
    } else {
813
        p.d = FT0;
814
        if (p.i == 0x8000000000000000ULL) {
815
            p.i = 0xFFF0000000000000ULL;
816
        } else if (p.i == 0x0000000000000000ULL) {
817
            p.i = 0x7FF0000000000000ULL;
818
        } else if (isnan(FT0)) {
819
            if (!(p.i & 0x0008000000000000ULL))
820
                p.i |= 0x000FFFFFFFFFFFFFULL;
821
        } else if (FT0 < 0) {
822
            p.i = 0x7FF8000000000000ULL;
823
        } else {
824
            p.i = 0x0000000000000000ULL;
825
        }
826
        FT0 = p.d;
827
    }
828
}
829

    
830
void do_fsel (void)
831
{
832
    if (FT0 >= 0)
833
        FT0 = FT1;
834
    else
835
        FT0 = FT2;
836
}
837

    
838
void do_fcmpu (void)
839
{
840
    if (likely(!isnan(FT0) && !isnan(FT1))) {
841
        if (float64_lt(FT0, FT1, &env->fp_status)) {
842
            T0 = 0x08UL;
843
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
844
            T0 = 0x04UL;
845
        } else {
846
            T0 = 0x02UL;
847
        }
848
    } else {
849
        T0 = 0x01UL;
850
        env->fpscr[4] |= 0x1;
851
        env->fpscr[6] |= 0x1;
852
    }
853
    env->fpscr[3] = T0;
854
}
855

    
856
void do_fcmpo (void)
857
{
858
    env->fpscr[4] &= ~0x1;
859
    if (likely(!isnan(FT0) && !isnan(FT1))) {
860
        if (float64_lt(FT0, FT1, &env->fp_status)) {
861
            T0 = 0x08UL;
862
        } else if (!float64_le(FT0, FT1, &env->fp_status)) {
863
            T0 = 0x04UL;
864
        } else {
865
            T0 = 0x02UL;
866
        }
867
    } else {
868
        T0 = 0x01UL;
869
        env->fpscr[4] |= 0x1;
870
        if (!float64_is_signaling_nan(FT0) || !float64_is_signaling_nan(FT1)) {
871
            /* Quiet NaN case */
872
            env->fpscr[6] |= 0x1;
873
            if (!(env->fpscr[1] & 0x8))
874
                env->fpscr[4] |= 0x8;
875
        } else {
876
            env->fpscr[4] |= 0x8;
877
        }
878
    }
879
    env->fpscr[3] = T0;
880
}
881

    
882
#if !defined (CONFIG_USER_ONLY)
883
void cpu_dump_rfi (target_ulong RA, target_ulong msr);
884

    
885
void do_store_msr (void)
886
{
887
    T0 = hreg_store_msr(env, T0);
888
    if (T0 != 0) {
889
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
890
        do_raise_exception(T0);
891
    }
892
}
893

    
894
static always_inline void __do_rfi (target_ulong nip, target_ulong msr,
895
                                    target_ulong msrm, int keep_msrh)
896
{
897
#if defined(TARGET_PPC64)
898
    if (msr & (1ULL << MSR_SF)) {
899
        nip = (uint64_t)nip;
900
        msr &= (uint64_t)msrm;
901
    } else {
902
        nip = (uint32_t)nip;
903
        msr = (uint32_t)(msr & msrm);
904
        if (keep_msrh)
905
            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
906
    }
907
#else
908
    nip = (uint32_t)nip;
909
    msr &= (uint32_t)msrm;
910
#endif
911
    /* XXX: beware: this is false if VLE is supported */
912
    env->nip = nip & ~((target_ulong)0x00000003);
913
    hreg_store_msr(env, msr);
914
#if defined (DEBUG_OP)
915
    cpu_dump_rfi(env->nip, env->msr);
916
#endif
917
    /* No need to raise an exception here,
918
     * as rfi is always the last insn of a TB
919
     */
920
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
921
}
922

    
923
void do_rfi (void)
924
{
925
    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
926
             ~((target_ulong)0xFFFF0000), 1);
927
}
928

    
929
#if defined(TARGET_PPC64)
930
void do_rfid (void)
931
{
932
    __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
933
             ~((target_ulong)0xFFFF0000), 0);
934
}
935
#endif
936
#if defined(TARGET_PPC64H)
937
void do_hrfid (void)
938
{
939
    __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
940
             ~((target_ulong)0xFFFF0000), 0);
941
}
942
#endif
943
#endif
944

    
945
void do_tw (int flags)
946
{
947
    if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
948
                  ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
949
                  ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
950
                  ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
951
                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
952
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
953
    }
954
}
955

    
956
#if defined(TARGET_PPC64)
957
void do_td (int flags)
958
{
959
    if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
960
                  ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
961
                  ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
962
                  ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
963
                  ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
964
        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
965
}
966
#endif
967

    
968
/*****************************************************************************/
969
/* PowerPC 601 specific instructions (POWER bridge) */
970
void do_POWER_abso (void)
971
{
972
    if ((uint32_t)T0 == INT32_MIN) {
973
        T0 = INT32_MAX;
974
        xer_ov = 1;
975
        xer_so = 1;
976
    } else {
977
        T0 = -T0;
978
        xer_ov = 0;
979
    }
980
}
981

    
982
void do_POWER_clcs (void)
983
{
984
    switch (T0) {
985
    case 0x0CUL:
986
        /* Instruction cache line size */
987
        T0 = env->icache_line_size;
988
        break;
989
    case 0x0DUL:
990
        /* Data cache line size */
991
        T0 = env->dcache_line_size;
992
        break;
993
    case 0x0EUL:
994
        /* Minimum cache line size */
995
        T0 = env->icache_line_size < env->dcache_line_size ?
996
            env->icache_line_size : env->dcache_line_size;
997
        break;
998
    case 0x0FUL:
999
        /* Maximum cache line size */
1000
        T0 = env->icache_line_size > env->dcache_line_size ?
1001
            env->icache_line_size : env->dcache_line_size;
1002
        break;
1003
    default:
1004
        /* Undefined */
1005
        break;
1006
    }
1007
}
1008

    
1009
void do_POWER_div (void)
1010
{
1011
    uint64_t tmp;
1012

    
1013
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1014
        T0 = (long)((-1) * (T0 >> 31));
1015
        env->spr[SPR_MQ] = 0;
1016
    } else {
1017
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1018
        env->spr[SPR_MQ] = tmp % T1;
1019
        T0 = tmp / (int32_t)T1;
1020
    }
1021
}
1022

    
1023
void do_POWER_divo (void)
1024
{
1025
    int64_t tmp;
1026

    
1027
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1028
        T0 = (long)((-1) * (T0 >> 31));
1029
        env->spr[SPR_MQ] = 0;
1030
        xer_ov = 1;
1031
        xer_so = 1;
1032
    } else {
1033
        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
1034
        env->spr[SPR_MQ] = tmp % T1;
1035
        tmp /= (int32_t)T1;
1036
        if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
1037
            xer_ov = 1;
1038
            xer_so = 1;
1039
        } else {
1040
            xer_ov = 0;
1041
        }
1042
        T0 = tmp;
1043
    }
1044
}
1045

    
1046
void do_POWER_divs (void)
1047
{
1048
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1049
        T0 = (long)((-1) * (T0 >> 31));
1050
        env->spr[SPR_MQ] = 0;
1051
    } else {
1052
        env->spr[SPR_MQ] = T0 % T1;
1053
        T0 = (int32_t)T0 / (int32_t)T1;
1054
    }
1055
}
1056

    
1057
void do_POWER_divso (void)
1058
{
1059
    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
1060
        T0 = (long)((-1) * (T0 >> 31));
1061
        env->spr[SPR_MQ] = 0;
1062
        xer_ov = 1;
1063
        xer_so = 1;
1064
    } else {
1065
        T0 = (int32_t)T0 / (int32_t)T1;
1066
        env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
1067
        xer_ov = 0;
1068
    }
1069
}
1070

    
1071
void do_POWER_dozo (void)
1072
{
1073
    if ((int32_t)T1 > (int32_t)T0) {
1074
        T2 = T0;
1075
        T0 = T1 - T0;
1076
        if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
1077
            ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
1078
            xer_ov = 1;
1079
            xer_so = 1;
1080
        } else {
1081
            xer_ov = 0;
1082
        }
1083
    } else {
1084
        T0 = 0;
1085
        xer_ov = 0;
1086
    }
1087
}
1088

    
1089
void do_POWER_maskg (void)
1090
{
1091
    uint32_t ret;
1092

    
1093
    if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
1094
        ret = -1;
1095
    } else {
1096
        ret = (((uint32_t)(-1)) >> ((uint32_t)T0)) ^
1097
            (((uint32_t)(-1) >> ((uint32_t)T1)) >> 1);
1098
        if ((uint32_t)T0 > (uint32_t)T1)
1099
            ret = ~ret;
1100
    }
1101
    T0 = ret;
1102
}
1103

    
1104
void do_POWER_mulo (void)
1105
{
1106
    uint64_t tmp;
1107

    
1108
    tmp = (uint64_t)T0 * (uint64_t)T1;
1109
    env->spr[SPR_MQ] = tmp >> 32;
1110
    T0 = tmp;
1111
    if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
1112
        xer_ov = 1;
1113
        xer_so = 1;
1114
    } else {
1115
        xer_ov = 0;
1116
    }
1117
}
1118

    
1119
#if !defined (CONFIG_USER_ONLY)
1120
void do_POWER_rac (void)
1121
{
1122
#if 0
1123
    mmu_ctx_t ctx;
1124

1125
    /* We don't have to generate many instances of this instruction,
1126
     * as rac is supervisor only.
1127
     */
1128
    if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT, 1) == 0)
1129
        T0 = ctx.raddr;
1130
#endif
1131
}
1132

    
1133
void do_POWER_rfsvc (void)
1134
{
1135
    __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
1136
}
1137

    
1138
/* PowerPC 601 BAT management helper */
1139
void do_store_601_batu (int nr)
1140
{
1141
    do_store_ibatu(env, nr, (uint32_t)T0);
1142
    env->DBAT[0][nr] = env->IBAT[0][nr];
1143
    env->DBAT[1][nr] = env->IBAT[1][nr];
1144
}
1145
#endif
1146

    
1147
/*****************************************************************************/
1148
/* 602 specific instructions */
1149
/* mfrom is the most crazy instruction ever seen, imho ! */
1150
/* Real implementation uses a ROM table. Do the same */
1151
#define USE_MFROM_ROM_TABLE
1152
void do_op_602_mfrom (void)
1153
{
1154
    if (likely(T0 < 602)) {
1155
#if defined(USE_MFROM_ROM_TABLE)
1156
#include "mfrom_table.c"
1157
        T0 = mfrom_ROM_table[T0];
1158
#else
1159
        double d;
1160
        /* Extremly decomposed:
1161
         *                    -T0 / 256
1162
         * T0 = 256 * log10(10          + 1.0) + 0.5
1163
         */
1164
        d = T0;
1165
        d = float64_div(d, 256, &env->fp_status);
1166
        d = float64_chs(d);
1167
        d = exp10(d); // XXX: use float emulation function
1168
        d = float64_add(d, 1.0, &env->fp_status);
1169
        d = log10(d); // XXX: use float emulation function
1170
        d = float64_mul(d, 256, &env->fp_status);
1171
        d = float64_add(d, 0.5, &env->fp_status);
1172
        T0 = float64_round_to_int(d, &env->fp_status);
1173
#endif
1174
    } else {
1175
        T0 = 0;
1176
    }
1177
}
1178

    
1179
/*****************************************************************************/
1180
/* Embedded PowerPC specific helpers */
1181
void do_405_check_ov (void)
1182
{
1183
    if (likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1184
               !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1185
        xer_ov = 0;
1186
    } else {
1187
        xer_ov = 1;
1188
        xer_so = 1;
1189
    }
1190
}
1191

    
1192
void do_405_check_sat (void)
1193
{
1194
    if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1195
                !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1196
        /* Saturate result */
1197
        if (T2 >> 31) {
1198
            T0 = INT32_MIN;
1199
        } else {
1200
            T0 = INT32_MAX;
1201
        }
1202
    }
1203
}
1204

    
1205
/* XXX: to be improved to check access rights when in user-mode */
1206
void do_load_dcr (void)
1207
{
1208
    target_ulong val;
1209

    
1210
    if (unlikely(env->dcr_env == NULL)) {
1211
        if (loglevel != 0) {
1212
            fprintf(logfile, "No DCR environment\n");
1213
        }
1214
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1215
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1216
    } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
1217
        if (loglevel != 0) {
1218
            fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
1219
        }
1220
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1221
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1222
    } else {
1223
        T0 = val;
1224
    }
1225
}
1226

    
1227
void do_store_dcr (void)
1228
{
1229
    if (unlikely(env->dcr_env == NULL)) {
1230
        if (loglevel != 0) {
1231
            fprintf(logfile, "No DCR environment\n");
1232
        }
1233
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1234
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1235
    } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
1236
        if (loglevel != 0) {
1237
            fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
1238
        }
1239
        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1240
                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1241
    }
1242
}
1243

    
1244
#if !defined(CONFIG_USER_ONLY)
1245
void do_40x_rfci (void)
1246
{
1247
    __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1248
             ~((target_ulong)0xFFFF0000), 0);
1249
}
1250

    
1251
void do_rfci (void)
1252
{
1253
    __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1254
             ~((target_ulong)0x3FFF0000), 0);
1255
}
1256

    
1257
void do_rfdi (void)
1258
{
1259
    __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1260
             ~((target_ulong)0x3FFF0000), 0);
1261
}
1262

    
1263
void do_rfmci (void)
1264
{
1265
    __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1266
             ~((target_ulong)0x3FFF0000), 0);
1267
}
1268

    
1269
void do_load_403_pb (int num)
1270
{
1271
    T0 = env->pb[num];
1272
}
1273

    
1274
void do_store_403_pb (int num)
1275
{
1276
    if (likely(env->pb[num] != T0)) {
1277
        env->pb[num] = T0;
1278
        /* Should be optimized */
1279
        tlb_flush(env, 1);
1280
    }
1281
}
1282
#endif
1283

    
1284
/* 440 specific */
1285
void do_440_dlmzb (void)
1286
{
1287
    target_ulong mask;
1288
    int i;
1289

    
1290
    i = 1;
1291
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1292
        if ((T0 & mask) == 0)
1293
            goto done;
1294
        i++;
1295
    }
1296
    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1297
        if ((T1 & mask) == 0)
1298
            break;
1299
        i++;
1300
    }
1301
 done:
1302
    T0 = i;
1303
}
1304

    
1305
#if defined(TARGET_PPCEMB)
1306
/* SPE extension helpers */
1307
/* Use a table to make this quicker */
1308
static uint8_t hbrev[16] = {
1309
    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
1310
    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
1311
};
1312

    
1313
static always_inline uint8_t byte_reverse (uint8_t val)
1314
{
1315
    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
1316
}
1317

    
1318
static always_inline uint32_t word_reverse (uint32_t val)
1319
{
1320
    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
1321
        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
1322
}
1323

    
1324
#define MASKBITS 16 // Random value - to be fixed
1325
void do_brinc (void)
1326
{
1327
    uint32_t a, b, d, mask;
1328

    
1329
    mask = (uint32_t)(-1UL) >> MASKBITS;
1330
    b = T1_64 & mask;
1331
    a = T0_64 & mask;
1332
    d = word_reverse(1 + word_reverse(a | ~mask));
1333
    T0_64 = (T0_64 & ~mask) | (d & mask);
1334
}
1335

    
1336
#define DO_SPE_OP2(name)                                                      \
1337
void do_ev##name (void)                                                       \
1338
{                                                                             \
1339
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) |         \
1340
        (uint64_t)_do_e##name(T0_64, T1_64);                                  \
1341
}
1342

    
1343
#define DO_SPE_OP1(name)                                                      \
1344
void do_ev##name (void)                                                       \
1345
{                                                                             \
1346
    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) |                      \
1347
        (uint64_t)_do_e##name(T0_64);                                         \
1348
}
1349

    
1350
/* Fixed-point vector arithmetic */
1351
static always_inline uint32_t _do_eabs (uint32_t val)
1352
{
1353
    if (val != 0x80000000)
1354
        val &= ~0x80000000;
1355

    
1356
    return val;
1357
}
1358

    
1359
static always_inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
1360
{
1361
    return op1 + op2;
1362
}
1363

    
1364
static always_inline int _do_ecntlsw (uint32_t val)
1365
{
1366
    if (val & 0x80000000)
1367
        return _do_cntlzw(~val);
1368
    else
1369
        return _do_cntlzw(val);
1370
}
1371

    
1372
static always_inline int _do_ecntlzw (uint32_t val)
1373
{
1374
    return _do_cntlzw(val);
1375
}
1376

    
1377
static always_inline uint32_t _do_eneg (uint32_t val)
1378
{
1379
    if (val != 0x80000000)
1380
        val ^= 0x80000000;
1381

    
1382
    return val;
1383
}
1384

    
1385
static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1386
{
1387
    return rotl32(op1, op2);
1388
}
1389

    
1390
static always_inline uint32_t _do_erndw (uint32_t val)
1391
{
1392
    return (val + 0x000080000000) & 0xFFFF0000;
1393
}
1394

    
1395
static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1396
{
1397
    /* No error here: 6 bits are used */
1398
    return op1 << (op2 & 0x3F);
1399
}
1400

    
1401
static always_inline int32_t _do_esrws (int32_t op1, uint32_t op2)
1402
{
1403
    /* No error here: 6 bits are used */
1404
    return op1 >> (op2 & 0x3F);
1405
}
1406

    
1407
static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1408
{
1409
    /* No error here: 6 bits are used */
1410
    return op1 >> (op2 & 0x3F);
1411
}
1412

    
1413
static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1414
{
1415
    return op2 - op1;
1416
}
1417

    
1418
/* evabs */
1419
DO_SPE_OP1(abs);
1420
/* evaddw */
1421
DO_SPE_OP2(addw);
1422
/* evcntlsw */
1423
DO_SPE_OP1(cntlsw);
1424
/* evcntlzw */
1425
DO_SPE_OP1(cntlzw);
1426
/* evneg */
1427
DO_SPE_OP1(neg);
1428
/* evrlw */
1429
DO_SPE_OP2(rlw);
1430
/* evrnd */
1431
DO_SPE_OP1(rndw);
1432
/* evslw */
1433
DO_SPE_OP2(slw);
1434
/* evsrws */
1435
DO_SPE_OP2(srws);
1436
/* evsrwu */
1437
DO_SPE_OP2(srwu);
1438
/* evsubfw */
1439
DO_SPE_OP2(subfw);
1440

    
1441
/* evsel is a little bit more complicated... */
1442
static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1443
{
1444
    if (n)
1445
        return op1;
1446
    else
1447
        return op2;
1448
}
1449

    
1450
void do_evsel (void)
1451
{
1452
    T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1453
        (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
1454
}
1455

    
1456
/* Fixed-point vector comparisons */
1457
#define DO_SPE_CMP(name)                                                      \
1458
void do_ev##name (void)                                                       \
1459
{                                                                             \
1460
    T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32,                   \
1461
                                               T1_64 >> 32) << 32,            \
1462
                         _do_e##name(T0_64, T1_64));                          \
1463
}
1464

    
1465
static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
1466
{
1467
    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1468
}
1469
static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1470
{
1471
    return op1 == op2 ? 1 : 0;
1472
}
1473

    
1474
static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
1475
{
1476
    return op1 > op2 ? 1 : 0;
1477
}
1478

    
1479
static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
1480
{
1481
    return op1 > op2 ? 1 : 0;
1482
}
1483

    
1484
static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
1485
{
1486
    return op1 < op2 ? 1 : 0;
1487
}
1488

    
1489
static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
1490
{
1491
    return op1 < op2 ? 1 : 0;
1492
}
1493

    
1494
/* evcmpeq */
1495
DO_SPE_CMP(cmpeq);
1496
/* evcmpgts */
1497
DO_SPE_CMP(cmpgts);
1498
/* evcmpgtu */
1499
DO_SPE_CMP(cmpgtu);
1500
/* evcmplts */
1501
DO_SPE_CMP(cmplts);
1502
/* evcmpltu */
1503
DO_SPE_CMP(cmpltu);
1504

    
1505
/* Single precision floating-point conversions from/to integer */
1506
static always_inline uint32_t _do_efscfsi (int32_t val)
1507
{
1508
    union {
1509
        uint32_t u;
1510
        float32 f;
1511
    } u;
1512

    
1513
    u.f = int32_to_float32(val, &env->spe_status);
1514

    
1515
    return u.u;
1516
}
1517

    
1518
static always_inline uint32_t _do_efscfui (uint32_t val)
1519
{
1520
    union {
1521
        uint32_t u;
1522
        float32 f;
1523
    } u;
1524

    
1525
    u.f = uint32_to_float32(val, &env->spe_status);
1526

    
1527
    return u.u;
1528
}
1529

    
1530
static always_inline int32_t _do_efsctsi (uint32_t val)
1531
{
1532
    union {
1533
        int32_t u;
1534
        float32 f;
1535
    } u;
1536

    
1537
    u.u = val;
1538
    /* NaN are not treated the same way IEEE 754 does */
1539
    if (unlikely(isnan(u.f)))
1540
        return 0;
1541

    
1542
    return float32_to_int32(u.f, &env->spe_status);
1543
}
1544

    
1545
static always_inline uint32_t _do_efsctui (uint32_t val)
1546
{
1547
    union {
1548
        int32_t u;
1549
        float32 f;
1550
    } u;
1551

    
1552
    u.u = val;
1553
    /* NaN are not treated the same way IEEE 754 does */
1554
    if (unlikely(isnan(u.f)))
1555
        return 0;
1556

    
1557
    return float32_to_uint32(u.f, &env->spe_status);
1558
}
1559

    
1560
static always_inline int32_t _do_efsctsiz (uint32_t val)
1561
{
1562
    union {
1563
        int32_t u;
1564
        float32 f;
1565
    } u;
1566

    
1567
    u.u = val;
1568
    /* NaN are not treated the same way IEEE 754 does */
1569
    if (unlikely(isnan(u.f)))
1570
        return 0;
1571

    
1572
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1573
}
1574

    
1575
static always_inline uint32_t _do_efsctuiz (uint32_t val)
1576
{
1577
    union {
1578
        int32_t u;
1579
        float32 f;
1580
    } u;
1581

    
1582
    u.u = val;
1583
    /* NaN are not treated the same way IEEE 754 does */
1584
    if (unlikely(isnan(u.f)))
1585
        return 0;
1586

    
1587
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1588
}
1589

    
1590
void do_efscfsi (void)
1591
{
1592
    T0_64 = _do_efscfsi(T0_64);
1593
}
1594

    
1595
void do_efscfui (void)
1596
{
1597
    T0_64 = _do_efscfui(T0_64);
1598
}
1599

    
1600
void do_efsctsi (void)
1601
{
1602
    T0_64 = _do_efsctsi(T0_64);
1603
}
1604

    
1605
void do_efsctui (void)
1606
{
1607
    T0_64 = _do_efsctui(T0_64);
1608
}
1609

    
1610
void do_efsctsiz (void)
1611
{
1612
    T0_64 = _do_efsctsiz(T0_64);
1613
}
1614

    
1615
void do_efsctuiz (void)
1616
{
1617
    T0_64 = _do_efsctuiz(T0_64);
1618
}
1619

    
1620
/* Single precision floating-point conversion to/from fractional */
1621
static always_inline uint32_t _do_efscfsf (uint32_t val)
1622
{
1623
    union {
1624
        uint32_t u;
1625
        float32 f;
1626
    } u;
1627
    float32 tmp;
1628

    
1629
    u.f = int32_to_float32(val, &env->spe_status);
1630
    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
1631
    u.f = float32_div(u.f, tmp, &env->spe_status);
1632

    
1633
    return u.u;
1634
}
1635

    
1636
static always_inline uint32_t _do_efscfuf (uint32_t val)
1637
{
1638
    union {
1639
        uint32_t u;
1640
        float32 f;
1641
    } u;
1642
    float32 tmp;
1643

    
1644
    u.f = uint32_to_float32(val, &env->spe_status);
1645
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1646
    u.f = float32_div(u.f, tmp, &env->spe_status);
1647

    
1648
    return u.u;
1649
}
1650

    
1651
static always_inline int32_t _do_efsctsf (uint32_t val)
1652
{
1653
    union {
1654
        int32_t u;
1655
        float32 f;
1656
    } u;
1657
    float32 tmp;
1658

    
1659
    u.u = val;
1660
    /* NaN are not treated the same way IEEE 754 does */
1661
    if (unlikely(isnan(u.f)))
1662
        return 0;
1663
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1664
    u.f = float32_mul(u.f, tmp, &env->spe_status);
1665

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

    
1669
static always_inline uint32_t _do_efsctuf (uint32_t val)
1670
{
1671
    union {
1672
        int32_t u;
1673
        float32 f;
1674
    } u;
1675
    float32 tmp;
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
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1682
    u.f = float32_mul(u.f, tmp, &env->spe_status);
1683

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

    
1687
static always_inline int32_t _do_efsctsfz (uint32_t val)
1688
{
1689
    union {
1690
        int32_t u;
1691
        float32 f;
1692
    } u;
1693
    float32 tmp;
1694

    
1695
    u.u = val;
1696
    /* NaN are not treated the same way IEEE 754 does */
1697
    if (unlikely(isnan(u.f)))
1698
        return 0;
1699
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1700
    u.f = float32_mul(u.f, tmp, &env->spe_status);
1701

    
1702
    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
1703
}
1704

    
1705
static always_inline uint32_t _do_efsctufz (uint32_t val)
1706
{
1707
    union {
1708
        int32_t u;
1709
        float32 f;
1710
    } u;
1711
    float32 tmp;
1712

    
1713
    u.u = val;
1714
    /* NaN are not treated the same way IEEE 754 does */
1715
    if (unlikely(isnan(u.f)))
1716
        return 0;
1717
    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
1718
    u.f = float32_mul(u.f, tmp, &env->spe_status);
1719

    
1720
    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
1721
}
1722

    
1723
void do_efscfsf (void)
1724
{
1725
    T0_64 = _do_efscfsf(T0_64);
1726
}
1727

    
1728
void do_efscfuf (void)
1729
{
1730
    T0_64 = _do_efscfuf(T0_64);
1731
}
1732

    
1733
void do_efsctsf (void)
1734
{
1735
    T0_64 = _do_efsctsf(T0_64);
1736
}
1737

    
1738
void do_efsctuf (void)
1739
{
1740
    T0_64 = _do_efsctuf(T0_64);
1741
}
1742

    
1743
void do_efsctsfz (void)
1744
{
1745
    T0_64 = _do_efsctsfz(T0_64);
1746
}
1747

    
1748
void do_efsctufz (void)
1749
{
1750
    T0_64 = _do_efsctufz(T0_64);
1751
}
1752

    
1753
/* Double precision floating point helpers */
1754
static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
1755
{
1756
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1757
    return _do_efdtstlt(op1, op2);
1758
}
1759

    
1760
static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
1761
{
1762
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1763
    return _do_efdtstgt(op1, op2);
1764
}
1765

    
1766
static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
1767
{
1768
    /* XXX: TODO: test special values (NaN, infinites, ...) */
1769
    return _do_efdtsteq(op1, op2);
1770
}
1771

    
1772
void do_efdcmplt (void)
1773
{
1774
    T0 = _do_efdcmplt(T0_64, T1_64);
1775
}
1776

    
1777
void do_efdcmpgt (void)
1778
{
1779
    T0 = _do_efdcmpgt(T0_64, T1_64);
1780
}
1781

    
1782
void do_efdcmpeq (void)
1783
{
1784
    T0 = _do_efdcmpeq(T0_64, T1_64);
1785
}
1786

    
1787
/* Double precision floating-point conversion to/from integer */
1788
static always_inline uint64_t _do_efdcfsi (int64_t val)
1789
{
1790
    union {
1791
        uint64_t u;
1792
        float64 f;
1793
    } u;
1794

    
1795
    u.f = int64_to_float64(val, &env->spe_status);
1796

    
1797
    return u.u;
1798
}
1799

    
1800
static always_inline uint64_t _do_efdcfui (uint64_t val)
1801
{
1802
    union {
1803
        uint64_t u;
1804
        float64 f;
1805
    } u;
1806

    
1807
    u.f = uint64_to_float64(val, &env->spe_status);
1808

    
1809
    return u.u;
1810
}
1811

    
1812
static always_inline int64_t _do_efdctsi (uint64_t val)
1813
{
1814
    union {
1815
        int64_t u;
1816
        float64 f;
1817
    } u;
1818

    
1819
    u.u = val;
1820
    /* NaN are not treated the same way IEEE 754 does */
1821
    if (unlikely(isnan(u.f)))
1822
        return 0;
1823

    
1824
    return float64_to_int64(u.f, &env->spe_status);
1825
}
1826

    
1827
static always_inline uint64_t _do_efdctui (uint64_t val)
1828
{
1829
    union {
1830
        int64_t u;
1831
        float64 f;
1832
    } u;
1833

    
1834
    u.u = val;
1835
    /* NaN are not treated the same way IEEE 754 does */
1836
    if (unlikely(isnan(u.f)))
1837
        return 0;
1838

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

    
1842
static always_inline int64_t _do_efdctsiz (uint64_t val)
1843
{
1844
    union {
1845
        int64_t u;
1846
        float64 f;
1847
    } u;
1848

    
1849
    u.u = val;
1850
    /* NaN are not treated the same way IEEE 754 does */
1851
    if (unlikely(isnan(u.f)))
1852
        return 0;
1853

    
1854
    return float64_to_int64_round_to_zero(u.f, &env->spe_status);
1855
}
1856

    
1857
static always_inline uint64_t _do_efdctuiz (uint64_t val)
1858
{
1859
    union {
1860
        int64_t u;
1861
        float64 f;
1862
    } u;
1863

    
1864
    u.u = val;
1865
    /* NaN are not treated the same way IEEE 754 does */
1866
    if (unlikely(isnan(u.f)))
1867
        return 0;
1868

    
1869
    return float64_to_uint64_round_to_zero(u.f, &env->spe_status);
1870
}
1871

    
1872
void do_efdcfsi (void)
1873
{
1874
    T0_64 = _do_efdcfsi(T0_64);
1875
}
1876

    
1877
void do_efdcfui (void)
1878
{
1879
    T0_64 = _do_efdcfui(T0_64);
1880
}
1881

    
1882
void do_efdctsi (void)
1883
{
1884
    T0_64 = _do_efdctsi(T0_64);
1885
}
1886

    
1887
void do_efdctui (void)
1888
{
1889
    T0_64 = _do_efdctui(T0_64);
1890
}
1891

    
1892
void do_efdctsiz (void)
1893
{
1894
    T0_64 = _do_efdctsiz(T0_64);
1895
}
1896

    
1897
void do_efdctuiz (void)
1898
{
1899
    T0_64 = _do_efdctuiz(T0_64);
1900
}
1901

    
1902
/* Double precision floating-point conversion to/from fractional */
1903
static always_inline uint64_t _do_efdcfsf (int64_t val)
1904
{
1905
    union {
1906
        uint64_t u;
1907
        float64 f;
1908
    } u;
1909
    float64 tmp;
1910

    
1911
    u.f = int32_to_float64(val, &env->spe_status);
1912
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
1913
    u.f = float64_div(u.f, tmp, &env->spe_status);
1914

    
1915
    return u.u;
1916
}
1917

    
1918
static always_inline uint64_t _do_efdcfuf (uint64_t val)
1919
{
1920
    union {
1921
        uint64_t u;
1922
        float64 f;
1923
    } u;
1924
    float64 tmp;
1925

    
1926
    u.f = uint32_to_float64(val, &env->spe_status);
1927
    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
1928
    u.f = float64_div(u.f, tmp, &env->spe_status);
1929

    
1930
    return u.u;
1931
}
1932

    
1933
static always_inline int64_t _do_efdctsf (uint64_t val)
1934
{
1935
    union {
1936
        int64_t u;
1937
        float64 f;
1938
    } u;
1939
    float64 tmp;
1940

    
1941
    u.u = val;
1942
    /* NaN are not treated the same way IEEE 754 does */
1943
    if (unlikely(isnan(u.f)))
1944
        return 0;
1945
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
1946
    u.f = float64_mul(u.f, tmp, &env->spe_status);
1947

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

    
1951
static always_inline uint64_t _do_efdctuf (uint64_t val)
1952
{
1953
    union {
1954
        int64_t u;
1955
        float64 f;
1956
    } u;
1957
    float64 tmp;
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
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
1964
    u.f = float64_mul(u.f, tmp, &env->spe_status);
1965

    
1966
    return float64_to_uint32(u.f, &env->spe_status);
1967
}
1968

    
1969
static always_inline int64_t _do_efdctsfz (uint64_t val)
1970
{
1971
    union {
1972
        int64_t u;
1973
        float64 f;
1974
    } u;
1975
    float64 tmp;
1976

    
1977
    u.u = val;
1978
    /* NaN are not treated the same way IEEE 754 does */
1979
    if (unlikely(isnan(u.f)))
1980
        return 0;
1981
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
1982
    u.f = float64_mul(u.f, tmp, &env->spe_status);
1983

    
1984
    return float64_to_int32_round_to_zero(u.f, &env->spe_status);
1985
}
1986

    
1987
static always_inline uint64_t _do_efdctufz (uint64_t val)
1988
{
1989
    union {
1990
        int64_t u;
1991
        float64 f;
1992
    } u;
1993
    float64 tmp;
1994

    
1995
    u.u = val;
1996
    /* NaN are not treated the same way IEEE 754 does */
1997
    if (unlikely(isnan(u.f)))
1998
        return 0;
1999
    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2000
    u.f = float64_mul(u.f, tmp, &env->spe_status);
2001

    
2002
    return float64_to_uint32_round_to_zero(u.f, &env->spe_status);
2003
}
2004

    
2005
void do_efdcfsf (void)
2006
{
2007
    T0_64 = _do_efdcfsf(T0_64);
2008
}
2009

    
2010
void do_efdcfuf (void)
2011
{
2012
    T0_64 = _do_efdcfuf(T0_64);
2013
}
2014

    
2015
void do_efdctsf (void)
2016
{
2017
    T0_64 = _do_efdctsf(T0_64);
2018
}
2019

    
2020
void do_efdctuf (void)
2021
{
2022
    T0_64 = _do_efdctuf(T0_64);
2023
}
2024

    
2025
void do_efdctsfz (void)
2026
{
2027
    T0_64 = _do_efdctsfz(T0_64);
2028
}
2029

    
2030
void do_efdctufz (void)
2031
{
2032
    T0_64 = _do_efdctufz(T0_64);
2033
}
2034

    
2035
/* Floating point conversion between single and double precision */
2036
static always_inline uint32_t _do_efscfd (uint64_t val)
2037
{
2038
    union {
2039
        uint64_t u;
2040
        float64 f;
2041
    } u1;
2042
    union {
2043
        uint32_t u;
2044
        float32 f;
2045
    } u2;
2046

    
2047
    u1.u = val;
2048
    u2.f = float64_to_float32(u1.f, &env->spe_status);
2049

    
2050
    return u2.u;
2051
}
2052

    
2053
static always_inline uint64_t _do_efdcfs (uint32_t val)
2054
{
2055
    union {
2056
        uint64_t u;
2057
        float64 f;
2058
    } u2;
2059
    union {
2060
        uint32_t u;
2061
        float32 f;
2062
    } u1;
2063

    
2064
    u1.u = val;
2065
    u2.f = float32_to_float64(u1.f, &env->spe_status);
2066

    
2067
    return u2.u;
2068
}
2069

    
2070
void do_efscfd (void)
2071
{
2072
    T0_64 = _do_efscfd(T0_64);
2073
}
2074

    
2075
void do_efdcfs (void)
2076
{
2077
    T0_64 = _do_efdcfs(T0_64);
2078
}
2079

    
2080
/* Single precision fixed-point vector arithmetic */
2081
/* evfsabs */
2082
DO_SPE_OP1(fsabs);
2083
/* evfsnabs */
2084
DO_SPE_OP1(fsnabs);
2085
/* evfsneg */
2086
DO_SPE_OP1(fsneg);
2087
/* evfsadd */
2088
DO_SPE_OP2(fsadd);
2089
/* evfssub */
2090
DO_SPE_OP2(fssub);
2091
/* evfsmul */
2092
DO_SPE_OP2(fsmul);
2093
/* evfsdiv */
2094
DO_SPE_OP2(fsdiv);
2095

    
2096
/* Single-precision floating-point comparisons */
2097
static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2098
{
2099
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2100
    return _do_efststlt(op1, op2);
2101
}
2102

    
2103
static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2104
{
2105
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2106
    return _do_efststgt(op1, op2);
2107
}
2108

    
2109
static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
2110
{
2111
    /* XXX: TODO: test special values (NaN, infinites, ...) */
2112
    return _do_efststeq(op1, op2);
2113
}
2114

    
2115
void do_efscmplt (void)
2116
{
2117
    T0 = _do_efscmplt(T0_64, T1_64);
2118
}
2119

    
2120
void do_efscmpgt (void)
2121
{
2122
    T0 = _do_efscmpgt(T0_64, T1_64);
2123
}
2124

    
2125
void do_efscmpeq (void)
2126
{
2127
    T0 = _do_efscmpeq(T0_64, T1_64);
2128
}
2129

    
2130
/* Single-precision floating-point vector comparisons */
2131
/* evfscmplt */
2132
DO_SPE_CMP(fscmplt);
2133
/* evfscmpgt */
2134
DO_SPE_CMP(fscmpgt);
2135
/* evfscmpeq */
2136
DO_SPE_CMP(fscmpeq);
2137
/* evfststlt */
2138
DO_SPE_CMP(fststlt);
2139
/* evfststgt */
2140
DO_SPE_CMP(fststgt);
2141
/* evfststeq */
2142
DO_SPE_CMP(fststeq);
2143

    
2144
/* Single-precision floating-point vector conversions */
2145
/* evfscfsi */
2146
DO_SPE_OP1(fscfsi);
2147
/* evfscfui */
2148
DO_SPE_OP1(fscfui);
2149
/* evfscfuf */
2150
DO_SPE_OP1(fscfuf);
2151
/* evfscfsf */
2152
DO_SPE_OP1(fscfsf);
2153
/* evfsctsi */
2154
DO_SPE_OP1(fsctsi);
2155
/* evfsctui */
2156
DO_SPE_OP1(fsctui);
2157
/* evfsctsiz */
2158
DO_SPE_OP1(fsctsiz);
2159
/* evfsctuiz */
2160
DO_SPE_OP1(fsctuiz);
2161
/* evfsctsf */
2162
DO_SPE_OP1(fsctsf);
2163
/* evfsctuf */
2164
DO_SPE_OP1(fsctuf);
2165
#endif /* defined(TARGET_PPCEMB) */
2166

    
2167
/*****************************************************************************/
2168
/* Softmmu support */
2169
#if !defined (CONFIG_USER_ONLY)
2170

    
2171
#define MMUSUFFIX _mmu
2172
#define GETPC() (__builtin_return_address(0))
2173

    
2174
#define SHIFT 0
2175
#include "softmmu_template.h"
2176

    
2177
#define SHIFT 1
2178
#include "softmmu_template.h"
2179

    
2180
#define SHIFT 2
2181
#include "softmmu_template.h"
2182

    
2183
#define SHIFT 3
2184
#include "softmmu_template.h"
2185

    
2186
/* try to fill the TLB and return an exception if error. If retaddr is
2187
   NULL, it means that the function was called in C code (i.e. not
2188
   from generated code or from helper.c) */
2189
/* XXX: fix it to restore all registers */
2190
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2191
{
2192
    TranslationBlock *tb;
2193
    CPUState *saved_env;
2194
    target_phys_addr_t pc;
2195
    int ret;
2196

    
2197
    /* XXX: hack to restore env in all cases, even if not called from
2198
       generated code */
2199
    saved_env = env;
2200
    env = cpu_single_env;
2201
    ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2202
    if (unlikely(ret != 0)) {
2203
        if (likely(retaddr)) {
2204
            /* now we have a real cpu fault */
2205
            pc = (target_phys_addr_t)(unsigned long)retaddr;
2206
            tb = tb_find_pc(pc);
2207
            if (likely(tb)) {
2208
                /* the PC is inside the translated code. It means that we have
2209
                   a virtual CPU fault */
2210
                cpu_restore_state(tb, env, pc, NULL);
2211
            }
2212
        }
2213
        do_raise_exception_err(env->exception_index, env->error_code);
2214
    }
2215
    env = saved_env;
2216
}
2217

    
2218
/* Software driven TLBs management */
2219
/* PowerPC 602/603 software TLB load instructions helpers */
2220
void do_load_6xx_tlb (int is_code)
2221
{
2222
    target_ulong RPN, CMP, EPN;
2223
    int way;
2224

    
2225
    RPN = env->spr[SPR_RPA];
2226
    if (is_code) {
2227
        CMP = env->spr[SPR_ICMP];
2228
        EPN = env->spr[SPR_IMISS];
2229
    } else {
2230
        CMP = env->spr[SPR_DCMP];
2231
        EPN = env->spr[SPR_DMISS];
2232
    }
2233
    way = (env->spr[SPR_SRR1] >> 17) & 1;
2234
#if defined (DEBUG_SOFTWARE_TLB)
2235
    if (loglevel != 0) {
2236
        fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
2237
                __func__, (unsigned long)T0, (unsigned long)EPN,
2238
                (unsigned long)CMP, (unsigned long)RPN, way);
2239
    }
2240
#endif
2241
    /* Store this TLB */
2242
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2243
                     way, is_code, CMP, RPN);
2244
}
2245

    
2246
void do_load_74xx_tlb (int is_code)
2247
{
2248
    target_ulong RPN, CMP, EPN;
2249
    int way;
2250

    
2251
    RPN = env->spr[SPR_PTELO];
2252
    CMP = env->spr[SPR_PTEHI];
2253
    EPN = env->spr[SPR_TLBMISS] & ~0x3;
2254
    way = env->spr[SPR_TLBMISS] & 0x3;
2255
#if defined (DEBUG_SOFTWARE_TLB)
2256
    if (loglevel != 0) {
2257
        fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
2258
                __func__, (unsigned long)T0, (unsigned long)EPN,
2259
                (unsigned long)CMP, (unsigned long)RPN, way);
2260
    }
2261
#endif
2262
    /* Store this TLB */
2263
    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
2264
                     way, is_code, CMP, RPN);
2265
}
2266

    
2267
static target_ulong booke_tlb_to_page_size (int size)
2268
{
2269
    return 1024 << (2 * size);
2270
}
2271

    
2272
static int booke_page_size_to_tlb (target_ulong page_size)
2273
{
2274
    int size;
2275

    
2276
    switch (page_size) {
2277
    case 0x00000400UL:
2278
        size = 0x0;
2279
        break;
2280
    case 0x00001000UL:
2281
        size = 0x1;
2282
        break;
2283
    case 0x00004000UL:
2284
        size = 0x2;
2285
        break;
2286
    case 0x00010000UL:
2287
        size = 0x3;
2288
        break;
2289
    case 0x00040000UL:
2290
        size = 0x4;
2291
        break;
2292
    case 0x00100000UL:
2293
        size = 0x5;
2294
        break;
2295
    case 0x00400000UL:
2296
        size = 0x6;
2297
        break;
2298
    case 0x01000000UL:
2299
        size = 0x7;
2300
        break;
2301
    case 0x04000000UL:
2302
        size = 0x8;
2303
        break;
2304
    case 0x10000000UL:
2305
        size = 0x9;
2306
        break;
2307
    case 0x40000000UL:
2308
        size = 0xA;
2309
        break;
2310
#if defined (TARGET_PPC64)
2311
    case 0x000100000000ULL:
2312
        size = 0xB;
2313
        break;
2314
    case 0x000400000000ULL:
2315
        size = 0xC;
2316
        break;
2317
    case 0x001000000000ULL:
2318
        size = 0xD;
2319
        break;
2320
    case 0x004000000000ULL:
2321
        size = 0xE;
2322
        break;
2323
    case 0x010000000000ULL:
2324
        size = 0xF;
2325
        break;
2326
#endif
2327
    default:
2328
        size = -1;
2329
        break;
2330
    }
2331

    
2332
    return size;
2333
}
2334

    
2335
/* Helpers for 4xx TLB management */
2336
void do_4xx_tlbre_lo (void)
2337
{
2338
    ppcemb_tlb_t *tlb;
2339
    int size;
2340

    
2341
    T0 &= 0x3F;
2342
    tlb = &env->tlb[T0].tlbe;
2343
    T0 = tlb->EPN;
2344
    if (tlb->prot & PAGE_VALID)
2345
        T0 |= 0x400;
2346
    size = booke_page_size_to_tlb(tlb->size);
2347
    if (size < 0 || size > 0x7)
2348
        size = 1;
2349
    T0 |= size << 7;
2350
    env->spr[SPR_40x_PID] = tlb->PID;
2351
}
2352

    
2353
void do_4xx_tlbre_hi (void)
2354
{
2355
    ppcemb_tlb_t *tlb;
2356

    
2357
    T0 &= 0x3F;
2358
    tlb = &env->tlb[T0].tlbe;
2359
    T0 = tlb->RPN;
2360
    if (tlb->prot & PAGE_EXEC)
2361
        T0 |= 0x200;
2362
    if (tlb->prot & PAGE_WRITE)
2363
        T0 |= 0x100;
2364
}
2365

    
2366
void do_4xx_tlbwe_hi (void)
2367
{
2368
    ppcemb_tlb_t *tlb;
2369
    target_ulong page, end;
2370

    
2371
#if defined (DEBUG_SOFTWARE_TLB)
2372
    if (loglevel != 0) {
2373
        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2374
    }
2375
#endif
2376
    T0 &= 0x3F;
2377
    tlb = &env->tlb[T0].tlbe;
2378
    /* Invalidate previous TLB (if it's valid) */
2379
    if (tlb->prot & PAGE_VALID) {
2380
        end = tlb->EPN + tlb->size;
2381
#if defined (DEBUG_SOFTWARE_TLB)
2382
        if (loglevel != 0) {
2383
            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
2384
                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2385
        }
2386
#endif
2387
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2388
            tlb_flush_page(env, page);
2389
    }
2390
    tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
2391
    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2392
     * If this ever occurs, one should use the ppcemb target instead
2393
     * of the ppc or ppc64 one
2394
     */
2395
    if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
2396
        cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2397
                  "are not supported (%d)\n",
2398
                  tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
2399
    }
2400
    tlb->EPN = T1 & ~(tlb->size - 1);
2401
    if (T1 & 0x40)
2402
        tlb->prot |= PAGE_VALID;
2403
    else
2404
        tlb->prot &= ~PAGE_VALID;
2405
    if (T1 & 0x20) {
2406
        /* XXX: TO BE FIXED */
2407
        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
2408
    }
2409
    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2410
    tlb->attr = T1 & 0xFF;
2411
#if defined (DEBUG_SOFTWARE_TLB)
2412
    if (loglevel != 0) {
2413
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2414
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2415
                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2416
                tlb->prot & PAGE_READ ? 'r' : '-',
2417
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2418
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2419
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2420
    }
2421
#endif
2422
    /* Invalidate new TLB (if valid) */
2423
    if (tlb->prot & PAGE_VALID) {
2424
        end = tlb->EPN + tlb->size;
2425
#if defined (DEBUG_SOFTWARE_TLB)
2426
        if (loglevel != 0) {
2427
            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
2428
                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
2429
        }
2430
#endif
2431
        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2432
            tlb_flush_page(env, page);
2433
    }
2434
}
2435

    
2436
void do_4xx_tlbwe_lo (void)
2437
{
2438
    ppcemb_tlb_t *tlb;
2439

    
2440
#if defined (DEBUG_SOFTWARE_TLB)
2441
    if (loglevel != 0) {
2442
        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
2443
    }
2444
#endif
2445
    T0 &= 0x3F;
2446
    tlb = &env->tlb[T0].tlbe;
2447
    tlb->RPN = T1 & 0xFFFFFC00;
2448
    tlb->prot = PAGE_READ;
2449
    if (T1 & 0x200)
2450
        tlb->prot |= PAGE_EXEC;
2451
    if (T1 & 0x100)
2452
        tlb->prot |= PAGE_WRITE;
2453
#if defined (DEBUG_SOFTWARE_TLB)
2454
    if (loglevel != 0) {
2455
        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2456
                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2457
                (int)T0, tlb->RPN, tlb->EPN, tlb->size,
2458
                tlb->prot & PAGE_READ ? 'r' : '-',
2459
                tlb->prot & PAGE_WRITE ? 'w' : '-',
2460
                tlb->prot & PAGE_EXEC ? 'x' : '-',
2461
                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2462
    }
2463
#endif
2464
}
2465

    
2466
/* PowerPC 440 TLB management */
2467
void do_440_tlbwe (int word)
2468
{
2469
    ppcemb_tlb_t *tlb;
2470
    target_ulong EPN, RPN, size;
2471
    int do_flush_tlbs;
2472

    
2473
#if defined (DEBUG_SOFTWARE_TLB)
2474
    if (loglevel != 0) {
2475
        fprintf(logfile, "%s word %d T0 " REGX " T1 " REGX "\n",
2476
                __func__, word, T0, T1);
2477
    }
2478
#endif
2479
    do_flush_tlbs = 0;
2480
    T0 &= 0x3F;
2481
    tlb = &env->tlb[T0].tlbe;
2482
    switch (word) {
2483
    default:
2484
        /* Just here to please gcc */
2485
    case 0:
2486
        EPN = T1 & 0xFFFFFC00;
2487
        if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2488
            do_flush_tlbs = 1;
2489
        tlb->EPN = EPN;
2490
        size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
2491
        if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2492
            do_flush_tlbs = 1;
2493
        tlb->size = size;
2494
        tlb->attr &= ~0x1;
2495
        tlb->attr |= (T1 >> 8) & 1;
2496
        if (T1 & 0x200) {
2497
            tlb->prot |= PAGE_VALID;
2498
        } else {
2499
            if (tlb->prot & PAGE_VALID) {
2500
                tlb->prot &= ~PAGE_VALID;
2501
                do_flush_tlbs = 1;
2502
            }
2503
        }
2504
        tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2505
        if (do_flush_tlbs)
2506
            tlb_flush(env, 1);
2507
        break;
2508
    case 1:
2509
        RPN = T1 & 0xFFFFFC0F;
2510
        if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN)
2511
            tlb_flush(env, 1);
2512
        tlb->RPN = RPN;
2513
        break;
2514
    case 2:
2515
        tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
2516
        tlb->prot = tlb->prot & PAGE_VALID;
2517
        if (T1 & 0x1)
2518
            tlb->prot |= PAGE_READ << 4;
2519
        if (T1 & 0x2)
2520
            tlb->prot |= PAGE_WRITE << 4;
2521
        if (T1 & 0x4)
2522
            tlb->prot |= PAGE_EXEC << 4;
2523
        if (T1 & 0x8)
2524
            tlb->prot |= PAGE_READ;
2525
        if (T1 & 0x10)
2526
            tlb->prot |= PAGE_WRITE;
2527
        if (T1 & 0x20)
2528
            tlb->prot |= PAGE_EXEC;
2529
        break;
2530
    }
2531
}
2532

    
2533
void do_440_tlbre (int word)
2534
{
2535
    ppcemb_tlb_t *tlb;
2536
    int size;
2537

    
2538
    T0 &= 0x3F;
2539
    tlb = &env->tlb[T0].tlbe;
2540
    switch (word) {
2541
    default:
2542
        /* Just here to please gcc */
2543
    case 0:
2544
        T0 = tlb->EPN;
2545
        size = booke_page_size_to_tlb(tlb->size);
2546
        if (size < 0 || size > 0xF)
2547
            size = 1;
2548
        T0 |= size << 4;
2549
        if (tlb->attr & 0x1)
2550
            T0 |= 0x100;
2551
        if (tlb->prot & PAGE_VALID)
2552
            T0 |= 0x200;
2553
        env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2554
        env->spr[SPR_440_MMUCR] |= tlb->PID;
2555
        break;
2556
    case 1:
2557
        T0 = tlb->RPN;
2558
        break;
2559
    case 2:
2560
        T0 = tlb->attr & ~0x1;
2561
        if (tlb->prot & (PAGE_READ << 4))
2562
            T0 |= 0x1;
2563
        if (tlb->prot & (PAGE_WRITE << 4))
2564
            T0 |= 0x2;
2565
        if (tlb->prot & (PAGE_EXEC << 4))
2566
            T0 |= 0x4;
2567
        if (tlb->prot & PAGE_READ)
2568
            T0 |= 0x8;
2569
        if (tlb->prot & PAGE_WRITE)
2570
            T0 |= 0x10;
2571
        if (tlb->prot & PAGE_EXEC)
2572
            T0 |= 0x20;
2573
        break;
2574
    }
2575
}
2576
#endif /* !CONFIG_USER_ONLY */